Skip to content

Commit

Permalink
fix: aes wrapper pre 15
Browse files Browse the repository at this point in the history
  • Loading branch information
beatt83 committed Jun 6, 2024
1 parent 2da6279 commit 28dc857
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 13 deletions.
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import PackageDescription
let package = Package(
name: "jose-swift",
platforms: [
.iOS(.v14),
.iOS(.v15),
.macOS(.v12),
.macCatalyst(.v14),
.tvOS(.v12),
.macCatalyst(.v15),
.tvOS(.v15),
.watchOS(.v5)
],
products: [
Expand Down
3 changes: 3 additions & 0 deletions Sources/JSONWebAlgorithms/CryptoError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import CommonCrypto
import Foundation

/// `CryptoError` is an enumeration representing various errors that can occur in cryptographic operations.
Expand Down Expand Up @@ -79,4 +80,6 @@ public enum CryptoError: LocalizedError {
case cannotGenerateKeyForTypeAndCurve(type: String, curve: String?)

case keyFormatNotSupported(format: String, supportedFormats: [String])

case commonCryptoError(status: CCStatus)
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ struct AESKeyUnwrap: KeyUnwrapping {
guard let key = using.key else {
throw CryptoError.missingOctetSequenceKey
}

return try AES.KeyWrap.unwrap(
encryptedKey,
using: .init(data: key)
).withUnsafeBytes { Data($0) }

if #available(iOS 15.0, macOS 12.0, watchOS 8.0, tvOS 15.0, *) {
return try AES.KeyWrap.unwrap(
encryptedKey,
using: .init(data: key)
).withUnsafeBytes { Data($0) }
} else {
return try AESKeyWrapperCommonCrypto().unwrap(key: encryptedKey, encryptionKey: key)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,15 @@ struct AESKeyWrap: KeyWrapping {
throw CryptoError.notValidPrivateKey
}

let encryptedKey = try AES.KeyWrap.wrap(
.init(data: cek),
using: .init(data: key)
)
let encryptedKey: Data
if #available(iOS 15.0, macOS 12.0, watchOS 8.0, tvOS 15.0, *) {
encryptedKey = try AES.KeyWrap.wrap(
.init(data: cek),
using: .init(data: key)
)
} else {
encryptedKey = try AESKeyWrapperCommonCrypto().wrap(key: cek, encryptionKey: key)
}

return .init(
encryptedKey: encryptedKey,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2024 Gonçalo Frade
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import CommonCrypto
import Foundation

class AESKeyWrapperCommonCrypto {
private let algorithm: CCWrappingAlgorithm = UInt32(kCCWRAPAES)

func wrap(key: Data, encryptionKey: Data) throws -> Data {
let outputSize = CCSymmetricWrappedSize(algorithm, key.count)
var buffer = Data(count: outputSize)
var wrappedKeyLength = outputSize

let result = buffer.write(withPointerTo: encryptionKey, key) { bufferPtr, ptrs in
CCSymmetricKeyWrap(self.algorithm,
CCrfc3394_iv,
CCrfc3394_ivLen,
ptrs[0],
encryptionKey.count,
ptrs[1],
key.count,
bufferPtr,
&wrappedKeyLength)
}

if result != kCCSuccess {
throw CryptoError.commonCryptoError(status: result)
}

return buffer.prefix(upTo: wrappedKeyLength)
}

func unwrap(key: Data, encryptionKey: Data) throws -> Data {
let outputSize = CCSymmetricUnwrappedSize(algorithm, key.count)
var buffer = Data(count: outputSize)
var unwrappedKeyLength = outputSize

let result = buffer.write(withPointerTo: encryptionKey, key) { bufferPtr, ptrs in
CCSymmetricKeyUnwrap(self.algorithm,
CCrfc3394_iv,
CCrfc3394_ivLen,
ptrs[0],
encryptionKey.count,
ptrs[1],
key.count,
bufferPtr,
&unwrappedKeyLength)
}

if result != kCCSuccess {
throw CryptoError.commonCryptoError(status: result)
}

return buffer.prefix(upTo: unwrappedKeyLength)
}
}

fileprivate extension Data {
func write<T>(withPointerTo args: Data..., body: (UnsafeMutablePointer<UInt8>, [UnsafePointer<UInt8>]) -> T) -> T {
return self.withUnsafeBytes { bufferRawPtr -> T in
let bufferPtr = bufferRawPtr.bindMemory(to: UInt8.self).baseAddress!
var ptrs: [UnsafePointer<UInt8>] = []
for arg in args {
arg.withUnsafeBytes { argRawPtr in
let argPtr = argRawPtr.bindMemory(to: UInt8.self).baseAddress!
ptrs.append(argPtr)
}
}
return bufferPtr.withMemoryRebound(to: UInt8.self, capacity: count) { reboundBufferPtr in
body(UnsafeMutablePointer(mutating: reboundBufferPtr), ptrs)
}
}
}
}
2 changes: 1 addition & 1 deletion Tests/JWSTests/Mocks/JWK+Testing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extension JWK {
static var testingES256PairSecKey: SecKey {
let p256Data = P256.Signing.PrivateKey().x963Representation
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECDSA,
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits as String: 256
]
Expand Down

0 comments on commit 28dc857

Please sign in to comment.