@@ -20,6 +20,13 @@ struct MasterkeyJson: Codable {
2020 let version : Int
2121}
2222
23+ enum MasterkeyError : Error , Equatable {
24+ case malformedMasterkeyFile( _ reason: String )
25+ case invalidPassword
26+ case unwrapFailed( _ status: CCCryptorStatus )
27+ case wrapFailed( _ status: CCCryptorStatus )
28+ }
29+
2330public class Masterkey {
2431
2532 private( set) var aesMasterKey : [ UInt8 ]
@@ -42,85 +49,70 @@ public class Masterkey {
4249 // MARK: -
4350 // MARK: Masterkey Factory Methods
4451
45- public static func createFromMasterkeyFile( file: URL , password: String , pepper: [ UInt8 ] = [ UInt8] ( ) ) -> Masterkey ? {
46- if let jsonData = try ? Data ( contentsOf: file) {
47- return createFromMasterkeyFile ( jsonData: jsonData, password: password)
48- } else {
49- return nil
50- }
52+ public static func createFromMasterkeyFile( file: URL , password: String , pepper: [ UInt8 ] = [ UInt8] ( ) ) throws -> Masterkey {
53+ let jsonData = try Data ( contentsOf: file)
54+ return try createFromMasterkeyFile ( jsonData: jsonData, password: password)
55+
5156 }
5257
53- public static func createFromMasterkeyFile( jsonData: Data , password: String , pepper: [ UInt8 ] = [ UInt8] ( ) ) -> Masterkey ? {
58+ public static func createFromMasterkeyFile( jsonData: Data , password: String , pepper: [ UInt8 ] = [ UInt8] ( ) ) throws -> Masterkey {
5459 let jsonDecoder = JSONDecoder ( )
55- if let decoded = try ? jsonDecoder. decode ( MasterkeyJson . self, from: jsonData) {
56- return createFromMasterkeyFile ( jsonData: decoded, password: password, pepper: pepper) ;
57- } else {
58- return nil
59- }
60+ let decoded = try jsonDecoder. decode ( MasterkeyJson . self, from: jsonData)
61+ return try createFromMasterkeyFile ( jsonData: decoded, password: password, pepper: pepper) ;
6062 }
6163
62- static func createFromMasterkeyFile( jsonData: MasterkeyJson , password: String , pepper: [ UInt8 ] ) -> Masterkey ? {
64+ static func createFromMasterkeyFile( jsonData: MasterkeyJson , password: String , pepper: [ UInt8 ] ) throws -> Masterkey {
6365 let pw = [ UInt8] ( password. precomposedStringWithCanonicalMapping. utf8)
6466 let salt = [ UInt8] ( Data ( base64Encoded: jsonData. scryptSalt) !)
6567 let saltAndPepper = salt + pepper
66- guard let kek = try ? Scrypt ( password: pw, salt: saltAndPepper, dkLen: kCCKeySizeAES256, N: jsonData. scryptCostParam, r: jsonData. scryptBlockSize, p: 1 ) . calculate ( ) else {
67- debugPrint ( " scrypt failed " )
68- return nil ;
69- }
70-
71- let wrappedMasterKey = [ UInt8] ( Data ( base64Encoded: jsonData. primaryMasterKey) !)
72- let unwrappedMasterKey = unwrapMasterKey ( wrappedKey: wrappedMasterKey, kek: kek)
68+ let kek = try Scrypt ( password: pw, salt: saltAndPepper, dkLen: kCCKeySizeAES256, N: jsonData. scryptCostParam, r: jsonData. scryptBlockSize, p: 1 ) . calculate ( )
7369
74- let wrappedHmacKey = [ UInt8] ( Data ( base64Encoded: jsonData. hmacMasterKey) !)
75- let unwrappedHmacKey = unwrapMasterKey ( wrappedKey: wrappedHmacKey, kek: kek)
70+ guard let wrappedMasterKey = Data ( base64Encoded: jsonData. primaryMasterKey) else {
71+ throw MasterkeyError . malformedMasterkeyFile ( " invalid base64 data in primaryMasterKey " )
72+ }
73+ let aesKey = try unwrapMasterKey ( wrappedKey: wrappedMasterKey. bytes, kek: kek)
7674
77- if ( unwrappedMasterKey != nil ) && ( unwrappedHmacKey != nil ) {
78- return createFromRaw ( aesMasterKey: unwrappedMasterKey!, macMasterKey: unwrappedHmacKey!)
79- } else {
80- return nil
75+ guard let wrappedHmacKey = Data ( base64Encoded: jsonData. hmacMasterKey) else {
76+ throw MasterkeyError . malformedMasterkeyFile ( " invalid base64 data in hmacMasterKey " )
8177 }
78+ let macKey = try unwrapMasterKey ( wrappedKey: wrappedHmacKey. bytes, kek: kek)
79+
80+ return createFromRaw ( aesMasterKey: aesKey, macMasterKey: macKey)
8281 }
8382
8483 internal static func createFromRaw( aesMasterKey: [ UInt8 ] , macMasterKey: [ UInt8 ] ) -> Masterkey {
85- // TODO CMAC implementation doesn't support 256 bit keys yet -.-
86- // assert(aesMasterKey.count == kCCKeySizeAES256)
87- // assert(macMasterKey.count == kCCKeySizeAES256)
84+ assert ( aesMasterKey. count == kCCKeySizeAES256)
85+ assert ( macMasterKey. count == kCCKeySizeAES256)
8886 return Masterkey ( aesMasterKey: aesMasterKey, macMasterKey: macMasterKey)
8987 }
9088
9189 // MARK: -
9290 // MARK: RFC 3394 Key Wrapping
9391
94- static func wrapMasterKey( rawKey: [ UInt8 ] , kek: [ UInt8 ] ) -> [ UInt8 ] ? {
92+ static func wrapMasterKey( rawKey: [ UInt8 ] , kek: [ UInt8 ] ) throws -> [ UInt8 ] {
9593 assert ( kek. count == kCCKeySizeAES256)
9694 var wrapepdKeyLen = CCSymmetricWrappedSize ( CCWrappingAlgorithm ( kCCWRAPAES) , rawKey. count)
9795 var wrapepdKey = [ UInt8] ( repeating: 0x00 , count: wrapepdKeyLen) ;
9896 let status = CCSymmetricKeyWrap ( CCWrappingAlgorithm ( kCCWRAPAES) , CCrfc3394_iv, CCrfc3394_ivLen, kek, kek. count, rawKey, rawKey. count, & wrapepdKey, & wrapepdKeyLen)
9997 if status == kCCSuccess {
10098 return wrapepdKey
101- } else if status == kCCParamError {
102- // wrong password
103- return nil
10499 } else {
105- debugPrint ( " unwrapping masterkey failed with status code " , status)
106- return nil
100+ throw MasterkeyError . wrapFailed ( status)
107101 }
108102 }
109103
110- static func unwrapMasterKey( wrappedKey: [ UInt8 ] , kek: [ UInt8 ] ) -> [ UInt8 ] ? {
104+ static func unwrapMasterKey( wrappedKey: [ UInt8 ] , kek: [ UInt8 ] ) throws -> [ UInt8 ] {
111105 assert ( kek. count == kCCKeySizeAES256)
112106 var unwrapepdKeyLen = CCSymmetricUnwrappedSize ( CCWrappingAlgorithm ( kCCWRAPAES) , wrappedKey. count)
113107 var unwrapepdKey = [ UInt8] ( repeating: 0x00 , count: unwrapepdKeyLen) ;
114108 let status = CCSymmetricKeyUnwrap ( CCWrappingAlgorithm ( kCCWRAPAES) , CCrfc3394_iv, CCrfc3394_ivLen, kek, kek. count, wrappedKey, wrappedKey. count, & unwrapepdKey, & unwrapepdKeyLen)
115109 if status == kCCSuccess {
116110 assert ( unwrapepdKeyLen == kCCKeySizeAES256)
117111 return unwrapepdKey
118- } else if status == kCCParamError {
119- // wrong password
120- return nil
112+ } else if status == kCCDecodeError {
113+ throw MasterkeyError . invalidPassword
121114 } else {
122- debugPrint ( " unwrapping masterkey failed with status code " , status)
123- return nil
115+ throw MasterkeyError . unwrapFailed ( status)
124116 }
125117 }
126118
0 commit comments