Commit 5e6fac22 authored by Oliver Wiese's avatar Oliver Wiese

Merge branch 'dev'

Conflicts:
	enzevalos_iphone.xcodeproj/project.pbxproj
	enzevalos_iphoneTests/GeneratedMocks.swift
parents 78020e1a bbd7c77b
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -26,8 +26,17 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A13526741D955BDF00D3BFE1"
BuildableName = "enzevalos_iphone.app"
BlueprintName = "enzevalos_iphone"
ReferencedContainer = "container:enzevalos_iphone.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
......@@ -39,9 +48,39 @@
ReferencedContainer = "container:enzevalos_iphone.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "CryptoTests/testfindNotSignedMailForPublicKey()">
</Test>
<Test
Identifier = "GamificationDataUnitTest">
</Test>
<Test
Identifier = "MailServerConfigurationTest">
</Test>
<Test
Identifier = "MailTest/testK9SecureInlineMail()">
</Test>
<Test
Identifier = "MailTest/testK9SecureMail()">
</Test>
<Test
Identifier = "MailTest/testK9SigedInlineMail()">
</Test>
<Test
Identifier = "MailTest/testK9SigedMail()">
</Test>
<Test
Identifier = "MailTest/testMacSecureMail()">
</Test>
<Test
Identifier = "MailTest/testMacSigedMail()">
</Test>
<Test
Identifier = "MailTest/testThunderbirdSigedInlineMail()">
</Test>
<Test
Identifier = "MailTest/testThunderbirdSigedMail()">
</Test>
</SkippedTests>
</TestableReference>
<TestableReference
......@@ -55,17 +94,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A13526741D955BDF00D3BFE1"
BuildableName = "enzevalos_iphone.app"
BlueprintName = "enzevalos_iphone"
ReferencedContainer = "container:enzevalos_iphone.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
......@@ -88,8 +116,6 @@
ReferencedContainer = "container:enzevalos_iphone.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
......
//
// CHelpers.swift
// enzevalos_iphone
//
// Created by lazarog98 on 10.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import Foundation
/**
Creates an arraz of C Strings from an array of swift strings
Always call deallocateCStrArr after using this!
*/
func createCStrArr(sarr: [String]) -> UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?{
let len = sarr.count
let carr = init_str_arr(Int32(len))
for i in 0..<len
{
let str = sarr[i]
add_str_to_arr(str,carr,Int32(i))
}
return carr
}
/**
Deallocates an array of c strings
*/
func deallocateCStrArr(arr: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?, len: Int){
return deallocate_str_arr(arr, Int32(len))
}
//
// Certificate.swift
// enzevalos_iphone
//
// Created by lazarog98 on 18.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import Foundation
/**
Contains information about a certificate
*/
class Certificate {
let pem: String // raw PEM string
let fingerPrint: String
let eMails: [String]?
let issuer: String?
let hasPrivateKey: Bool
let subject: String?
let startDate: String?
let endDate: String?
init(pem: String) {
let cCertInfo = get_cert_data(pem)
defer {
deallocateCertInfo(certInfo: cCertInfo)
}
let certInfo = cCertInfo?.pointee
self.hasPrivateKey = pem.contains("PRIVATE KEY")
let (fingerPrint, _, errors) = getFingerprintFromPem(pem: pem)
// if it crashes on this line, you can loop through the errors and see what's wrong
self.fingerPrint = fingerPrint!
self.pem = pem
self.eMails = certInfo?.extractField(field: CertInfoString.emails)
self.endDate = certInfo?.extractField(field: CertInfoString.endDate)
self.startDate = certInfo?.extractField(field: CertInfoString.startDate)
self.subject = certInfo?.extractField(field: CertInfoString.subject)
self.issuer = certInfo?.extractField(field: CertInfoString.issuer)
}
}
/**
An enum used in the extractString() method of cert_info
*/
enum CertInfoString {
case issuer;
case subject;
case startDate;
case endDate;
case emails;
}
/**
extensions to the C struct so that memory deallocation is automatic
*/
extension cert_info {
/**
Extracts an array of certs in PEM of the respective function from the result object
Deallocates the "errors" part of the result object
Only use in combination with_extractOutput and _extractErrors
*/
private func extractEmails() -> [String]? {
let arr = self.emails
var strArr: [String]? = nil
if arr != nil {
strArr = []
let size = self.num_emails
//print("Size:",size)
for i in 0..<size {
let str = String(cString: arr![Int(i)]!)
strArr?.append(str)
// (arr![Int(i)])!.deallocate()
}
// arr?.deallocate()
}
return strArr
}
/**
Extracts the output of the respective function from the result object
Deallocates the "res" part of the result object
Only use in combination with_extractErrors
- parameters:
- field: the result object
*/
private func extractString(field: CertInfoString) -> String? {
let cStr: UnsafeMutablePointer<Int8>?
switch field {
case .endDate:
cStr = self.date_end
case .startDate:
cStr = self.date_start
case .issuer:
cStr = self.issuer
case .subject:
cStr = self.subject
default:
return nil
}
var swiftStr: String? = nil
if cStr != nil {
swiftStr = String(cString: cStr!)
}
return swiftStr
}
/**
A generic function that reads a field and casts it to the type of the variable that stores the result. The variable must therefore have the correct type
- parameters:
- field: enum, specifiying the field to extract
*/
func extractField<T>(field: CertInfoString) -> T? {
switch field {
case .emails:
let emails = self.extractEmails()
if emails is T? {
return emails as! T?
}
default:
let res = self.extractString(field: field)
if res is T? {
return res as! T?
}
}
return nil
}
}
......@@ -55,12 +55,15 @@ enum EncryptionState: Int16 {
public enum CryptoScheme {
case PGP
case SMIME
case UNKNOWN
var description: String {
switch self {
case .PGP:
return "PGP"
case .SMIME:
return "SMIME"
default:
return ""
}
......@@ -78,6 +81,8 @@ public enum CryptoScheme {
switch self {
case CryptoScheme.PGP:
return 0
case CryptoScheme.SMIME:
return 1
case CryptoScheme.UNKNOWN:
return 99
}
......@@ -91,6 +96,7 @@ public class CryptoObject {
let signatureState: SignatureState
var encryptionState: EncryptionState
let signKey: String?
let signedKeys: [String]
let encType: CryptoScheme
let passcode: String?
let signedAdrs: [String]
......@@ -109,7 +115,6 @@ public class CryptoObject {
return nil
}
init(chiphertext: Data?, plaintext: String?, decryptedData: Data?, sigState: SignatureState, encState: EncryptionState, signKey: String?, encType: CryptoScheme, signedAdrs: [String]) {
self.chiphertext = chiphertext
self.plaintext = plaintext
......@@ -120,5 +125,25 @@ public class CryptoObject {
self.encType = encType
self.passcode = nil
self.signedAdrs = signedAdrs
if signKey != nil
{
self.signedKeys = [signKey!]
}
else{
self.signedKeys = []
}
}
init(chiphertext: Data?, plaintext: String?, decryptedData: Data?, sigState: SignatureState, encState: EncryptionState, signKey: String?, encType: CryptoScheme, signedAdrs: [String], signedKeys: [String]) {
self.chiphertext = chiphertext
self.plaintext = plaintext
self.decryptedData = decryptedData
self.signatureState = sigState
self.encryptionState = encState
self.signKey = signKey
self.encType = encType
self.passcode = nil
self.signedAdrs = signedAdrs
self.signedKeys = signedKeys
}
}
......@@ -1119,19 +1119,17 @@ class DataHandler {
return []
}
/**
Filters all Presistent Mails with encState == EncryptionState.UnableToDecrypt
*/
func getAllNotDecryptedPersistentMail() -> [PersistentMail] {
let result = getAllPersistentMails().filter({ $0.encState == EncryptionState.UnableToDecrypt })
return result
}
// filter all presistent mails without public key
func getAllNoPublicKeyPersistentMail() -> [PersistentMail] {
let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey })
return result
}
/**
Filters all Presistent Mails with sigState == SignatureState.NoPublicKey
*/
func getAllNotSignedPersistentMail() -> [PersistentMail] {
let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey })
return result
......
This diff is collapsed.
//
// MailComparison.swift
// enzevalos_iphone
//
// Created by Katharina Müller and Viktoria Sorgalla on 04.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import Foundation
import CoreData
private let datahandler = DataHandler.handler
public enum ResultCompareSenderToContacts {
case isContact, isSender, OnlyIdentity, Unknown
}
extension String {
/**
compares the given mail address to the persistant mails and returns the number of matches
***/
private func countMatches(_ mailAddr: String, _ inboxMails: [PersistentMail]) -> Int {
var senders: [String] = []
for sender in inboxMails{
let sender: String = sender.from.mailAddress
senders.append(sender)
}
var numberOfFoundMatches = 0
for addr in senders{
if addr == mailAddr{
numberOfFoundMatches += 1
}
}
return numberOfFoundMatches
}
/**
returns a mail address, wich has the same identity as the given one but a different domain
***/
private func getIdentityWithDifferentDomain(_ mailAdd: String, inboxMails: [PersistentMail]) -> String{
let senderIdentity = mailAdd.getLocalMailIdentity()
var senderDomain = mailAdd.splitAddress()
senderDomain.removeFirst()
var senders: [String] = []
for sender in inboxMails{
let sender: String = sender.from.mailAddress
senders.append(sender)
}
var foundMatch = ""
for addr in senders{
let foundIdentity = addr.getLocalMailIdentity()
var foundDomain = addr.splitAddress()
foundDomain.removeFirst()
if senderIdentity == foundIdentity && senderDomain != foundDomain{
foundMatch = addr
return foundMatch
}
}
return foundMatch
}
/**
looks if the mail address of the sender is already known
***/
public func compareSenderToContacts() -> ResultCompareSenderToContacts {
// Case 1: Is the address of the sender known through previous mails?
let inboxMails = datahandler.getAllPersistentMails()
if countMatches(self, inboxMails) >= 2{
return ResultCompareSenderToContacts.isSender
}
// Case 2: Is the address of the sender in the address book?
let enzContacts = datahandler.getContacts()
for contact in enzContacts {
let contMailAddr = contact.cnContact?.getMailAddresses()
if contMailAddr != nil{
for mAddr in contMailAddr!{
if mAddr.mailAddress == self {
return ResultCompareSenderToContacts.isContact
}
}
}
}
// Case 3: The identity of an mail address is known, but not the (sub-)domain
let foundIdentity = getIdentityWithDifferentDomain(self, inboxMails: inboxMails)
if foundIdentity != ""{
return ResultCompareSenderToContacts.OnlyIdentity
}
return ResultCompareSenderToContacts.Unknown
}
}
This diff is collapsed.
//
// SMIMEHelpers.swift
// enzevalos_iphone
//
// Created by lazarog98 on 19.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import Foundation
class SMIMEError : Error {
enum ErrorType {
case fingerPrint
case encryption
case decryption
case verification
case signing
case other
}
func errorArrayToString() -> [String] {
var strArr: [String] = []
for error in self.errorArray ?? [] {
strArr.append(getErrorString(errCode: error))
}
return strArr
}
let message: String?
let errorArray: [UInt]?
let type: ErrorType
init(message: String?, errorArray: [UInt]?, type: ErrorType) {
self.message = message
self.errorArray = errorArray
self.type = type
}
}
/**
Returns a fingerprint hash of a certificate given a PEM
- parameters:
- pem: cerificate's PEM as a string
- returns:a tuple of the form (fingerprint, nil, array of errors)
*/
func getFingerprintFromPem (pem: String) -> (String?, [String]?, [UInt]?) {
let res = get_fingerprint_from_pem(pem, 0);
defer {
deallocateResult(res: res)
}
let result = res?.pointee;
let fpStr: String? = result?.extractField(field: ResultAttribute.output)
let errArr: [UInt]? = result?.extractField(field: ResultAttribute.errors)
return (fpStr, nil, errArr)
}
/**
Exrtracts a private key from an ecnrypted PEM
- parameters:
- pem: key's PEM as a string
- passwd: password to decrypt the PEM
- returns:(<decrypted PEM>, <array of errors>)
*/
func getPKeyFromEncryptedPem(pem: String, passwd: String) -> (String?, [UInt]?) {
let res = get_pkey_from_enc_pem(pem, passwd)
defer {
deallocateResult(res: res)
}
let result = res?.pointee
let pKey: String? = result?.extractField(field: ResultAttribute.output)
let errArr: [UInt]? = result?.extractField(field: ResultAttribute.errors)
return (pKey, errArr)
}
/**
Encrypts a private key's PEM with a password (encryption key)
- parameters:
- pem: key's PEM as a string
- passwd: password for the encryption
- returns:(<encrypted PEM>, <array of errors>)
*/
func getEncryptedPemFromPKey(pem: String, passwd: String) -> (String?, [UInt]?) {
let res = get_enc_pem_from_pkey(pem, passwd)
defer {
deallocateResult(res: res)
}
let result = res?.pointee
let pKey: String? = result?.extractField(field: ResultAttribute.output)
let errArr: [UInt]? = result?.extractField(field: ResultAttribute.errors)
return (pKey, errArr)
}
/**
Returns the complete string of an OpenSSL error. Includes things such as reason, function that caused it and so on
- parameters;
- errCode: the error code
*/
func getErrorString(errCode: UInt) -> String {
let cStr = get_err_string(errCode);
defer {
cStr?.deallocate()
}
if (cStr != nil) {
let str = String( cString: cStr!)
return str;
}
return "Invalid error code!"
}
/**
Returns the reason part of the string of an OpenSSL error.
- parameters;
- errCode: the error code
*/
func getErrorReasonString(errCode: UInt) -> String {
let cStr = get_err_reason_string(errCode);
defer {
cStr?.deallocate()
}
if (cStr != nil) {
let str = String( cString: cStr!)
return str;
}
return "Invalid error code!"
}
/**
Returns the list of all e-mails from an array of certificates. Each email has only one instance in the array.
- parameters:
- certs: an array of PEMs
- returns:an array of emails
*/
func getAllEmailsFromPEMs(certs: [String]) -> [String] {
let certObjects = certs.map( { (arg) -> Certificate in
return Certificate(pem: arg)
})
var addrs : [String:Bool] = [:]
for c in certObjects
{
for e in c.eMails!
{
addrs[e] = true
}
}
return Array(addrs.keys)
}
func deallocateResult(res: UnsafeMutablePointer<result>?) {
deallocate_result(res)
}
func deallocateCertInfo(certInfo: UnsafeMutablePointer<cert_info>?) {
deallocate_cert_info(certInfo)
}
enum ResultAttribute {
case certificates
case errors
case output
case fingerprints
}
/**
A structure returned by the C crypto functions
This is not intended to be used outside of the SMIME library for letterbox. Look at the encryption/decryption functions for example usages
*/
extension result {
/**
Extracts an array of certs in PEM of the respective function from the result object
Deallocates the "errors" part of the result object
Only use in combination with_extractOutput and _extractErrors
*/
private func extractStringArray(attrType: ResultAttribute) -> [String]? {
let arr: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?
switch (attrType) {
case .certificates:
arr = self.certs
case .fingerprints:
arr = self.fingerprints
default:
// TODO: Exceptions
return nil
}
var strArr: [String]? =