Skip to content

Commit cc3709d

Browse files
committed
Using GCM Nonce pattern for CBC, CFB, and CTR
1 parent 3570357 commit cc3709d

File tree

6 files changed

+392
-123
lines changed

6 files changed

+392
-123
lines changed

Sources/_CryptoExtras/AES/AES_CBC.swift

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extension AES {
2020
/// suite.
2121
public enum _CBC {
2222
private static var blockSize: Int { 16 }
23+
static let nonceByteCount = 16
2324

2425
private static func encryptBlockInPlace(
2526
_ plaintext: inout Block,
@@ -67,7 +68,7 @@ extension AES {
6768
var ciphertext = Data()
6869
ciphertext.reserveCapacity(plaintext.count + Self.blockSize) // Room for padding.
6970

70-
var previousBlock = Block(iv)
71+
var previousBlock = Block(blockBytes: iv)
7172
var plaintext = plaintext[...]
7273

7374
while plaintext.count > 0 {
@@ -121,7 +122,7 @@ extension AES {
121122
var plaintext = Data()
122123
plaintext.reserveCapacity(ciphertext.count)
123124

124-
var previousBlock = Block(iv)
125+
var previousBlock = Block(blockBytes: iv)
125126
var ciphertext = ciphertext[...]
126127

127128
while ciphertext.count > 0 {
@@ -141,57 +142,6 @@ extension AES {
141142
}
142143
}
143144

144-
extension AES._CBC {
145-
/// An initialization vector.
146-
public struct IV: Sendable {
147-
// AES CBC uses a 128-bit IV.
148-
var ivBytes: (
149-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
150-
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8
151-
)
152-
153-
public init() {
154-
var rng = SystemRandomNumberGenerator()
155-
let (first, second) = (rng.next(), rng.next())
156-
157-
self.ivBytes = (
158-
UInt8(truncatingIfNeeded: first),
159-
UInt8(truncatingIfNeeded: first >> 8),
160-
UInt8(truncatingIfNeeded: first >> 16),
161-
UInt8(truncatingIfNeeded: first >> 24),
162-
UInt8(truncatingIfNeeded: first >> 32),
163-
UInt8(truncatingIfNeeded: first >> 40),
164-
UInt8(truncatingIfNeeded: first >> 48),
165-
UInt8(truncatingIfNeeded: first >> 56),
166-
UInt8(truncatingIfNeeded: second),
167-
UInt8(truncatingIfNeeded: second >> 8),
168-
UInt8(truncatingIfNeeded: second >> 16),
169-
UInt8(truncatingIfNeeded: second >> 24),
170-
UInt8(truncatingIfNeeded: second >> 32),
171-
UInt8(truncatingIfNeeded: second >> 40),
172-
UInt8(truncatingIfNeeded: second >> 48),
173-
UInt8(truncatingIfNeeded: second >> 56)
174-
)
175-
}
176-
177-
public init<IVBytes: Collection>(ivBytes: IVBytes) throws where IVBytes.Element == UInt8 {
178-
// We support a 128-bit IV.
179-
guard ivBytes.count == 16 else {
180-
throw CryptoKitError.incorrectKeySize
181-
}
182-
183-
self.ivBytes = (
184-
0, 0, 0, 0, 0, 0, 0, 0,
185-
0, 0, 0, 0, 0, 0, 0, 0
186-
)
187-
188-
withUnsafeMutableBytes(of: &self.ivBytes) { bytesPtr in
189-
bytesPtr.copyBytes(from: ivBytes)
190-
}
191-
}
192-
}
193-
}
194-
195145
extension Data {
196146
fileprivate mutating func trimPadding() throws {
197147
guard let paddingBytes = self.last else {

Sources/_CryptoExtras/AES/AES_CFB.swift

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ typealias AESCFBImpl = OpenSSLAESCFBImpl
2020

2121
extension AES {
2222
public enum _CFB {
23+
static let nonceByteCount = 16
24+
2325
@inlinable
2426
public static func encrypt<Plaintext: DataProtocol>(
2527
_ plaintext: Plaintext,
@@ -41,31 +43,3 @@ extension AES {
4143
}
4244
}
4345
}
44-
45-
extension AES._CFB {
46-
public struct IV: Sendable {
47-
// AES CFB uses a 128-bit IV.
48-
private var ivBytes: (UInt64, UInt64)
49-
50-
public init() {
51-
var rng = SystemRandomNumberGenerator()
52-
self.ivBytes = (rng.next(), rng.next())
53-
}
54-
55-
public init<IVBytes: Collection>(ivBytes: IVBytes) throws where IVBytes.Element == UInt8 {
56-
guard ivBytes.count == 16 else {
57-
throw CryptoKitError.incorrectParameterSize
58-
}
59-
60-
self.ivBytes = (0, 0)
61-
62-
Swift.withUnsafeMutableBytes(of: &self.ivBytes) { bytesPtr in
63-
bytesPtr.copyBytes(from: ivBytes)
64-
}
65-
}
66-
67-
mutating func withUnsafeMutableBytes<ReturnType>(_ body: (UnsafeMutableRawBufferPointer) throws -> ReturnType) rethrows -> ReturnType {
68-
return try Swift.withUnsafeMutableBytes(of: &self.ivBytes, body)
69-
}
70-
}
71-
}

Sources/_CryptoExtras/AES/AES_CTR.swift

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import Foundation
1919
typealias AESCTRImpl = OpenSSLAESCTRImpl
2020

2121
extension AES {
22-
2322
public enum _CTR {
23+
static let nonceByteCount = 12
24+
2425
@inlinable
2526
public static func encrypt<Plaintext: DataProtocol>(
2627
_ plaintext: Plaintext,
@@ -42,41 +43,3 @@ extension AES {
4243
}
4344
}
4445
}
45-
46-
extension AES._CTR {
47-
public struct Nonce: Sendable {
48-
// AES CTR uses a 128-bit counter. It's most usual to use a 96-bit nonce
49-
// and a 32-bit counter at the end, so we support that specific mode of
50-
// operation here.
51-
private var nonceBytes: (
52-
UInt64, UInt32, UInt32
53-
)
54-
55-
public init() {
56-
var rng = SystemRandomNumberGenerator()
57-
self.nonceBytes = (
58-
rng.next(), rng.next(), rng.next()
59-
)
60-
}
61-
62-
public init<NonceBytes: Collection>(nonceBytes: NonceBytes) throws where NonceBytes.Element == UInt8 {
63-
// We support a 96-bit nonce (with a 32-bit counter, initialized to 0) or a full 128-bit
64-
// expression.
65-
guard nonceBytes.count == 12 || nonceBytes.count == 16 else {
66-
throw CryptoKitError.incorrectParameterSize
67-
}
68-
69-
self.nonceBytes = (
70-
0, 0, 0
71-
)
72-
73-
Swift.withUnsafeMutableBytes(of: &self.nonceBytes) { bytesPtr in
74-
bytesPtr.copyBytes(from: nonceBytes)
75-
}
76-
}
77-
78-
mutating func withUnsafeMutableBytes<ReturnType>(_ body: (UnsafeMutableRawBufferPointer) throws -> ReturnType) rethrows -> ReturnType {
79-
return try Swift.withUnsafeMutableBytes(of: &self.nonceBytes, body)
80-
}
81-
}
82-
}

Sources/_CryptoExtras/AES/Block Function.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,10 @@ extension AES {
131131
init(_ blockBytes: BlockBytes) {
132132
self.blockBytes = blockBytes
133133
}
134-
135-
init(_ iv: AES._CBC.IV) {
136-
self.blockBytes = iv.ivBytes
134+
135+
init<BlockBytes: Sequence>(blockBytes: BlockBytes) where BlockBytes.Element == UInt8 {
136+
let blockBytes: [UInt8] = Array(blockBytes)
137+
self.init(blockBytes: blockBytes)
137138
}
138139

139140
init<BlockBytes: Collection>(blockBytes: BlockBytes) where BlockBytes.Element == UInt8 {

0 commit comments

Comments
 (0)