* @APPLE_LICENSE_HEADER_END@
*/
-#include "SecKey.h"
-#include "SecKeyPriv.h"
-#include "SecItem.h"
-#include "SecItemPriv.h"
+#include <Security/SecKey.h>
+#include <Security/SecKeyPriv.h>
+#include <Security/SecKeyInternal.h>
+#include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
#include <libDER/asn1Types.h>
#include <libDER/DER_Encode.h>
#include <libDER/DER_Decode.h>
#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>
static OSStatus
SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
- key->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
- key->key->initializeWithSecKeyRef(key);
- key->credentialType = kSecCredentialTypeDefault;
+ CDSASecKey *cdsaKey = (CDSASecKey *)key;
+ cdsaKey->key = const_cast<KeyItem *>(reinterpret_cast<const KeyItem *>(keyData));
+ CDSASecKey::keyItem(key)->initializeWithSecKeyRef(key);
+ cdsaKey->credentialType = kSecCredentialTypeDefault;
+ cdsaKey->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.
- KeyItem *keyItem = keyRef->key;
+ CDSASecKey *cdsaKey = static_cast<CDSASecKey *>(keyRef);
+ StMaybeLock<Mutex> cdsaMutex(cdsaKey->cdsaKeyMutex);
+
+ KeyItem *keyItem = static_cast<KeyItem *>(keyRef->key);
+
if (keyItem == NULL) {
// KeyImpl::attachSecKeyRef disconnected us from KeyItem instance, there is nothing to do for us.
+ cdsaMutex.unlock();
+ delete cdsaKey->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;
+ keyItem = static_cast<KeyItem *>(keyRef->key);
if (keyItem == NULL) {
// Second version of the check above, the definitive one because this one is performed with locked object's mutex, therefore we can be sure that KeyImpl is still connected to this keyRef instance.
return;
delete keyItem;
}
+ delete cdsaKey->cdsaKeyMutex;
+
(void) kc; // Tell the compiler we're actually using this variable. At destruction time, it'll release the keychain.
}
CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(size_t,0)
- const CssmKey::Header keyHeader = key->key->unverifiedKeyHeader();
+ const CssmKey::Header keyHeader = CDSASecKey::keyItem(key)->unverifiedKeyHeader();
switch(keyHeader.algorithm())
{
case CSSM_ALGID_RSA:
BEGIN_SECKEYAPI(CFIndex, 0)
result = kSecNullAlgorithmID;
- switch (key->key->unverifiedKeyHeader().AlgorithmId) {
+ switch (CDSASecKey::keyItem(key)->unverifiedKeyHeader().AlgorithmId) {
case CSSM_ALGID_RSA:
result = kSecRSAAlgorithmID;
break;
CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(OSStatus, errSecSuccess)
- const CssmKey::Header &header = key->key->key().header();
+ const CssmKey::Header &header = CDSASecKey::keyItem(key)->key().header();
switch (header.algorithm()) {
case CSSM_ALGID_RSA: {
switch (header.keyClass()) {
BEGIN_SECKEYAPI(CFDataRef, NULL)
result = NULL;
- const CssmKey::Header header = key->key->unverifiedKeyHeader();
+ const CssmKey::Header header = CDSASecKey::keyItem(key)->unverifiedKeyHeader();
CFRef<CFDataRef> keyData;
switch (header.algorithm()) {
case CSSM_ALGID_RSA:
static CFDataRef SecCDSAKeyCopyLabel(SecKeyRef key) {
CFDataRef label = NULL;
- if (key->key->isPersistent()) {
+ if (CDSASecKey::keyItem(key)->isPersistent()) {
UInt32 tags[] = { kSecKeyLabel }, formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_BLOB };
SecKeychainAttributeInfo info = { 1, tags, formats };
SecKeychainAttributeList *list = NULL;
- key->key->getAttributesAndData(&info, NULL, &list, NULL, NULL);
+ CDSASecKey::keyItem(key)->getAttributesAndData(&info, NULL, &list, NULL, NULL);
if (list->count == 1) {
SecKeychainAttribute *attr = list->attr;
label = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)attr->data, (CFIndex)attr->length);
}
- key->key->freeAttributesAndData(list, NULL);
+ CDSASecKey::keyItem(key)->freeAttributesAndData(list, NULL);
}
return label;
}
CFDictionarySetValue(dict, kSecClass, kSecClassKey);
- const CssmKey::Header header = key->key->unverifiedKeyHeader();
+ const CssmKey::Header header = CDSASecKey::keyItem(key)->unverifiedKeyHeader();
CFIndex sizeValue = header.LogicalKeySizeInBits;
CFRef<CFNumberRef> sizeInBits = CFNumberCreate(NULL, kCFNumberCFIndexType, &sizeValue);
CFDictionarySetValue(dict, kSecAttrKeySizeInBits, sizeInBits);
if (header.algorithm() == CSSM_ALGID_RSA && header.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY &&
header.blobType() == CSSM_KEYBLOB_RAW) {
- const CssmData &keyData = key->key->key()->keyData();
+ const CssmData &keyData = CDSASecKey::keyItem(key)->key()->keyData();
DERItem keyItem = { static_cast<DERByte *>(keyData.data()), keyData.length() };
DERRSAPubKeyPKCS1 decodedKey;
if (DERParseSequence(&keyItem, DERNumRSAPubKeyPKCS1ItemSpecs,
#pragma clang diagnostic pop
static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) {
- CFErrorRef *error;
+ CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(SecKeyRef, NULL)
result = NULL;
- KeyItem *key = privateKey->key;
+ KeyItem *key = CDSASecKey::keyItem(privateKey);
CFRef<CFDataRef> label = SecCDSAKeyCopyLabel(privateKey);
if (label) {
// Lookup public key in the database.
}
if (result == NULL && key->publicKey()) {
- KeyItem *publicKey = new KeyItem(key->publicKey());
+ SecPointer<KeyItem> publicKey(new KeyItem(key->publicKey()));
result = reinterpret_cast<SecKeyRef>(publicKey->handle());
}
END_SECKEYAPI
}
-static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
+static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType &operation, SecKeyAlgorithm algorithm,
CSSM_ALGORITHMS &baseAlgorithm, CSSM_ALGORITHMS &secondaryAlgorithm,
CSSM_ALGORITHMS &paddingAlgorithm, CFIndex &inputSizeLimit) {
- KeyItem *keyItem = key->key;
+ KeyItem *keyItem = CDSASecKey::keyItem(key);
CSSM_KEYCLASS keyClass = keyItem->key()->header().keyClass();
baseAlgorithm = keyItem->key()->header().algorithm();
switch (baseAlgorithm) {
} else {
return NULL;
}
+ } else if (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeDecrypt &&
+ CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) {
+ // Raw RSA decryption is identical to raw RSA encryption, so lets use encryption instead of decryption,
+ // because CDSA keys refuses to perform decrypt using public key.
+ operation = kSecKeyOperationTypeEncrypt;
+ secondaryAlgorithm = CSSM_ALGID_NONE;
+ paddingAlgorithm = CSSM_PADDING_NONE;
+ inputSizeLimit = 0;
} else {
return NULL;
}
static CFDataRef
SecCDSAKeyCopyPaddedPlaintext(SecKeyRef key, CFDataRef plaintext, SecKeyAlgorithm algorithm) {
- CFIndex blockSize = key->key->key().header().LogicalKeySizeInBits / 8;
+ CFIndex blockSize = CDSASecKey::keyItem(key)->key().header().LogicalKeySizeInBits / 8;
CFIndex plaintextLength = CFDataGetLength(plaintext);
if ((algorithm == kSecKeyAlgorithmRSAEncryptionRaw || algorithm == kSecKeyAlgorithmRSASignatureRaw)
&& plaintextLength < blockSize) {
}
}
+ CDSASecKey *cdsaKey = static_cast<CDSASecKey *>(key);
switch (operation) {
case kSecKeyOperationTypeSign: {
CssmClient::Sign signContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm);
signContext.key(keyItem->key());
- signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, key->credentialType));
+ signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, cdsaKey->credentialType));
signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
CssmAutoData signature(signContext.allocator());
case kSecKeyOperationTypeVerify: {
CssmClient::Verify verifyContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm);
verifyContext.key(keyItem->key());
- verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, key->credentialType));
+ verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, cdsaKey->credentialType));
verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm);
CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef<CFDataRef>::check(in2, errSecParam)));
CssmClient::Encrypt encryptContext(keyItem->csp(), baseAlgorithm);
encryptContext.key(keyItem->key());
encryptContext.padding(paddingAlgorithm);
- encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, key->credentialType));
+ encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, cdsaKey->credentialType));
CFRef<CFDataRef> input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef<CFDataRef>::check(in1, errSecParam), algorithm);
CssmAutoData output(encryptContext.allocator()), remainingData(encryptContext.allocator());
size_t length = encryptContext.encrypt(CssmData(CFDataRef(input)), output.get(), remainingData.get());
CssmClient::Decrypt decryptContext(keyItem->csp(), baseAlgorithm);
decryptContext.key(keyItem->key());
decryptContext.padding(paddingAlgorithm);
- decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, key->credentialType));
+ decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, cdsaKey->credentialType));
CssmAutoData output(decryptContext.allocator()), remainingData(decryptContext.allocator());
size_t length = decryptContext.decrypt(CssmData(CFRef<CFDataRef>::check(in1, errSecParam)),
output.get(), remainingData.get());
}
static Boolean SecCDSAKeyIsEqual(SecKeyRef key1, SecKeyRef key2) {
- CFErrorRef *error;
+ CFErrorRef *error = NULL;
BEGIN_SECKEYAPI(Boolean, false)
- result = key1->key->equal(*key2->key);
+ result = CDSASecKey::keyItem(key1)->equal(*CDSASecKey::keyItem(key2));
END_SECKEYAPI
}
BEGIN_SECKEYAPI(Boolean, false)
if (CFEqual(name, kSecUseAuthenticationUI)) {
- key->credentialType = CFEqual(value, kSecUseAuthenticationUIAllow) ? kSecCredentialTypeDefault : kSecCredentialTypeNoUI;
+ static_cast<CDSASecKey *>(key)->credentialType = CFEqual(value, kSecUseAuthenticationUIAllow) ? kSecCredentialTypeDefault : kSecCredentialTypeNoUI;
result = true;
} else {
result = SecError(errSecUnimplemented, error, CFSTR("Unsupported parameter '%@' for SecKeyCDSASetParameter"), name);
.copyOperationResult = SecCDSAKeyCopyOperationResult,
.isEqual = SecCDSAKeyIsEqual,
.setParameter = SecCDSAKeySetParameter,
+
+ .extraBytes = (sizeof(class CDSASecKey) > sizeof(struct __SecKey) ? (sizeof(class CDSASecKey) - sizeof(struct __SecKey)) : 0),
};
namespace Security {
return static_cast<SecCFObject *>(key->key);
}
- if (key->cdsaKey == NULL) {
+ CFRef<SecKeyRef> cdsaKey = SecKeyCopyAuxilliaryCDSAKeyForKey(key);
+ if (!cdsaKey) {
// 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, kSecUseDataProtectionKeychain, 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)) {
+ cdsaKey = privateKey;
+ SecKeySetAuxilliaryCDSAKeyForKey(key, cdsaKey.get());
+ break;
+ }
+ }
+ }
+ } else {
+ cdsaKey.take(SecKeyCreateFromData(keyAttributes, keyData, NULL));
+ if (cdsaKey) {
+ SecKeySetAuxilliaryCDSAKeyForKey(key, cdsaKey.get());
+ }
+ }
}
}
- return (key->cdsaKey != NULL) ? key->cdsaKey->key : NULL;
+ return cdsaKey ? CDSASecKey::keyItem(cdsaKey.get()) : NULL;
}
// You need to hold this key's MutexForObject when you run this
void KeyItem::attachSecKeyRef() const {
SecKeyRef key = SecKeyCreate(NULL, &kSecCDSAKeyDescriptor, reinterpret_cast<const uint8_t *>(this), 0, 0);
- key->key->mWeakSecKeyRef = key;
+ CDSASecKey::keyItem(key)->mWeakSecKeyRef = key;
}
}
SecPointer<KeyItem> pubItem, privItem;
if (((publicKeyAttr | privateKeyAttr) & CSSM_KEYATTR_PERMANENT) != 0) {
keychain = Keychain::optional(keychainRef);
- StLock<Mutex> _(*keychain->getKeychainMutex());
- KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr,
- privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem);
- } else {
- KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr,
- privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem);
}
+ StMaybeLock<Mutex> _(keychain ? keychain->getKeychainMutex() : NULL);
+ KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr,
+ privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem);
// Return the generated keys.
if (publicKeyRef)
// Private APIs
//
+static ModuleNexus<Mutex> gSecReturnedKeyCSPsMutex;
+static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeyCSPs;
+
OSStatus
SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle)
{
BEGIN_SECAPI
SecPointer<KeyItem> keyItem(KeyItem::required(keyRef));
- Required(cspHandle) = keyItem->csp()->handle();
+
+ // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP).
+ // Keep a global pointer to it to force the CSP to stay live forever.
+ CssmClient::CSP returnedKeyCSP = keyItem->csp();
+ {
+ StLock<Mutex> _(gSecReturnedKeyCSPsMutex());
+ gSecReturnedKeyCSPs().insert(returnedKeyCSP);
+ }
+ Required(cspHandle) = returnedKeyCSP->handle();
END_SECAPI
}
// figure out the size of the string
CFIndex numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8);
- char buffer[numChars];
+ char *buffer = (char *)malloc(numChars);
+ if (NULL == buffer) {
+ UnixError::throwMe(ENOMEM);
+ }
if (!CFStringGetCString(ref, buffer, numChars, kCFStringEncodingUTF8))
{
+ free(buffer);
MacOSError::throwMe(errSecParam);
}
- return atoi(buffer);
+ u_int32_t result = atoi(buffer);
+ free(buffer);
+ return result;
}
SecKeychainAttribute attributes[numToModify];
int i = 0;
+ void *data = NULL;
if (label != NULL)
{
attributes[i].data = (void*) CFStringGetCStringPtr(label_string, kCFStringEncodingUTF8);
if (NULL == attributes[i].data) {
CFIndex buffer_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(label_string), kCFStringEncodingUTF8);
- attributes[i].data = alloca((size_t)buffer_length);
+ data = attributes[i].data = malloc((size_t)buffer_length);
if (NULL == attributes[i].data) {
UnixError::throwMe(ENOMEM);
}
if (!CFStringGetCString(label_string, static_cast<char *>(attributes[i].data), buffer_length, kCFStringEncodingUTF8)) {
+ free(data);
MacOSError::throwMe(errSecParam);
}
}
attrList.count = numToModify;
attrList.attr = attributes;
-
- return SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL);
+
+ OSStatus result = SecKeychainItemModifyAttributesAndData((SecKeychainItemRef) keyRef, &attrList, 0, NULL);
+ if (data)
+ {
+ free(data);
+ }
+
+ return result;
}
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, kSecUseDataProtectionKeychain, NULL);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ if (!noLegacy) { // Also lookup via deprecated symbol because we do CFDictionaryGetValue and your CFDict might be an idiot
+ noLegacy = GetAttributeFromParams(parameters, kSecAttrNoLegacy, NULL);
+ }
+#pragma clang diagnostic pop
+ 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);
}
}
else {
// we can set the label attributes on the generated key if it's a keychain item
- size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 0;
+ size_t labelBufLen = (label) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(label), kCFStringEncodingUTF8) + 1 : 1;
char *labelBuf = (char *)malloc(labelBufLen);
- size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 0;
+ size_t appLabelBufLen = (appLabel) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appLabel), kCFStringEncodingUTF8) + 1 : 1;
char *appLabelBuf = (char *)malloc(appLabelBufLen);
- size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 0;
+ size_t appTagBufLen = (appTag) ? (size_t)CFStringGetMaximumSizeForEncoding(CFStringGetLength(appTag), kCFStringEncodingUTF8) + 1 : 1;
char *appTagBuf = (char *)malloc(appTagBufLen);
- if (label && !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8))
+ if (!label || !CFStringGetCString(label, labelBuf, labelBufLen-1, kCFStringEncodingUTF8))
labelBuf[0]=0;
- if (appLabel && !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8))
+ if (!appLabel || !CFStringGetCString(appLabel, appLabelBuf, appLabelBufLen-1, kCFStringEncodingUTF8))
appLabelBuf[0]=0;
- if (appTag && !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8))
+ if (!appTag || !CFStringGetCString(appTag, appTagBuf, appTagBufLen-1, kCFStringEncodingUTF8))
appTagBuf[0]=0;
SecKeychainAttribute attrs[] = {
CFRelease(ka);
return sk;
} else {
+ CFRelease(ka);
if (error) {
*error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, crtn ? crtn : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
}
/* Pick Values from parameters */
if((saltDictValue = (CFDataRef) CFDictionaryGetValue(parameters, kSecAttrSalt)) == NULL) {
- *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL);
+ if(error) {
+ *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL);
+ }
goto errOut;
}
saltLen = CFDataGetLength(saltDictValue);
if((salt = (uint8_t *) malloc(saltLen)) == NULL) {
- *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ if(error) {
+ *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ }
goto errOut;
}
passwordLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1;
if((thePassword = (char *) malloc(passwordLen)) == NULL) {
- *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ if(error) {
+ *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ }
goto errOut;
}
CFStringGetBytes(password, CFRangeMake(0, CFStringGetLength(password)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)thePassword, passwordLen, &passwordLen);
if((derivedKey = (uint8_t *) malloc(derivedKeyLen)) == NULL) {
- *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ if(error) {
+ *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL);
+ }
goto errOut;
}
}
if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) {
- *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
+ if(error) {
+ *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
+ }
goto errOut;
}