END_SECAPI1(_kCFRuntimeNotATypeID)
}
-OSStatus
-SecKeyCreatePair(
+static OSStatus SecKeyCreatePairInternal(
SecKeychainRef keychainRef,
CSSM_ALGORITHMS algorithm,
uint32 keySizeInBits,
SecPointer<Access> theAccess(initialAccess ? Access::required(initialAccess) : new Access("<key>"));
SecPointer<KeyItem> pubItem, privItem;
+ Mutex *keychainMutex = keychain->getKeychainMutex();
+ StLock<Mutex> _(*keychainMutex);
+
KeyItem::createPair(keychain,
algorithm,
keySizeInBits,
END_SECAPI
}
+OSStatus
+SecKeyCreatePair(
+ SecKeychainRef keychainRef,
+ CSSM_ALGORITHMS algorithm,
+ uint32 keySizeInBits,
+ CSSM_CC_HANDLE contextHandle,
+ CSSM_KEYUSE publicKeyUsage,
+ uint32 publicKeyAttr,
+ CSSM_KEYUSE privateKeyUsage,
+ uint32 privateKeyAttr,
+ SecAccessRef initialAccess,
+ SecKeyRef* publicKeyRef,
+ SecKeyRef* privateKeyRef)
+{
+ OSStatus result = SecKeyCreatePairInternal(keychainRef, algorithm, keySizeInBits, contextHandle, publicKeyUsage,
+ publicKeyAttr, privateKeyUsage, privateKeyAttr, initialAccess, publicKeyRef, privateKeyRef);
+
+ return result;
+}
+
+
+
OSStatus
SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey)
{
{
const CSSM_KEY *cssmKey;
- if (SecKeyGetCSSMKey(key, &cssmKey) != noErr)
+ if (SecKeyGetCSSMKey(key, &cssmKey) != errSecSuccess)
return kSecNullAlgorithmID;
switch (cssmKey->KeyHeader.AlgorithmId) {
END_SECAPI
}
-OSStatus
+static OSStatus
SecKeyGenerateWithAttributes(
SecKeychainAttributeList* attrList,
SecKeychainRef keychainRef,
try {
//FIXME: needs implementation
- __secapiresult=noErr;
+ __secapiresult=errSecSuccess;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
- catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
- catch (...) { __secapiresult=internalComponentErr; }
+ catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
+ catch (...) { __secapiresult=errSecInternalComponent; }
return keyRef;
}
}
// figure out the size of the string
- int numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8);
+ CFIndex numChars = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ref), kCFStringEncodingUTF8);
char buffer[numChars];
if (!CFStringGetCString(ref, buffer, numChars, kCFStringEncodingUTF8))
{
- MacOSError::throwMe(paramErr);
+ MacOSError::throwMe(errSecParam);
}
return atoi(buffer);
if (CFEqual(ktype, kSecAttrKeyTypeRSA)) {
algorithms = CSSM_ALGID_RSA;
- return noErr;
- } else if(CFEqual(ktype, kSecAttrKeyTypeECDSA)) {
+ return errSecSuccess;
+ } else if(CFEqual(ktype, kSecAttrKeyTypeECDSA) ||
+ CFEqual(ktype, kSecAttrKeyTypeEC)) {
algorithms = CSSM_ALGID_ECDSA;
- return noErr;
+ return errSecSuccess;
} else if(CFEqual(ktype, kSecAttrKeyTypeAES)) {
algorithms = CSSM_ALGID_AES;
- return noErr;
+ return errSecSuccess;
} else if(CFEqual(ktype, kSecAttrKeyType3DES)) {
algorithms = CSSM_ALGID_3DES;
- return noErr;
+ return errSecSuccess;
} else {
return errSecUnsupportedAlgorithm;
}
switch (algorithms) {
case CSSM_ALGID_ECDSA:
if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecp256r1;
- if(keySizeInBits == kSecp192r1 || keySizeInBits == kSecp256r1 || keySizeInBits == kSecp384r1 || keySizeInBits == kSecp521r1 ) return noErr;
+ if(keySizeInBits == kSecp192r1 || keySizeInBits == kSecp256r1 || keySizeInBits == kSecp384r1 || keySizeInBits == kSecp521r1 ) return errSecSuccess;
break;
case CSSM_ALGID_RSA:
if(keySizeInBits % 8) return errSecParam;
if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = 2048;
- if(keySizeInBits >= kSecRSAMin && keySizeInBits <= kSecRSAMax) return noErr;
+ if(keySizeInBits >= kSecRSAMin && keySizeInBits <= kSecRSAMax) return errSecSuccess;
break;
case CSSM_ALGID_AES:
if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSecAES128;
- if(keySizeInBits == kSecAES128 || keySizeInBits == kSecAES192 || keySizeInBits == kSecAES256) return noErr;
+ if(keySizeInBits == kSecAES128 || keySizeInBits == kSecAES192 || keySizeInBits == kSecAES256) return errSecSuccess;
break;
case CSSM_ALGID_3DES:
if(keySizeInBits == kSecDefaultKeySize) keySizeInBits = kSec3DES192;
- if(keySizeInBits == kSec3DES192) return noErr;
+ if(keySizeInBits == kSec3DES192) return errSecSuccess;
break;
default:
break;
}
}
- return noErr;
+ return errSecSuccess;
}
// look for modifiers in the general dictionary
OSStatus result = ScanDictionaryForParameters(parameters, attributePointers);
- if (result != noErr)
+ if (result != errSecSuccess)
{
return result;
}
}
// pull any additional parameters out of this dictionary
- result = ScanDictionaryForParameters(parameters, attributePointers);
- if (result != noErr)
+ result = ScanDictionaryForParameters((CFDictionaryRef)dType, attributePointers);
+ if (result != errSecSuccess)
{
return result;
}
attrs |= CSSM_KEYATTR_PERMANENT;
- return noErr;
+ return errSecSuccess;
}
OSStatus result;
result = CheckAlgorithmType(parameters, algorithms);
- if (result != noErr)
+ if (result != errSecSuccess)
{
return result;
}
result = GetKeySize(parameters, algorithms, keySizeInBits);
- if (result != noErr)
+ if (result != errSecSuccess)
{
return result;
}
- result = GetKeyParameters(parameters, keySizeInBits, false, privateKeyUse, privateKeyAttr, publicKeyLabelRef, publicKeyAttributeTagRef);
- if (result != noErr)
+ result = GetKeyParameters(parameters, keySizeInBits, false, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef);
+ if (result != errSecSuccess)
{
return result;
}
- result = GetKeyParameters(parameters, keySizeInBits, true, publicKeyUse, publicKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef);
- if (result != noErr)
+ result = GetKeyParameters(parameters, keySizeInBits, true, publicKeyUse, publicKeyAttr, publicKeyLabelRef, publicKeyAttributeTagRef);
+ if (result != errSecSuccess)
{
return result;
}
}
else if (SecAccessGetTypeID() != CFGetTypeID(initialAccess))
{
- return paramErr;
+ return errSecParam;
}
- return noErr;
+ return errSecSuccess;
}
if (numToModify == 0)
{
- return noErr;
+ return errSecSuccess;
}
SecKeychainAttributeList attrList;
UnixError::throwMe(ENOMEM);
}
if (!CFStringGetCString(label_string, static_cast<char *>(attributes[i].data), buffer_length, kCFStringEncodingUTF8)) {
- MacOSError::throwMe(paramErr);
+ MacOSError::throwMe(errSecParam);
}
}
- attributes[i].length = strlen(static_cast<char *>(attributes[i].data));
+ attributes[i].length = (UInt32)strlen(static_cast<char *>(attributes[i].data));
} else if (CFDataGetTypeID() == CFGetTypeID(label)) {
// 10.6 bug compatibility
CFDataRef label_data = static_cast<CFDataRef>(label);
attributes[i].tag = kSecKeyLabel;
attributes[i].data = (void*) CFDataGetBytePtr(label_data);
- attributes[i].length = CFDataGetLength(label_data);
+ attributes[i].length = (UInt32)CFDataGetLength(label_data);
} else {
- MacOSError::throwMe(paramErr);
+ MacOSError::throwMe(errSecParam);
}
i++;
}
{
attributes[i].tag = kSecKeyApplicationTag;
attributes[i].data = (void*) CFDataGetBytePtr(tag);
- attributes[i].length = CFDataGetLength(tag);
+ attributes[i].length = (UInt32)CFDataGetLength(tag);
i++;
}
publicKeyAttributeTagRef, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef,
initialAccess);
- if (result != noErr)
+ if (result != errSecSuccess)
{
return result;
}
// do the key generation
result = SecKeyCreatePair(keychain, algorithms, keySizeInBits, 0, publicKeyUse, publicKeyAttr, privateKeyUse, privateKeyAttr, initialAccess, publicKey, privateKey);
- if (result != noErr)
+ if (result != errSecSuccess)
{
return result;
}
END_SECAPI
}
+OSStatus SecKeyRawVerifyOSX(
+ SecKeyRef key, /* Public key */
+ SecPadding padding, /* kSecPaddingNone or kSecPaddingPKCS1 */
+ const uint8_t *signedData, /* signature over this data */
+ size_t signedDataLen, /* length of dataToSign */
+ const uint8_t *sig, /* signature */
+ size_t sigLen)
+{
+ return SecKeyRawVerify(key,padding,signedData,signedDataLen,sig,sigLen);
+}
+
/* new in 10.6 */
OSStatus
SecKeyRawVerify(
blockSize = 16; /* FIXME: revisit this */
break;
}
- __secapiresult=noErr;
+ __secapiresult=errSecSuccess;
}
catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
- catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
- catch (...) { __secapiresult=internalComponentErr; }
+ catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
+ catch (...) { __secapiresult=errSecInternalComponent; }
return blockSize;
}
*algorithm = CSSM_ALGID_DSA;
*keySizeInBits = 128;
*keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
- } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeECDSA)) {
+ } else if(CFEqual(algorithmDictValue, kSecAttrKeyTypeECDSA) ||
+ CFEqual(algorithmDictValue, kSecAttrKeyTypeEC)) {
*algorithm = CSSM_ALGID_ECDSA;
*keySizeInBits = 128;
*keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
SecKeyRef
SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error)
{
- OSStatus result = paramErr; // default result for an early exit
+ OSStatus result = errSecParam; // default result for an early exit
SecKeyRef key = NULL;
SecKeychainRef keychain = NULL;
SecAccessRef access;
appTagBuf[0]=0;
SecKeychainAttribute attrs[] = {
- { kSecKeyPrintName, strlen(labelBuf), (char *)labelBuf },
- { kSecKeyLabel, strlen(appLabelBuf), (char *)appLabelBuf },
- { kSecKeyApplicationTag, strlen(appTagBuf), (char *)appTagBuf } };
+ { kSecKeyPrintName, (UInt32)strlen(labelBuf), (char *)labelBuf },
+ { kSecKeyLabel, (UInt32)strlen(appLabelBuf), (char *)appLabelBuf },
+ { kSecKeyApplicationTag, (UInt32)strlen(appTagBuf), (char *)appTagBuf } };
SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
if (!appTag) --attributes.count;
OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
dispatch_async(deliveryQueue, ^{
CFErrorRef error = NULL;
- if (noErr != status) {
+ if (errSecSuccess != status) {
error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL);
}
result(publicKey, privateKey, error);
algorithm = kCCPRFHmacAlgSHA384;
} else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) {
algorithm = kCCPRFHmacAlgSHA512;
+ } else {
+#warning "This else clause is here to prevent the use of unitialized variable, but really, this should return an error, without leaking."
+ algorithm = kCCPRFHmacAlgSHA1;
}
if(rounds == 0) {
if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) {
+#warning "Aren't we leaking salt and thePassword when this fail???"
*error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL);
return NULL;
}
if (digestData) {
if(dataLen>UINT32_MAX) /* Check for overflow with CC_LONG cast */
- return paramErr;
+ return errSecParam;
digestFcn(data, (CC_LONG)dataLen, &digestInfo[offset]);
*digestInfoLen = offset + digestLen;
} else {
if (dataLen != digestLen)
- return paramErr;
+ return errSecParam;
memcpy(&digestInfo[offset], data, dataLen);
*digestInfoLen = offset + dataLen;
}
- return noErr;
+ return errSecSuccess;
}
OSStatus SecKeyVerifyDigest(
}
#endif
-OSStatus _SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes)
+OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes)
{
CFIndex keyAlgId;
#if TARGET_OS_EMBEDDED
#else
keyAlgId = SecKeyGetAlgorithmId(key);
#endif
- if (kSecRSAAlgorithmID == keyAlgId) {
+
+ OSStatus ecStatus = errSecParam;
+ CFDataRef tempPublicData = NULL;
+ CFDataRef headerlessPublicData = NULL;
+ CFIndex headerLength = 0;
+ const UInt8* pData_Ptr = NULL;
+
+ if (kSecRSAAlgorithmID == keyAlgId)
+ {
return SecItemExport(key, kSecFormatBSAFE, 0, NULL, publicBytes);
}
- if (kSecECDSAAlgorithmID == keyAlgId) {
- OSStatus ecStatus = errSecParam;
- *publicBytes = NULL;
- uint8 headerBytes[] = { 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,
- 0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,
- 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,
- 0x42,0x00 };
- uint8 altHdrBytes[] = { 0x30,0x81,0x9b,0x30,0x10,0x06,0x07,0x2a,
- 0x86,0x48,0xce,0x3d,0x02,0x01,0x06,0x05,
- 0x2b,0x81,0x04,0x00,0x23,0x03,0x81,0x86,
- 0x00};
-
- const size_t headerLen = sizeof(headerBytes);
- const size_t altHdrLen = sizeof(altHdrBytes);
- CFDataRef requiredPublicHeader = NULL;
- CFDataRef tempPublicData = NULL;
- CFDataRef publicDataHeader = NULL;
- CFDataRef headerlessPublicData = NULL;
+
+ if (kSecECDSAAlgorithmID == keyAlgId)
+ {
+ // First export the key so there is access to the underlying key material
ecStatus = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, &tempPublicData);
- if(ecStatus != errSecSuccess) {
+ if(ecStatus != errSecSuccess)
+ {
secdebug("key", "SecKeyCopyPublicBytes: SecItemExport error (%d) for ECDSA public key %p",
ecStatus, (uintptr_t)key);
- goto failEC;
- }
- requiredPublicHeader = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, headerBytes, headerLen, kCFAllocatorNull);
- if (!requiredPublicHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (1)");
- goto failEC;
- }
- publicDataHeader = _CFDataCreateReferenceFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(0, headerLen));
- if (!publicDataHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (1)");
- goto failEC;
- }
- headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(headerLen, CFDataGetLength(tempPublicData) - headerLen));
- if (!headerlessPublicData) {
- secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (1)");
- goto failEC;
- }
- if(!_CFDataEquals(publicDataHeader, requiredPublicHeader)) {
- CFRelease(publicDataHeader);
- CFRelease(headerlessPublicData);
- CFRelease(requiredPublicHeader);
- requiredPublicHeader = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, altHdrBytes, altHdrLen, kCFAllocatorNull);
- if (!requiredPublicHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (2)");
- goto failEC;
- }
- publicDataHeader = _CFDataCreateReferenceFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(0, altHdrLen));
- if (!publicDataHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (2)");
- goto failEC;
- }
- headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(altHdrLen, CFDataGetLength(tempPublicData) - altHdrLen));
- if (!headerlessPublicData) {
- secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (2)");
- goto failEC;
- }
- }
- if(!_CFDataEquals(publicDataHeader, requiredPublicHeader)) {
- #if ECDSA_DEBUG
- CFIndex dataLen = CFDataGetLength(tempPublicData);
- const UInt8 *dataPtr = CFDataGetBytePtr(tempPublicData);
- syslog(LOG_NOTICE, "Public key data (with header):");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- dataLen = CFDataGetLength(requiredPublicHeader);
- dataPtr = CFDataGetBytePtr(requiredPublicHeader);
- syslog(LOG_NOTICE, "Required header:");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- dataLen = CFDataGetLength(publicDataHeader);
- dataPtr = CFDataGetBytePtr(publicDataHeader);
- syslog(LOG_NOTICE, "Actual header:");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- #endif
- secdebug("key", "_SecKeyCopyPublicBytes: public data header mismatch");
- goto failEC;
- }
- if(publicBytes) {
- *publicBytes = headerlessPublicData;
- ecStatus = errSecSuccess;
+
+ return ecStatus;
+ }
+
+
+ // Get a pointer to the first byte of the exported data
+ pData_Ptr = CFDataGetBytePtr(tempPublicData);
+
+ // the first byte should be a sequence 0x30
+ if (*pData_Ptr != 0x30)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: exported data is invalid");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+ return ecStatus;
+ }
+
+ // move past the sequence byte
+ pData_Ptr++;
+
+ // Check to see if the high bit is set which
+ // indicates that the length will be at least
+ // two bytes. If the high bit is set then
+ // The lower seven bits specifies the number of
+ // bytes used for the length. The additonal 1
+ // is for the current byte. Otherwise just move past the
+ // single length byte
+ pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1;
+
+ // The current byte should be a sequence 0x30
+ if (*pData_Ptr != 0x30)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: Could not find the key sequence");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;
+ }
+
+ // The next bytes will always be the same
+ // 0x30 = SEQUENCE
+ // XX Length Byte
+ // 0x06 OBJECT ID
+ // 0x07 Length Byte
+ // ECDSA public KEY OID value 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01
+ // 0x06 OBJECT ID
+ // This is a total of 12 bytes
+ pData_Ptr += 12;
+
+ // Next byte is the length of the ECDSA curve OID
+ // Move past the length byte and the curve OID
+ pData_Ptr += (((int)*pData_Ptr) + 1);
+
+ // Should be at a BINARY String which is specifed by a 0x3
+ if (*pData_Ptr != 0x03)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: Invalid key structure");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;
+ }
+
+ // Move past the BINARY String specifier 0x03
+ pData_Ptr++;
+
+
+ // Check to see if the high bit is set which
+ // indicates that the length will be at least
+ // two bytes. If the high bit is set then
+ // The lower seven bits specifies the number of
+ // bytes used for the length. The additonal 1
+ // is for the current byte. Otherwise just move past the
+ // single length byte
+ pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1;
+
+ // Move past the beginning marker for the BINARY String 0x00
+ pData_Ptr++;
+
+ // pData_Ptr now points to the first bytes of the key material
+ headerLength = (CFIndex)(((intptr_t)pData_Ptr) - ((intptr_t)CFDataGetBytePtr(tempPublicData)));
+
+ headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
+ tempPublicData, CFRangeMake(headerLength, CFDataGetLength(tempPublicData) - headerLength));
+
+ if (!headerlessPublicData)
+ {
+ printf("SecKeyCopyPublicBytes: headerlessPublicData is nil (1)\n");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;
}
+
+ if (publicBytes)
+ {
+ *publicBytes = headerlessPublicData;
+ }
-failEC:
- if(requiredPublicHeader) CFRelease(requiredPublicHeader);
- if(publicDataHeader) CFRelease(publicDataHeader);
- if(tempPublicData) CFRelease(tempPublicData);
- return ecStatus;
- }
- return errSecParam;
+ ecStatus = errSecSuccess;
+
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ return ecStatus;
+ }
+
+ return errSecParam;
}
+
CFDataRef SecECKeyCopyPublicBits(SecKeyRef key)
{
CFDataRef exportedKey;
- if(_SecKeyCopyPublicBytes(key, &exportedKey) != noErr) {
+ if(SecKeyCopyPublicBytes(key, &exportedKey) != errSecSuccess) {
exportedKey = NULL;
}
return exportedKey;
}
-SecKeyRef _SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef publicBytes)
+SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef publicBytes)
{
SecExternalFormat externalFormat = kSecFormatOpenSSL;
SecExternalItemType externalItemType = kSecItemTypePublicKey;
} else if(kSecKeyEncodingRSAPublicParams == encoding) {
/* SecRSAPublicKeyParams format; we must encode as PKCS1. */
- #if !TARGET_OS_EMBEDDED
- typedef struct SecRSAPublicKeyParams {
- uint8_t *modulus; /* modulus */
- CFIndex modulusLength;
- uint8_t *exponent; /* public exponent */
- CFIndex exponentLength;
- } SecRSAPublicKeyParams;
- #endif
SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData;
DERSize m_size = params->modulusLength;
DERSize e_size = params->exponentLength;
/* unsupported encoding */
return NULL;
}
- SecKeyRef publicKey = _SecKeyCreateFromPublicData(allocator, kSecRSAAlgorithmID, pubKeyData);
+ SecKeyRef publicKey = SecKeyCreateFromPublicData(allocator, kSecRSAAlgorithmID, pubKeyData);
CFRelease(pubKeyData);
return publicKey;
}
// Given a CSSM public key, copy its modulus and/or exponent data.
// Caller is responsible for releasing the returned CFDataRefs.
//
+static
OSStatus _SecKeyCopyRSAPublicModulusAndExponent(SecKeyRef key, CFDataRef *modulus, CFDataRef *exponent)
{
const CSSM_KEY *pubKey;
OSStatus result;
result = SecKeyGetCSSMKey(key, &pubKey);
- if(result != noErr) {
+ if(result != errSecSuccess) {
return result;
}
hdr = &pubKey->KeyHeader;
return exponentData;
}
+SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) {
+ OSStatus status = errSecParam;
+
+ CFDataRef serializedPublic = NULL;
+
+ status = SecKeyCopyPublicBytes(privateKey, &serializedPublic);
+ if ((status == errSecSuccess) && (serializedPublic != NULL)) {
+ SecKeyRef publicKeyRef = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmId(privateKey), serializedPublic);
+ CFRelease(serializedPublic);
+ if (publicKeyRef != NULL) {
+ return publicKeyRef;
+ }
+ }
+
+ const void *keys[] = { kSecClass, kSecValueRef, kSecReturnAttributes };
+ const void *values[] = { kSecClassKey, privateKey, kCFBooleanTrue };
+ CFDictionaryRef query= CFDictionaryCreate(NULL, keys, values,
+ (sizeof(values) / sizeof(*values)),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFTypeRef foundItem = NULL;
+ status = SecItemCopyMatching(query, &foundItem);
+
+ if (status == errSecSuccess) {
+ if (CFGetTypeID(foundItem) == CFDictionaryGetTypeID()) {
+ CFMutableDictionaryRef query2 = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(query2, kSecClass, kSecClassKey);
+ CFDictionaryAddValue(query2, kSecAttrKeyClass, kSecAttrKeyClassPublic);
+ CFDictionaryAddValue(query2, kSecAttrApplicationLabel, CFDictionaryGetValue((CFDictionaryRef)foundItem, kSecAttrApplicationLabel));
+ CFDictionaryAddValue(query2, kSecReturnRef, kCFBooleanTrue);
+
+ CFTypeRef foundKey = NULL;
+ status = SecItemCopyMatching(query2, &foundKey);
+ if (status == errSecSuccess) {
+ if (CFGetTypeID(foundKey) == SecKeyGetTypeID()) {
+ CFRelease(query);
+ CFRelease(query2);
+ CFRelease(foundItem);
+ return (SecKeyRef)foundKey;
+ } else {
+ status = errSecItemNotFound;
+ }
+ }
+ CFRelease(query2);
+
+ } else {
+ status = errSecItemNotFound;
+ }
+ CFRelease(foundItem);
+ }
+
+ CFRelease(query);
+ return NULL;
+}
+