Restore internal `*Secret` interfaces (#130)

In a prior PR, an internal interface was exposed to work-around a problem wherein cross-module type casts would fail in an app using this SDK, so we changed the build settings such that modules that expose types which may subject to casts are built as dynamic, and not static, libraries, and then restored the internal interface
This commit is contained in:
Stephen Higgins 2022-08-18 10:44:47 +01:00 коммит произвёл GitHub
Родитель a66f103ff6
Коммит e8910d1a0a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 46 добавлений и 25 удалений

Просмотреть файл

@ -641,7 +641,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCCrypto;
PRODUCT_NAME = VCCrypto;
SKIP_INSTALL = YES;
@ -672,7 +672,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCCrypto;
PRODUCT_NAME = VCCrypto;
SKIP_INSTALL = YES;

Просмотреть файл

@ -9,6 +9,7 @@ import CommonCrypto
enum AesError : Error {
case keyWrapError
case keyUnwrapError
case invalidSecret
case cryptoError(operation:CCOperation, status:CCCryptorStatus)
}
@ -24,8 +25,11 @@ public struct Aes {
public func wrap(key: VCCryptoSecret, with kek: VCCryptoSecret) throws -> Data {
// Look for an early out
guard key is Secret, kek is Secret else {
throw AesError.invalidSecret
}
var wrappedSize: Int = 0
try key.withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
try (key as! Secret).withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
let keySize = keyPtr.bindMemory(to: UInt8.self).count
wrappedSize = CCSymmetricWrappedSize(keyWrapAlg, keySize)
}
@ -33,10 +37,10 @@ public struct Aes {
try wrapped.withUnsafeMutableBytes({ (wrappedPtr: UnsafeMutableRawBufferPointer) in
let wrappedBytes = wrappedPtr.bindMemory(to: UInt8.self)
try key.withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
try (key as! Secret).withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
let keyBytes = keyPtr.bindMemory(to: UInt8.self)
try kek.withUnsafeBytes { (kekPtr: UnsafeRawBufferPointer) in
try (kek as! Secret).withUnsafeBytes { (kekPtr: UnsafeRawBufferPointer) in
let kekBytes = kekPtr.bindMemory(to: UInt8.self)
let status = CCSymmetricKeyWrap(keyWrapAlg,
CCrfc3394_iv,
@ -58,6 +62,11 @@ public struct Aes {
public func unwrap(wrapped: Data, using kek: VCCryptoSecret) throws -> VCCryptoSecret {
// Look for an early out
guard kek is Secret else {
throw AesError.invalidSecret
}
var unwrappedSize = CCSymmetricUnwrappedSize(keyWrapAlg, wrapped.count)
var unwrapped = Data(repeating: 0, count: unwrappedSize)
defer {
@ -73,7 +82,7 @@ public struct Aes {
try wrapped.withUnsafeBytes { (wrappedPtr: UnsafeRawBufferPointer) in
let wrappedBytes = wrappedPtr.bindMemory(to: UInt8.self)
try kek.withUnsafeBytes { (kekPtr: UnsafeRawBufferPointer) in
try (kek as! Secret).withUnsafeBytes { (kekPtr: UnsafeRawBufferPointer) in
let kekBytes = kekPtr.bindMemory(to: UInt8.self)
let status = CCSymmetricKeyUnwrap(keyWrapAlg,
CCrfc3394_iv,
@ -106,6 +115,9 @@ public struct Aes {
private func apply(operation: CCOperation, withOptions options: CCOptions, to data: Data, using key: VCCryptoSecret, iv: Data) throws -> Data {
// Look for an early out
guard key is Secret else { throw AesError.invalidSecret }
// Allocate the output buffer
var outputSize = size_t(data.count)
let modulo = data.count % blockSize
@ -114,7 +126,7 @@ public struct Aes {
}
var output = [UInt8](repeating: 0, count: outputSize)
try key.withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
try (key as! Secret).withUnsafeBytes { (keyPtr: UnsafeRawBufferPointer) in
let keyBytes = keyPtr.bindMemory(to: UInt8.self)
try iv.withUnsafeBytes { (ivPtr: UnsafeRawBufferPointer) in

Просмотреть файл

@ -8,6 +8,7 @@ import CommonCrypto
enum HmacSha2Error: Error {
case invalidMessage
case invalidSecret
case invalidAlgorithm
}
@ -39,6 +40,7 @@ public struct HmacSha2 {
// Look for an early out
guard message.count > 0 else { throw HmacSha2Error.invalidMessage }
guard secret is Secret else { throw HmacSha2Error.invalidSecret }
// Apply
let ccHmacAlg = self.algorithm
@ -46,7 +48,7 @@ public struct HmacSha2 {
try message.withUnsafeBytes { (messagePtr: UnsafeRawBufferPointer) in
let messageBytes = messagePtr.bindMemory(to: UInt8.self)
try secret.withUnsafeBytes { (secretPtr: UnsafeRawBufferPointer) in
try (secret as! Secret).withUnsafeBytes { (secretPtr: UnsafeRawBufferPointer) in
let secretBytes = secretPtr.bindMemory(to: UInt8.self)
CCHmac(ccHmacAlg, secretBytes.baseAddress, secretBytes.count, messageBytes.baseAddress, messageBytes.count, &mac)

Просмотреть файл

@ -13,6 +13,7 @@ enum Secp256k1Error: Error {
case invalidSignature
case invalidPublicKey
case publicKeyCreationFailure
case invalidSecret
}
public struct Secp256k1: Signing {
@ -27,6 +28,7 @@ public struct Secp256k1: Signing {
public func sign(messageHash: Data, withSecret secret: VCCryptoSecret) throws -> Data {
// Validate params
guard secret is Secret else { throw Secp256k1Error.invalidSecret }
guard messageHash.count == 32 else { throw Secp256k1Error.invalidMessageHash }
// Create the context and signature data structure
@ -40,7 +42,7 @@ public struct Secp256k1: Signing {
}
// Sign the message
try secret.withUnsafeBytes { (secretPtr) in
try (secret as! Secret).withUnsafeBytes { (secretPtr) in
guard secp256k1_ec_seckey_verify(context!, secretPtr.bindMemory(to: UInt8.self).baseAddress.unsafelyUnwrapped) > 0 else { throw Secp256k1Error.invalidSecretKey }
try messageHash.withUnsafeBytes { (msgPtr) in
@ -133,6 +135,9 @@ public struct Secp256k1: Signing {
/// - Returns: The key pair
public func createKeyPair(forSecret secret: VCCryptoSecret) throws -> (EphemeralSecret, Secp256k1PublicKey)
{
// Validate params
guard secret is Secret else { throw Secp256k1Error.invalidSecret }
// Get out the private key data
let privateKey = try EphemeralSecret(with: secret)
@ -143,7 +148,7 @@ public struct Secp256k1: Signing {
/// Create a public key from a private key
/// - Parameter secret: The Secret used to generate the public key
/// - Returns: The public key
public func createPublicKey(forPrivateKey privateKey:EphemeralSecret) throws -> Secp256k1PublicKey {
public func createPublicKey(forPrivateKey privateKey: EphemeralSecret) throws -> Secp256k1PublicKey {
// Create the context and public key data structure
let context = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN))!

Просмотреть файл

@ -45,10 +45,12 @@ public final class EphemeralSecret: Secret {
public init(with secret: VCCryptoSecret) throws
{
value = Data()
try secret.withUnsafeBytes { secretPtr in
if let baseAddress = secretPtr.baseAddress, secretPtr.count > 0 {
let bytes = baseAddress.assumingMemoryBound(to: UInt8.self)
value.append(bytes, count: secretPtr.count)
if let internalSecret = secret as? Secret {
try internalSecret.withUnsafeBytes { secretPtr in
if let baseAddress = secretPtr.baseAddress, secretPtr.count > 0 {
let bytes = baseAddress.assumingMemoryBound(to: UInt8.self)
value.append(bytes, count: secretPtr.count)
}
}
}
self.id = secret.id

Просмотреть файл

@ -18,13 +18,13 @@ public protocol VCCryptoSecret {
func isValidKey() throws
func migrateKey(fromAccessGroup currentAccessGroup: String?) throws
/// Invokes the closure passed as a param with a buffer pointer to the raw bytes of the secret.
func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> Void) throws
}
protocol InternalSecret {
/// Invokes the closure passed as a param with a buffer pointer to the raw bytes of the secret.
func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> Void) throws
/// The 4 characters representing the secret type in the store. This correspond to kSecAttrType in keychain
static var itemTypeCode: String { get }
}

Просмотреть файл

@ -35,7 +35,7 @@ class AesTests: XCTestCase {
let result = try fixture.unwrap(wrapped: wrapped, using: kek)
var data = Data()
try result.withUnsafeBytes{ resultPtr in
try (result as! Secret).withUnsafeBytes{ resultPtr in
data.append(resultPtr.bindMemory(to: UInt8.self))
}
XCTAssertEqual(data, cek.value)

Просмотреть файл

@ -24,7 +24,7 @@ class PbkdfTests : XCTestCase {
// Validate
var data = Data()
try derived.withUnsafeBytes { (derivedPtr) in
try (derived as! Secret).withUnsafeBytes { (derivedPtr) in
data.append(derivedPtr.bindMemory(to: UInt8.self))
}
XCTAssertEqual(Data(expected), data)

Просмотреть файл

@ -1202,7 +1202,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCEntities;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
@ -1232,7 +1232,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCEntities;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;

Просмотреть файл

@ -863,7 +863,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCNetworking;
PRODUCT_NAME = VCNetworking;
SKIP_INSTALL = YES;
@ -893,7 +893,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCNetworking;
PRODUCT_NAME = VCNetworking;
SKIP_INSTALL = YES;

Просмотреть файл

@ -488,7 +488,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCToken;
PRODUCT_NAME = VCToken;
SKIP_INSTALL = YES;
@ -516,7 +516,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MACH_O_TYPE = staticlib;
MACH_O_TYPE = mh_dylib;
PRODUCT_BUNDLE_IDENTIFIER = com.microsoft.VCToken;
PRODUCT_NAME = VCToken;
SKIP_INSTALL = YES;