X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/866f8763175ff60e4fa455b92b5eb660a12fe6c7..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_keychain/lib/SecKey.cpp diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index 229ee8bb..6fb96593 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.cpp +++ b/OSX/libsecurity_keychain/lib/SecKey.cpp @@ -35,6 +35,10 @@ #include #include +#include +// '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 @@ -56,6 +60,7 @@ SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, Sec key->key = const_cast(reinterpret_cast(keyData)); key->key->initializeWithSecKeyRef(key); key->credentialType = kSecCredentialTypeDefault; + key->cdsaKeyMutex = new Mutex(); return errSecSuccess; } @@ -65,14 +70,22 @@ SecCDSAKeyDestroy(SecKeyRef keyRef) { // 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 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 _(keyItem->getMutexForObject()); keyItem = keyRef->key; @@ -85,6 +98,8 @@ SecCDSAKeyDestroy(SecKeyRef keyRef) { delete keyItem; } + delete keyRef->cdsaKeyMutex; + (void) kc; // Tell the compiler we're actually using this variable. At destruction time, it'll release the keychain. } @@ -501,7 +516,7 @@ static CSSM_DB_NAME_ATTR(kInfoKeyLabel, kSecKeyLabel, (char*) "Label", 0, NULL, #pragma clang diagnostic pop static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) { - CFErrorRef *error; + CFErrorRef *error = NULL; BEGIN_SECKEYAPI(SecKeyRef, NULL) result = NULL; @@ -761,7 +776,7 @@ static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationTyp } static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) { - CFErrorRef *error; + CFErrorRef *error = NULL; BEGIN_SECKEYAPI(Boolean, false) result = key1->key->equal(*key2->key); @@ -797,6 +812,8 @@ const SecKeyDescriptor kSecCDSAKeyDescriptor = { .copyOperationResult = SecCDSAKeyCopyOperationResult, .isEqual = SecCDSAKeyIsEqual, .setParameter = SecCDSAKeySetParameter, + + .extraBytes = (sizeof(struct OpaqueSecKeyRef) > sizeof(struct __SecKey) ? (sizeof(struct OpaqueSecKeyRef) - sizeof(struct __SecKey)) : 0), }; namespace Security { @@ -813,10 +830,35 @@ namespace Security { if (key->cdsaKey == NULL) { // Create CDSA key from exported data of existing key. - CFRef keyData = SecKeyCopyExternalRepresentation(key, NULL); CFRef keyAttributes = SecKeyCopyAttributes(key); - if (keyData && keyAttributes) { - key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL); + if (keyAttributes) { + CFRef 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 query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRef identities; + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)identities.take()); + if (status == errSecSuccess) { + for (int i = 0; i < CFArrayGetCount(identities); ++i) { + CFRef privateKey; + if (SecIdentityCopyPrivateKey((SecIdentityRef)CFArrayGetValueAtIndex(identities, i), privateKey.take()) != errSecSuccess) { + continue; + } + CFRef attrs = SecKeyCopyAttributes(privateKey); + if (CFEqual(CFDictionaryGetValue(attrs, kSecAttrApplicationLabel), pubKeyHash)) { + key->cdsaKey = privateKey.retain(); + break; + } + } + } + } else { + key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL); + } } } @@ -910,7 +952,7 @@ SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey) // static ModuleNexus gSecReturnedKeyCSPsMutex; -static std::set gSecReturnedKeyCSPs; +static ModuleNexus> gSecReturnedKeyCSPs; OSStatus SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) @@ -924,7 +966,7 @@ SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) CssmClient::CSP returnedKeyCSP = keyItem->csp(); { StLock _(gSecReturnedKeyCSPsMutex()); - gSecReturnedKeyCSPs.insert(returnedKeyCSP); + gSecReturnedKeyCSPs().insert(returnedKeyCSP); } Required(cspHandle) = returnedKeyCSP->handle(); @@ -1544,19 +1586,26 @@ SecKeyGeneratePairInternal( 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); }