|
|
@@ -39,28 +39,65 @@ public struct CCM: BlockMode {
|
|
|
return CBCModeWorker(blockSize: blockSize, iv: iv.slice, cipherOperation: cipherOperation)
|
|
|
}
|
|
|
|
|
|
+// // Apply the formatting function to (N, A, P) to produce blocks [B0, ..., Br]
|
|
|
+// private func format(N: [UInt8], A: [UInt8], P: [UInt8]) throws -> [UInt8] {
|
|
|
+// let block0 = try format(nonce: N, Q: 512, q: 3, t: 12, hasAssociatedData: false) // mock
|
|
|
+// let ctr1 = try format(counter: 1, nonce: N, q: 3)
|
|
|
+// return block0 + ctr1
|
|
|
+// }
|
|
|
|
|
|
- // Apply the formatting function to (N, A, P) to produce blocks [B0, ..., Br]
|
|
|
- private func format(N: [UInt8], A: [UInt8], P: [UInt8]) throws -> [UInt8] {
|
|
|
- let block0 = try formatNonce(N: N, Q: 512, q: 3, t: 12, hasAssociatedData: false) // mock
|
|
|
- return []
|
|
|
+}
|
|
|
+
|
|
|
+struct CCMModeWorker: BlockModeWorker {
|
|
|
+ let cipherOperation: CipherOperationOnBlock
|
|
|
+ var blockSize: Int
|
|
|
+ let additionalBufferSize: Int = 0
|
|
|
+ private let iv: ArraySlice<UInt8>
|
|
|
+ private var prev: ArraySlice<UInt8>?
|
|
|
+
|
|
|
+ public enum Error: Swift.Error {
|
|
|
+ case invalidParameter
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
|
|
+ self.blockSize = blockSize
|
|
|
+ self.iv = iv
|
|
|
+ self.cipherOperation = cipherOperation
|
|
|
+ }
|
|
|
+
|
|
|
+ mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
|
|
+ guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
|
|
|
+ return Array(plaintext)
|
|
|
+ }
|
|
|
+ prev = ciphertext.slice
|
|
|
+ return ciphertext
|
|
|
+ }
|
|
|
+
|
|
|
+ mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
|
|
+ guard let plaintext = cipherOperation(ciphertext) else {
|
|
|
+ return Array(ciphertext)
|
|
|
+ }
|
|
|
+ let result: Array<UInt8> = xor(prev ?? iv, plaintext)
|
|
|
+ prev = ciphertext
|
|
|
+ return result
|
|
|
}
|
|
|
|
|
|
// Q - octet length of P
|
|
|
// q - octet length of Q. Maximum length (in octets) of payload. An element of {2,3,4,5,6,7,8}
|
|
|
// t - octet length of T (MAC length). An element of {4,6,8,10,12,14,16}
|
|
|
- private func formatNonce(N: [UInt8], Q: UInt32, q: UInt8, t: UInt8, hasAssociatedData: Bool) throws -> [UInt8] {
|
|
|
+ private func format(nonce N: [UInt8], Q: UInt32, q: UInt8, t: UInt8, hasAssociatedData: Bool) throws -> [UInt8] {
|
|
|
var flags0: UInt8 = 0
|
|
|
|
|
|
if hasAssociatedData {
|
|
|
- // 6 bit
|
|
|
+ // 7 bit
|
|
|
flags0 |= (1 << 6)
|
|
|
}
|
|
|
|
|
|
- // 5,4,3 is t in 3 bits
|
|
|
+ // 6,5,4 bit is t in 3 bits
|
|
|
flags0 |= (((t-2)/2) & 0x07) << 3
|
|
|
|
|
|
- // 2,1,0 is q in 3 bits
|
|
|
+ // 3,2,1 bit is q in 3 bits
|
|
|
flags0 |= ((q-1) & 0x07) << 0
|
|
|
|
|
|
var block0: [UInt8] = Array<UInt8>(repeating: 0, count: 16) // block[0]
|
|
|
@@ -80,35 +117,34 @@ public struct CCM: BlockMode {
|
|
|
|
|
|
return block0
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-struct CCMModeWorker: BlockModeWorker {
|
|
|
- let cipherOperation: CipherOperationOnBlock
|
|
|
- var blockSize: Int
|
|
|
- let additionalBufferSize: Int = 0
|
|
|
- private let iv: ArraySlice<UInt8>
|
|
|
- private var prev: ArraySlice<UInt8>?
|
|
|
+ /// Formatting of the Counter Blocks. Ctr[i]
|
|
|
+ /// The counter generation function.
|
|
|
+ /// Q - octet length of P
|
|
|
+ /// q - octet length of Q. Maximum length (in octets) of payload. An element of {2,3,4,5,6,7,8}
|
|
|
+ private func format(counter i: Int, nonce N: [UInt8], q: UInt8) throws -> [UInt8] {
|
|
|
+ var flags0: UInt8 = 0
|
|
|
|
|
|
- init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
|
|
- self.blockSize = blockSize
|
|
|
- self.iv = iv
|
|
|
- self.cipherOperation = cipherOperation
|
|
|
- }
|
|
|
+ // bit 8,7 is Reserved
|
|
|
+ // bit 4,5,6 shall be set to 0
|
|
|
+ // 3,2,1 bit is q in 3 bits
|
|
|
+ flags0 |= ((q-1) & 0x07) << 0
|
|
|
|
|
|
- mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
|
|
- guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
|
|
|
- return Array(plaintext)
|
|
|
- }
|
|
|
- prev = ciphertext.slice
|
|
|
- return ciphertext
|
|
|
- }
|
|
|
+ var block = Array<UInt8>(repeating: 0, count: 16) // block[0]
|
|
|
+ block[0] = flags0
|
|
|
|
|
|
- mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
|
|
- guard let plaintext = cipherOperation(ciphertext) else {
|
|
|
- return Array(ciphertext)
|
|
|
+ // N in 1...(15-q) octets, n = 15-q
|
|
|
+ // n is an element of {7,8,9,10,11,12,13}
|
|
|
+ let n = 15-Int(q)
|
|
|
+ guard (n + Int(q)) == 15 else {
|
|
|
+ // n+q == 15
|
|
|
+ throw Error.invalidParameter
|
|
|
}
|
|
|
- let result: Array<UInt8> = xor(prev ?? iv, plaintext)
|
|
|
- prev = ciphertext
|
|
|
- return result
|
|
|
+ block[1...n] = N[0...(n-1)]
|
|
|
+
|
|
|
+ // [i]8q in (16-q)...15 octets
|
|
|
+ block[(16-Int(q))...15] = i.bytes(totalBytes: Int(q)).slice
|
|
|
+
|
|
|
+ return block
|
|
|
}
|
|
|
}
|