#include <security_utilities/casts.h>
#include <CommonCrypto/CommonKeyDerivation.h>
+#include <CoreFoundation/CFPriv.h>
+// 'verify' macro is somehow dragged in from CFPriv.h and breaks compilation of signclient.h, so undef it, we don't need it.
+#undef verify
+
#include "SecBridge.h"
#include <security_keychain/Access.h>
key->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
key->key->initializeWithSecKeyRef(key);
key->credentialType = kSecCredentialTypeDefault;
+ key->cdsaKeyMutex = new Mutex();
return errSecSuccess;
}
// If we hold the keychain's mutex (the key's 'mutexForObject') during this destruction, pthread gets upset.
// Hold a reference to the keychain (if it exists) until after we release the keychain's mutex.
+ StMaybeLock<Mutex> cdsaMutex(keyRef->cdsaKeyMutex);
+
KeyItem *keyItem = keyRef->key;
+
if (keyItem == NULL) {
// KeyImpl::attachSecKeyRef disconnected us from KeyItem instance, there is nothing to do for us.
+ cdsaMutex.unlock();
+ delete keyRef->cdsaKeyMutex;
return;
}
Keychain kc = keyItem->keychain();
+ // We have a +1 reference to the KeyItem now; no need to protect our storage any more
+ cdsaMutex.unlock();
+
{
StMaybeLock<Mutex> _(keyItem->getMutexForObject());
keyItem = keyRef->key;
delete keyItem;
}
+ delete keyRef->cdsaKeyMutex;
+
(void) kc; // Tell the compiler we're actually using this variable. At destruction time, it'll release the keychain.
}
#pragma clang diagnostic pop
static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) {
- CFErrorRef *error;
+ CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(SecKeyRef, NULL)
result = NULL;
}
static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) {
- CFErrorRef *error;
+ CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(Boolean, false)
result = key1->key->equal(*key2->key);
.copyOperationResult = SecCDSAKeyCopyOperationResult,
.isEqual = SecCDSAKeyIsEqual,
.setParameter = SecCDSAKeySetParameter,
+
+ .extraBytes = (sizeof(struct OpaqueSecKeyRef) > sizeof(struct __SecKey) ? (sizeof(struct OpaqueSecKeyRef) - sizeof(struct __SecKey)) : 0),
};
namespace Security {
if (key->cdsaKey == NULL) {
// Create CDSA key from exported data of existing key.
- CFRef<CFDataRef> keyData = SecKeyCopyExternalRepresentation(key, NULL);
CFRef<CFDictionaryRef> keyAttributes = SecKeyCopyAttributes(key);
- if (keyData && keyAttributes) {
- key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL);
+ if (keyAttributes) {
+ CFRef<CFDataRef> keyData = SecKeyCopyExternalRepresentation(key, NULL);
+ if (!keyData) {
+ CFTypeRef pubKeyHash = CFDictionaryGetValue(keyAttributes, kSecAttrApplicationLabel);
+ const void *keys[] = { kSecClass, kSecAttrNoLegacy, kSecReturnRef, kSecMatchLimit };
+ const void *values[] = { kSecClassIdentity, kCFBooleanFalse, kCFBooleanTrue, kSecMatchLimitAll };
+ CFRef<CFDictionaryRef> query = CFDictionaryCreate(kCFAllocatorDefault, keys, values,
+ sizeof(keys) / sizeof(*keys),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFRef<CFArrayRef> identities;
+ OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)identities.take());
+ if (status == errSecSuccess) {
+ for (int i = 0; i < CFArrayGetCount(identities); ++i) {
+ CFRef<SecKeyRef> privateKey;
+ if (SecIdentityCopyPrivateKey((SecIdentityRef)CFArrayGetValueAtIndex(identities, i), privateKey.take()) != errSecSuccess) {
+ continue;
+ }
+ CFRef<CFDictionaryRef> attrs = SecKeyCopyAttributes(privateKey);
+ if (CFEqual(CFDictionaryGetValue(attrs, kSecAttrApplicationLabel), pubKeyHash)) {
+ key->cdsaKey = privateKey.retain();
+ break;
+ }
+ }
+ }
+ } else {
+ key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL);
+ }
}
}
//
static ModuleNexus<Mutex> gSecReturnedKeyCSPsMutex;
-static std::set<CssmClient::CSP> gSecReturnedKeyCSPs;
+static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeyCSPs;
OSStatus
SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle)
CssmClient::CSP returnedKeyCSP = keyItem->csp();
{
StLock<Mutex> _(gSecReturnedKeyCSPsMutex());
- gSecReturnedKeyCSPs.insert(returnedKeyCSP);
+ gSecReturnedKeyCSPs().insert(returnedKeyCSP);
}
Required(cspHandle) = returnedKeyCSP->handle();
Required(publicKey);
Required(privateKey);
- CFTypeRef tokenID = GetAttributeFromParams(parameters, kSecAttrTokenID, NULL);
- CFTypeRef noLegacy = GetAttributeFromParams(parameters, kSecAttrNoLegacy, NULL);
- CFTypeRef sync = GetAttributeFromParams(parameters, kSecAttrSynchronizable, kSecPrivateKeyAttrs);
- CFTypeRef accessControl = GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPrivateKeyAttrs) ?:
- GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPublicKeyAttrs);
- CFTypeRef accessGroup = GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPrivateKeyAttrs) ?:
- GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPublicKeyAttrs);
-
- // If any of these attributes are present, forward the call to iOS implementation (and create keys in iOS keychain).
- if (tokenID != NULL ||
- (noLegacy != NULL && CFBooleanGetValue((CFBooleanRef)noLegacy)) ||
- (sync != NULL && CFBooleanGetValue((CFBooleanRef)sync)) ||
- accessControl != NULL || (accessGroup != NULL && CFEqual(accessGroup, kSecAttrAccessGroupToken))) {
+ bool forceIOSKey = false;
+ if (_CFMZEnabled()) {
+ // On Marzipan, always go iOS SecItem/SecKey route, do not drag CSSM keys in.
+ forceIOSKey = true;
+ } else {
+ CFTypeRef tokenID = GetAttributeFromParams(parameters, kSecAttrTokenID, NULL);
+ CFTypeRef noLegacy = GetAttributeFromParams(parameters, kSecAttrNoLegacy, NULL);
+ CFTypeRef sync = GetAttributeFromParams(parameters, kSecAttrSynchronizable, kSecPrivateKeyAttrs);
+ CFTypeRef accessControl = GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPrivateKeyAttrs) ?:
+ GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPublicKeyAttrs);
+ CFTypeRef accessGroup = GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPrivateKeyAttrs) ?:
+ GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPublicKeyAttrs);
+ // If any of these attributes are present, forward the call to iOS implementation (and create keys in iOS keychain).
+ forceIOSKey = (tokenID != NULL ||
+ (noLegacy != NULL && CFBooleanGetValue((CFBooleanRef)noLegacy)) ||
+ (sync != NULL && CFBooleanGetValue((CFBooleanRef)sync)) ||
+ accessControl != NULL || (accessGroup != NULL && CFEqual(accessGroup, kSecAttrAccessGroupToken)));
+ }
+
+ if (forceIOSKey) {
// Generate keys in iOS keychain.
return SecKeyGeneratePair_ios(parameters, publicKey, privateKey);
}