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:
Родитель
a66f103ff6
Коммит
e8910d1a0a
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче