#include <Security/SecBase.h>
#include <Security/SecKeyInternal.h>
#include <Security/SecItem.h>
#include <Security/SecCFAllocator.h>
#include <AssertMacros.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/array_size.h>
#include <utilities/debugging.h>
#include <utilities/SecCFError.h>
#include <utilities/SecBuffer.h>
#include <corecrypto/ccsha1.h>
#include <corecrypto/ccsha2.h>
#include <corecrypto/ccmd5.h>
#include <corecrypto/ccrsa_priv.h>
#include <corecrypto/ccansikdf.h>
#include <corecrypto/ccmode.h>
#include <corecrypto/ccaes.h>
#pragma mark Algorithm constants value definitions
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureRaw = CFSTR("algid:sign:RSA:raw");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureRawCCUnit = CFSTR("algid:sign:RSA:raw-cc");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw = CFSTR("algid:sign:RSA:digest-PKCS1v15");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 = CFSTR("algid:sign:RSA:digest-PKCS1v15:MD5");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 = CFSTR("algid:sign:RSA:digest-PKCS1v15:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224 = CFSTR("algid:sign:RSA:digest-PKCS1v15:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 = CFSTR("algid:sign:RSA:digest-PKCS1v15:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 = CFSTR("algid:sign:RSA:digest-PKCS1v15:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 = CFSTR("algid:sign:RSA:digest-PKCS1v15:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5 = CFSTR("algid:sign:RSA:message-PKCS1v15:MD5");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 = CFSTR("algid:sign:RSA:message-PKCS1v15:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 = CFSTR("algid:sign:RSA:message-PKCS1v15:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 = CFSTR("algid:sign:RSA:message-PKCS1v15:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 = CFSTR("algid:sign:RSA:message-PKCS1v15:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512 = CFSTR("algid:sign:RSA:message-PKCS1v15:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureRFC4754 = CFSTR("algid:sign:ECDSA:RFC4754");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962 = CFSTR("algid:sign:ECDSA:digest-X962");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA1 = CFSTR("algid:sign:ECDSA:digest-X962:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA224 = CFSTR("algid:sign:ECDSA:digest-X962:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA256 = CFSTR("algid:sign:ECDSA:digest-X962:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA384 = CFSTR("algid:sign:ECDSA:digest-X962:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA512 = CFSTR("algid:sign:ECDSA:digest-X962:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA1 = CFSTR("algid:sign:ECDSA:message-X962:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA224 = CFSTR("algid:sign:ECDSA:message-X962:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA256 = CFSTR("algid:sign:ECDSA:message-X962:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA384 = CFSTR("algid:sign:ECDSA:message-X962:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA512 = CFSTR("algid:sign:ECDSA:message-X962:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionRaw = CFSTR("algid:encrypt:RSA:raw");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionRawCCUnit = CFSTR("algid:encrypt:RSA:raw-cc");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionPKCS1 = CFSTR("algid:encrypt:RSA:PKCS1");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA1 = CFSTR("algid:encrypt:RSA:OAEP:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA224 = CFSTR("algid:encrypt:RSA:OAEP:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA256 = CFSTR("algid:encrypt:RSA:OAEP:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA384 = CFSTR("algid:encrypt:RSA:OAEP:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA512 = CFSTR("algid:encrypt:RSA:OAEP:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM = CFSTR("algid:encrypt:RSA:OAEP:SHA1:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM = CFSTR("algid:encrypt:RSA:OAEP:SHA224:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM = CFSTR("algid:encrypt:RSA:OAEP:SHA256:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM = CFSTR("algid:encrypt:RSA:OAEP:SHA384:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM = CFSTR("algid:encrypt:RSA:OAEP:SHA512:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM = CFSTR("algid:encrypt:ECIES:ECDH:KDFX963:SHA1:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM = CFSTR("algid:encrypt:ECIES:ECDH:KDFX963:SHA224:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM = CFSTR("algid:encrypt:ECIES:ECDH:KDFX963:SHA256:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM = CFSTR("algid:encrypt:ECIES:ECDH:KDFX963:SHA384:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM = CFSTR("algid:encrypt:ECIES:ECDH:KDFX963:SHA512:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM = CFSTR("algid:encrypt:ECIES:ECDHC:KDFX963:SHA1:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM = CFSTR("algid:encrypt:ECIES:ECDHC:KDFX963:SHA224:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM = CFSTR("algid:encrypt:ECIES:ECDHC:KDFX963:SHA256:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM = CFSTR("algid:encrypt:ECIES:ECDHC:KDFX963:SHA384:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM = CFSTR("algid:encrypt:ECIES:ECDHC:KDFX963:SHA512:AESGCM");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandard = CFSTR("algid:keyexchange:ECDH");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1 = CFSTR("algid:keyexchange:ECDH:KDFX963:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224 = CFSTR("algid:keyexchange:ECDH:KDFX963:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256 = CFSTR("algid:keyexchange:ECDH:KDFX963:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384 = CFSTR("algid:keyexchange:ECDH:KDFX963:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512 = CFSTR("algid:keyexchange:ECDH:KDFX963:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactor = CFSTR("algid:keyexchange:ECDHC");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1 = CFSTR("algid:keyexchange:ECDHC:KDFX963:SHA1");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224 = CFSTR("algid:keyexchange:ECDHC:KDFX963:SHA224");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256 = CFSTR("algid:keyexchange:ECDHC:KDFX963:SHA256");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384 = CFSTR("algid:keyexchange:ECDHC:KDFX963:SHA384");
const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512 = CFSTR("algid:keyexchange:ECDHC:KDFX963:SHA512");
const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionAKSSmartCard = CFSTR("algid:encrypt:ECIES:ECDH:SHA256:2PubKeys");
void SecKeyOperationContextDestroy(SecKeyOperationContext *context) {
CFReleaseSafe(context->algorithm);
}
static void PerformWithCFDataBuffer(CFIndex size, void (^operation)(uint8_t *buffer, CFDataRef data)) {
PerformWithBuffer(size, ^(size_t size, uint8_t *buffer) {
CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)buffer, size, kCFAllocatorNull);
operation(buffer, data);
CFRelease(data);
});
}
static CFDataRef SecKeyMessageToDigestAdaptor(SecKeyOperationContext *context, CFDataRef message, CFDataRef in2,
const struct ccdigest_info *di, CFErrorRef *error) {
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFTypeRef result;
PerformWithCFDataBuffer(di->output_size, ^(uint8_t *buffer, CFDataRef data) {
ccdigest(di, CFDataGetLength(message), CFDataGetBytePtr(message), buffer);
result = SecKeyRunAlgorithmAndCopyResult(context, data, in2, error);
});
return result;
}
#define SECKEY_DIGEST_RSA_ADAPTORS(name, di) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15 ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15 ## name); \
return SecKeyMessageToDigestAdaptor(context, in1, in2, di, error); \
}
#define SECKEY_DIGEST_ADAPTORS(name, di) SECKEY_DIGEST_RSA_ADAPTORS(name, di) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962 ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmECDSASignatureDigestX962 ## name); \
return SecKeyMessageToDigestAdaptor(context, in1, in2, di, error); \
} \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962 ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmECDSASignatureDigestX962); \
return SecKeyRunAlgorithmAndCopyResult(context, in1, in2, error); \
}
SECKEY_DIGEST_ADAPTORS(SHA1, ccsha1_di())
SECKEY_DIGEST_ADAPTORS(SHA224, ccsha224_di())
SECKEY_DIGEST_ADAPTORS(SHA256, ccsha256_di())
SECKEY_DIGEST_ADAPTORS(SHA384, ccsha384_di())
SECKEY_DIGEST_ADAPTORS(SHA512, ccsha512_di())
SECKEY_DIGEST_RSA_ADAPTORS(MD5, ccmd5_di())
#undef SECKEY_DIGEST_RSA_ADAPTORS
#undef SECKEY_DIGEST_ADAPTORS
static CFDataRef SecKeyRSACopyBigEndianToCCUnit(CFDataRef bigEndian, size_t size) {
CFMutableDataRef result = NULL;
if (bigEndian != NULL) {
size_t dataSize = CFDataGetLength(bigEndian);
if (dataSize > size) {
size = dataSize;
}
result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, ccrsa_sizeof_n_from_size(size));
ccn_read_uint(ccn_nof_size(size), (cc_unit *)CFDataGetMutableBytePtr(result), dataSize, CFDataGetBytePtr(bigEndian));
}
return result;
}
static void PerformWithBigEndianToCCUnit(CFDataRef bigEndian, size_t size, void (^operation)(CFDataRef ccunits)) {
if (bigEndian == NULL) {
return operation(NULL);
}
size_t dataSize = CFDataGetLength(bigEndian);
if (dataSize > size) {
size = dataSize;
}
PerformWithCFDataBuffer(ccrsa_sizeof_n_from_size(size), ^(uint8_t *buffer, CFDataRef data) {
ccn_read_uint(ccn_nof_size(size), (cc_unit *)buffer, dataSize, CFDataGetBytePtr(bigEndian));
operation(data);
});
}
static CFDataRef SecKeyRSACopyCCUnitToBigEndian(CFDataRef ccunits, size_t size) {
CFMutableDataRef result = NULL;
if (ccunits != NULL) {
cc_size n = ccn_nof_size(CFDataGetLength(ccunits));
const cc_unit *s = (const cc_unit *)CFDataGetBytePtr(ccunits);
result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, size);
ccn_write_uint_padded(n, s, CFDataGetLength(result), CFDataGetMutableBytePtr(result));
}
return result;
}
static void PerformWithCCUnitToBigEndian(CFDataRef ccunits, size_t size, void (^operation)(CFDataRef bigEndian)) {
if (ccunits == NULL) {
return operation(NULL);
}
PerformWithCFDataBuffer(size, ^(uint8_t *buffer, CFDataRef data) {
cc_size n = ccn_nof_size(CFDataGetLength(ccunits));
const cc_unit *s = (const cc_unit *)CFDataGetBytePtr(ccunits);
ccn_write_uint_padded(n, s, size, buffer);
operation(data);
});
}
static CFTypeRef SecKeyRSACopyPKCS1EMSASignature(SecKeyOperationContext *context,
CFDataRef in1, CFDataRef in2, CFErrorRef *error, const uint8_t *oid) {
if (oid != NULL) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw);
}
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSASignatureRawCCUnit);
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFTypeRef result = NULL;
size_t size = SecKeyGetBlockSize(context->key);
if (size == 0) {
SecError(errSecParam, error, CFSTR("expecting RSA key"));
return NULL;
}
PerformWithCFDataBuffer(size, ^(uint8_t *buffer, CFDataRef data) {
uint8_t s[size];
int err = ccrsa_emsa_pkcs1v15_encode(size, s, CFDataGetLength(in1), CFDataGetBytePtr(in1), oid);
require_noerr_action_quiet(err, out, SecError(errSecParam, error, CFSTR("RSAsign wrong input data length")));
ccn_read_uint(ccn_nof_size(size), (cc_unit *)buffer, size, s);
require_quiet(result = SecKeyRunAlgorithmAndCopyResult(context, data, NULL, error), out);
CFAssignRetained(result, SecKeyRSACopyCCUnitToBigEndian(result, SecKeyGetBlockSize(context->key)));
out:;
});
return result;
}
#define seckey_ccoid_md5 ((unsigned char *)"\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05")
#define PKCS1v15_EMSA_SIGN_ADAPTOR(name, oid) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15 ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSACopyPKCS1EMSASignature(context, in1, in2, error, oid); \
}
PKCS1v15_EMSA_SIGN_ADAPTOR(SHA1, ccoid_sha1)
PKCS1v15_EMSA_SIGN_ADAPTOR(SHA224, ccoid_sha224)
PKCS1v15_EMSA_SIGN_ADAPTOR(SHA256, ccoid_sha256)
PKCS1v15_EMSA_SIGN_ADAPTOR(SHA384, ccoid_sha384)
PKCS1v15_EMSA_SIGN_ADAPTOR(SHA512, ccoid_sha512)
PKCS1v15_EMSA_SIGN_ADAPTOR(Raw, NULL)
PKCS1v15_EMSA_SIGN_ADAPTOR(MD5, seckey_ccoid_md5)
#undef PKCS1v15_EMSA_SIGN_ADAPTOR
static CFTypeRef SecKeyAlgorithmAdaptorBigEndianToCCUnit(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFTypeRef result = NULL;
PerformWithBigEndianToCCUnit(in1, SecKeyGetBlockSize(context->key), ^(CFDataRef ccunits) {
result = SecKeyRunAlgorithmAndCopyResult(context, ccunits, in2, error);
if (result != NULL) {
CFAssignRetained(result, SecKeyRSACopyCCUnitToBigEndian(result, SecKeyGetBlockSize(context->key)));
}
});
return result;
}
static CFTypeRef SecKeyAlgorithmAdaptorCCUnitToBigEndian(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFTypeRef result = NULL;
PerformWithCCUnitToBigEndian(in1, SecKeyGetBlockSize(context->key), ^(CFDataRef bigEndian) {
result = SecKeyRunAlgorithmAndCopyResult(context, bigEndian, in2, error);
if (result != NULL) {
CFAssignRetained(result, SecKeyRSACopyBigEndianToCCUnit(result, SecKeyGetBlockSize(context->key)));
}
});
return result;
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureRaw(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSASignatureRawCCUnit);
return SecKeyAlgorithmAdaptorBigEndianToCCUnit(context, in1, in2, error);
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureRawCCUnit(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSASignatureRaw);
return SecKeyAlgorithmAdaptorCCUnitToBigEndian(context, in1, in2, error);
}
static bool SecKeyVerifyBadSignature(CFErrorRef *error) {
return SecError(errSecVerifyFailed, error, CFSTR("RSA signature verification failed, no match"));
}
static CFTypeRef SecKeyRSAVerifyAdaptor(SecKeyOperationContext *context, CFTypeRef signature, CFErrorRef *error,
Boolean (^verifyBlock)(CFDataRef decrypted)) {
CFTypeRef result = NULL;
context->operation = kSecKeyOperationTypeDecrypt;
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSAEncryptionRaw);
result = SecKeyRunAlgorithmAndCopyResult(context, signature, NULL, error);
if (context->mode == kSecKeyOperationModePerform && result != NULL) {
if (verifyBlock(result)) {
CFRetainAssign(result, kCFBooleanTrue);
} else {
CFRetainAssign(result, kCFBooleanFalse);
SecKeyVerifyBadSignature(error);
}
}
return result;
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureRaw(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
return SecKeyRSAVerifyAdaptor(context, in2, error, ^Boolean(CFDataRef decrypted) {
const UInt8 *data = CFDataGetBytePtr(decrypted);
CFIndex length = CFDataGetLength(decrypted);
while (*data == 0x00 && length > 0) {
data++;
length--;
}
return length == CFDataGetLength(in1) && memcmp(CFDataGetBytePtr(in1), data, length) == 0;
});
};
#define PKCS1v15_EMSA_VERIFY_ADAPTOR(name, oid) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15 ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSAVerifyAdaptor(context, in2, error, ^Boolean(CFDataRef decrypted) { \
return ccrsa_emsa_pkcs1v15_verify(CFDataGetLength(decrypted), \
(uint8_t *)CFDataGetBytePtr(decrypted), \
CFDataGetLength(in1), CFDataGetBytePtr(in1), oid) == 0; \
}); \
}
PKCS1v15_EMSA_VERIFY_ADAPTOR(SHA1, ccoid_sha1)
PKCS1v15_EMSA_VERIFY_ADAPTOR(SHA224, ccoid_sha224)
PKCS1v15_EMSA_VERIFY_ADAPTOR(SHA256, ccoid_sha256)
PKCS1v15_EMSA_VERIFY_ADAPTOR(SHA384, ccoid_sha384)
PKCS1v15_EMSA_VERIFY_ADAPTOR(SHA512, ccoid_sha512)
PKCS1v15_EMSA_VERIFY_ADAPTOR(Raw, NULL)
PKCS1v15_EMSA_VERIFY_ADAPTOR(MD5, seckey_ccoid_md5)
#undef PKCS1v15_EMSA_VERIFY_ADAPTOR
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRaw(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit);
return SecKeyAlgorithmAdaptorBigEndianToCCUnit(context, in1, in2, error);
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRawCCUnit(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSAEncryptionRaw);
return SecKeyAlgorithmAdaptorCCUnitToBigEndian(context, in1, in2, error);
}
static CFTypeRef SecKeyRSACopyEncryptedWithPadding(SecKeyOperationContext *context, const struct ccdigest_info *di,
CFDataRef in1, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit);
size_t size = SecKeyGetBlockSize(context->key);
size_t minSize = (di != NULL) ? di->output_size * 2 + 2 : 11;
if (size < minSize) {
return kCFNull;
}
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFTypeRef result = NULL;
PerformWithCFDataBuffer(size, ^(uint8_t *buffer, CFDataRef data) {
int err;
if (di != NULL) {
err = ccrsa_oaep_encode(di, ccrng_seckey, size, (cc_unit *)buffer,
CFDataGetLength(in1), CFDataGetBytePtr(in1));
} else {
err = ccrsa_eme_pkcs1v15_encode(ccrng_seckey, size, (cc_unit *)buffer,
CFDataGetLength(in1), CFDataGetBytePtr(in1));
}
require_noerr_action_quiet(err, out, SecError(errSecParam, error,
CFSTR("RSAencrypt wrong input size (err %d)"), err));
require_quiet(result = SecKeyRunAlgorithmAndCopyResult(context, data, NULL, error), out);
CFAssignRetained(result, SecKeyRSACopyCCUnitToBigEndian(result, SecKeyGetBlockSize(context->key)));
out:;
});
return result;
}
static CFTypeRef SecKeyRSACopyDecryptedWithPadding(SecKeyOperationContext *context, const struct ccdigest_info *di,
CFDataRef in1, CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmRSAEncryptionRawCCUnit);
size_t minSize = (di != NULL) ? di->output_size * 2 + 2 : 11;
if (SecKeyGetBlockSize(context->key) < minSize) {
return kCFNull;
}
if (context->mode == kSecKeyOperationModeCheckIfSupported) {
return SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error);
}
__block CFMutableDataRef result = NULL;
PerformWithBigEndianToCCUnit(in1, SecKeyGetBlockSize(context->key), ^(CFDataRef ccunits) {
CFDataRef cc_result = NULL;
require_quiet(cc_result = SecKeyRunAlgorithmAndCopyResult(context, ccunits, NULL, error), out);
size_t size = CFDataGetLength(cc_result);
result = CFDataCreateMutableWithScratch(NULL, size);
int err;
if (di != NULL) {
err = ccrsa_oaep_decode(di, &size, CFDataGetMutableBytePtr(result),
CFDataGetLength(cc_result), (cc_unit *)CFDataGetBytePtr(cc_result));
} else {
err = ccrsa_eme_pkcs1v15_decode(&size, CFDataGetMutableBytePtr(result),
CFDataGetLength(cc_result), (cc_unit *)CFDataGetBytePtr(cc_result));
}
require_noerr_action_quiet(err, out, (CFReleaseNull(result),
SecError(errSecParam, error, CFSTR("RSAdecrypt wrong input (err %d)"), err)));
CFDataSetLength(result, size);
out:
CFReleaseSafe(cc_result);
});
return result;
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionPKCS1(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
return SecKeyRSACopyEncryptedWithPadding(context, NULL, in1, error);
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionPKCS1(SecKeyOperationContext *context,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
return SecKeyRSACopyDecryptedWithPadding(context, NULL, in1, error);
}
#define RSA_OAEP_CRYPT_ADAPTOR(name, di) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEP ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSACopyEncryptedWithPadding(context, di, in1, error); \
} \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEP ## name( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSACopyDecryptedWithPadding(context, di, in1, error); \
}
RSA_OAEP_CRYPT_ADAPTOR(SHA1, ccsha1_di());
RSA_OAEP_CRYPT_ADAPTOR(SHA224, ccsha224_di());
RSA_OAEP_CRYPT_ADAPTOR(SHA256, ccsha256_di());
RSA_OAEP_CRYPT_ADAPTOR(SHA384, ccsha384_di());
RSA_OAEP_CRYPT_ADAPTOR(SHA512, ccsha512_di());
#undef RSA_OAEP_CRYPT_ADAPTOR
const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterRequestedSize = CFSTR("requestedSize");
const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterSharedInfo = CFSTR("sharedInfo");
static CFTypeRef SecKeyECDHCopyX963Result(SecKeyOperationContext *context, const struct ccdigest_info *di,
CFTypeRef in1, CFTypeRef params, CFErrorRef *error) {
CFTypeRef result = NULL;
require_quiet(result = SecKeyRunAlgorithmAndCopyResult(context, in1, NULL, error), out);
if (context->mode == kSecKeyOperationModePerform) {
CFTypeRef value = NULL;
CFIndex requestedSize = 0;
require_action_quiet((value = CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterRequestedSize)) != NULL
&& CFGetTypeID(value) == CFNumberGetTypeID() &&
CFNumberGetValue(value, kCFNumberCFIndexType, &requestedSize), out,
SecError(errSecParam, error, CFSTR("kSecKeyKeyExchangeParameterRequestedSize is missing")));
size_t sharedInfoLength = 0;
const void *sharedInfo = NULL;
if ((value = CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterSharedInfo)) != NULL &&
CFGetTypeID(value) == CFDataGetTypeID()) {
sharedInfo = CFDataGetBytePtr(value);
sharedInfoLength = CFDataGetLength(value);
}
CFMutableDataRef kdfResult = CFDataCreateMutableWithScratch(kCFAllocatorDefault, requestedSize);
int err = ccansikdf_x963(di, CFDataGetLength(result), CFDataGetBytePtr(result), sharedInfoLength, sharedInfo,
requestedSize, CFDataGetMutableBytePtr(kdfResult));
CFAssignRetained(result, kdfResult);
require_noerr_action_quiet(err, out, (CFReleaseNull(result),
SecError(errSecParam, error, CFSTR("ECDHKeyExchange wrong input (%d)"), err)));
}
out:
return result;
}
#define ECDH_X963_ADAPTOR(hashname, di, cofactor) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDH ## cofactor ## X963 ## hashname( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
CFArrayAppendValue(context->algorithm, kSecKeyAlgorithmECDHKeyExchange ## cofactor); \
return SecKeyECDHCopyX963Result(context, di, in1, in2, error); \
}
ECDH_X963_ADAPTOR(SHA1, ccsha1_di(), Standard)
ECDH_X963_ADAPTOR(SHA224, ccsha224_di(), Standard)
ECDH_X963_ADAPTOR(SHA256, ccsha256_di(), Standard)
ECDH_X963_ADAPTOR(SHA384, ccsha384_di(), Standard)
ECDH_X963_ADAPTOR(SHA512, ccsha512_di(), Standard)
ECDH_X963_ADAPTOR(SHA1, ccsha1_di(), Cofactor)
ECDH_X963_ADAPTOR(SHA224, ccsha224_di(), Cofactor)
ECDH_X963_ADAPTOR(SHA256, ccsha256_di(), Cofactor)
ECDH_X963_ADAPTOR(SHA384, ccsha384_di(), Cofactor)
ECDH_X963_ADAPTOR(SHA512, ccsha512_di(), Cofactor)
#undef ECDH_X963_ADAPTOR
static CFIndex SecKeyGetCFIndexFromRef(CFTypeRef ref) {
CFIndex result = 0;
if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
if (!CFNumberGetValue(ref, kCFNumberCFIndexType, &result)) {
result = 0;
}
} else if (CFGetTypeID(ref) == CFStringGetTypeID()) {
result = CFStringGetIntValue(ref);
}
return result;
}
typedef CFDataRef (*SecKeyECIESKeyExchangeCopyResult)(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm, bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey, CFErrorRef *error);
typedef Boolean (*SecKeyECIESEncryptCopyResult)(CFDataRef keyExchangeResult, CFDataRef inData, CFMutableDataRef result, CFErrorRef *error);
typedef CFDataRef SecKeyECIESDecryptCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error);
static CFTypeRef SecKeyECIESCopyEncryptedData(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
SecKeyECIESKeyExchangeCopyResult keyExchangeCopyResult,
SecKeyECIESEncryptCopyResult encryptCopyResult,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFDictionaryRef parameters = NULL;
SecKeyRef ephemeralPrivateKey = NULL, ephemeralPublicKey = NULL;
CFDataRef pubKeyData = NULL, ephemeralPubKeyData = NULL, keyExchangeResult = NULL;
CFTypeRef result = NULL;
SecKeyRef originalKey = context->key;
CFMutableDataRef ciphertext = NULL;
require_action_quiet(parameters = SecKeyCopyAttributes(context->key), out,
SecError(errSecParam, error, CFSTR("Unable to export key parameters")));
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyType), kSecAttrKeyTypeECSECPrimeRandom), out, result = kCFNull);
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyClass), kSecAttrKeyClassPublic), out, result = kCFNull);
require_quiet(pubKeyData = SecKeyCopyExternalRepresentation(context->key, error), out);
CFAssignRetained(parameters, CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
kSecAttrKeyType, CFDictionaryGetValue(parameters, kSecAttrKeyType),
kSecAttrKeySizeInBits, CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits),
NULL));
require_quiet(ephemeralPrivateKey = SecKeyCreateRandomKey(parameters, error), out);
require_action_quiet(ephemeralPublicKey = SecKeyCopyPublicKey(ephemeralPrivateKey), out,
SecError(errSecParam, error, CFSTR("Unable to get public key from generated ECkey")));
require_quiet(ephemeralPubKeyData = SecKeyCopyExternalRepresentation(ephemeralPublicKey, error), out);
context->key = ephemeralPrivateKey;
require_quiet(keyExchangeResult = keyExchangeCopyResult(context, keyExchangeAlgorithm, true,
ephemeralPubKeyData, pubKeyData, error), out);
if (context->mode == kSecKeyOperationModePerform) {
ciphertext = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, ephemeralPubKeyData);
require_quiet(encryptCopyResult(keyExchangeResult, in1, ciphertext, error), out);
result = CFRetain(ciphertext);
} else {
result = CFRetain(keyExchangeResult);
}
out:
CFReleaseSafe(parameters);
CFReleaseSafe(ephemeralPrivateKey);
CFReleaseSafe(ephemeralPublicKey);
CFReleaseSafe(pubKeyData);
CFReleaseSafe(ephemeralPubKeyData);
CFReleaseSafe(keyExchangeResult);
CFReleaseSafe(ciphertext);
context->key = originalKey;
return result;
}
static CFTypeRef SecKeyECIESCopyDecryptedData(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
SecKeyECIESKeyExchangeCopyResult keyExchangeCopyResult,
SecKeyECIESDecryptCopyResult decryptCopyResult,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFTypeRef result = NULL;
CFDictionaryRef parameters = NULL;
CFDataRef ephemeralPubKeyData = NULL, keyExchangeResult = NULL, pubKeyData = NULL;
SecKeyRef pubKey = NULL;
CFDataRef ciphertext = NULL;
const UInt8 *ciphertextBuffer = NULL;
CFIndex keySize = 0;
require_action_quiet(parameters = SecKeyCopyAttributes(context->key), out,
SecError(errSecParam, error, CFSTR("Unable to export key parameters")));
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyType), kSecAttrKeyTypeECSECPrimeRandom), out, result = kCFNull);
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyClass), kSecAttrKeyClassPrivate), out, result = kCFNull);
if (context->mode == kSecKeyOperationModePerform) {
keySize = (SecKeyGetCFIndexFromRef(CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits)) + 7) / 8;
require_action_quiet(CFDataGetLength(in1) >= keySize * 2 + 1, out,
SecError(errSecParam, error, CFSTR("%@: too small input packet for ECIES decrypt"), context->key));
ciphertextBuffer = CFDataGetBytePtr(in1);
ephemeralPubKeyData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ciphertextBuffer, keySize * 2 + 1, kCFAllocatorNull);
ciphertextBuffer += keySize * 2 + 1;
require_action_quiet(pubKey = SecKeyCopyPublicKey(context->key), out,
SecError(errSecParam, error, CFSTR("%@: Unable to get public key"), context->key));
require_quiet(pubKeyData = SecKeyCopyExternalRepresentation(pubKey, error), out);
}
require_quiet(keyExchangeResult = keyExchangeCopyResult(context, keyExchangeAlgorithm, false,
ephemeralPubKeyData, pubKeyData, error), out);
if (context->mode == kSecKeyOperationModePerform) {
ciphertext = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ciphertextBuffer, CFDataGetLength(in1) - (keySize * 2 + 1),
kCFAllocatorNull);
require_quiet(result = decryptCopyResult(keyExchangeResult, ciphertext, error), out);
} else {
result = CFRetain(keyExchangeResult);
}
out:
CFReleaseSafe(parameters);
CFReleaseSafe(ephemeralPubKeyData);
CFReleaseSafe(keyExchangeResult);
CFReleaseSafe(pubKeyData);
CFReleaseSafe(pubKey);
CFReleaseSafe(ciphertext);
return result;
}
static const CFIndex kSecKeyIESTagLength = 16;
static const UInt8 kSecKeyIESIV[16] = { 0 };
static CFDataRef SecKeyECIESKeyExchangeKDFX963CopyResult(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey,
CFErrorRef *error) {
CFDictionaryRef parameters = NULL;
CFNumberRef keySizeRef = NULL;
CFDataRef result = NULL;
CFArrayAppendValue(context->algorithm, keyExchangeAlgorithm);
context->operation = kSecKeyOperationTypeKeyExchange;
if (context->mode == kSecKeyOperationModePerform) {
CFIndex keySize = ((CFDataGetLength(pubKey) - 1) / 2) * 8;
keySize = (keySize > 256) ? (256 / 8) : (128 / 8);
keySizeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &keySize);
parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
kSecKeyKeyExchangeParameterSharedInfo, ephemeralPubKey,
kSecKeyKeyExchangeParameterRequestedSize, keySizeRef,
NULL);
}
result = SecKeyRunAlgorithmAndCopyResult(context, encrypt ? pubKey : ephemeralPubKey, parameters, error);
CFReleaseSafe(parameters);
CFReleaseSafe(keySizeRef);
return result;
}
static Boolean SecKeyECIESEncryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFMutableDataRef result,
CFErrorRef *error) {
Boolean res = FALSE;
CFIndex prefix = CFDataGetLength(result);
CFDataSetLength(result, prefix + CFDataGetLength(inData) + kSecKeyIESTagLength);
UInt8 *resultBuffer = CFDataGetMutableBytePtr(result) + prefix;
UInt8 *tagBuffer = resultBuffer + CFDataGetLength(inData);
require_action_quiet(ccgcm_one_shot(ccaes_gcm_encrypt_mode(),
CFDataGetLength(keyExchangeResult), CFDataGetBytePtr(keyExchangeResult),
sizeof(kSecKeyIESIV), kSecKeyIESIV,
0, NULL,
CFDataGetLength(inData), CFDataGetBytePtr(inData),
resultBuffer, kSecKeyIESTagLength, tagBuffer) == 0, out,
SecError(errSecParam, error, CFSTR("ECIES: Failed to aes-gcm encrypt data")));
res = TRUE;
out:
return res;
}
static CFDataRef SecKeyECIESDecryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error) {
CFDataRef result = NULL;
CFMutableDataRef plaintext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData) - kSecKeyIESTagLength);
CFMutableDataRef tag = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), kSecKeyIESTagLength);
CFDataGetBytes(inData, CFRangeMake(CFDataGetLength(inData) - kSecKeyIESTagLength, kSecKeyIESTagLength),
CFDataGetMutableBytePtr(tag));
require_action_quiet(ccgcm_one_shot(ccaes_gcm_decrypt_mode(),
CFDataGetLength(keyExchangeResult), CFDataGetBytePtr(keyExchangeResult),
sizeof(kSecKeyIESIV), kSecKeyIESIV,
0, NULL,
CFDataGetLength(plaintext), CFDataGetBytePtr(inData), CFDataGetMutableBytePtr(plaintext),
kSecKeyIESTagLength, CFDataGetMutableBytePtr(tag)) == 0, out,
SecError(errSecParam, error, CFSTR("ECIES: Failed to aes-gcm decrypt data")));
result = CFRetain(plaintext);
out:
CFReleaseSafe(plaintext);
CFReleaseSafe(tag);
return result;
}
#define ECIES_X963_ADAPTOR(hashname, cofactor) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIES ## cofactor ## X963 ## hashname( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyECIESCopyEncryptedData(context, kSecKeyAlgorithmECDHKeyExchange ## cofactor ## X963 ## hashname, \
SecKeyECIESKeyExchangeKDFX963CopyResult, SecKeyECIESEncryptAESGCMCopyResult, in1, in2, error); \
} \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIES ## cofactor ## X963 ## hashname( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyECIESCopyDecryptedData(context, kSecKeyAlgorithmECDHKeyExchange ## cofactor ## X963 ## hashname, \
SecKeyECIESKeyExchangeKDFX963CopyResult, SecKeyECIESDecryptAESGCMCopyResult, in1, in2, error); \
}
ECIES_X963_ADAPTOR(SHA1, Standard)
ECIES_X963_ADAPTOR(SHA224, Standard)
ECIES_X963_ADAPTOR(SHA256, Standard)
ECIES_X963_ADAPTOR(SHA384, Standard)
ECIES_X963_ADAPTOR(SHA512, Standard)
ECIES_X963_ADAPTOR(SHA1, Cofactor)
ECIES_X963_ADAPTOR(SHA224, Cofactor)
ECIES_X963_ADAPTOR(SHA256, Cofactor)
ECIES_X963_ADAPTOR(SHA384, Cofactor)
ECIES_X963_ADAPTOR(SHA512, Cofactor)
#undef ECIES_X963_ADAPTOR
static CFDataRef SecKeyECIESKeyExchangeSHA2562PubKeysCopyResult(SecKeyOperationContext *context, SecKeyAlgorithm keyExchangeAlgorithm,
bool encrypt, CFDataRef ephemeralPubKey, CFDataRef pubKey,
CFErrorRef *error) {
CFArrayAppendValue(context->algorithm, keyExchangeAlgorithm);
context->operation = kSecKeyOperationTypeKeyExchange;
CFMutableDataRef result = (CFMutableDataRef)SecKeyRunAlgorithmAndCopyResult(context, ephemeralPubKey, NULL, error);
if (result != NULL && context->mode == kSecKeyOperationModePerform) {
const struct ccdigest_info *di = ccsha256_di();
ccdigest_di_decl(di, ctx);
ccdigest_init(di, ctx);
ccdigest_update(di, ctx, CFDataGetLength(result), CFDataGetBytePtr(result));
ccdigest_update(di, ctx, CFDataGetLength(ephemeralPubKey), CFDataGetBytePtr(ephemeralPubKey));
ccdigest_update(di, ctx, CFDataGetLength(pubKey), CFDataGetBytePtr(pubKey));
CFAssignRetained(result, CFDataCreateMutableWithScratch(kCFAllocatorDefault, di->output_size));
ccdigest_final(di, ctx, CFDataGetMutableBytePtr(result));
}
return result;
}
static CFDataRef SecKeyECIESDecryptAESCBCCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFErrorRef *error) {
CFMutableDataRef result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData));
cccbc_one_shot(ccaes_cbc_decrypt_mode(),
CFDataGetLength(keyExchangeResult), CFDataGetBytePtr(keyExchangeResult),
NULL, CFDataGetLength(keyExchangeResult) / CCAES_BLOCK_SIZE,
CFDataGetBytePtr(inData), CFDataGetMutableBytePtr(result));
return result;
}
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIES_Standard_SHA256_2PubKeys(
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
return SecKeyECIESCopyDecryptedData(context, kSecKeyAlgorithmECDHKeyExchangeStandard,
SecKeyECIESKeyExchangeSHA2562PubKeysCopyResult,
SecKeyECIESDecryptAESCBCCopyResult,
in1, in2, error);
}
static CFTypeRef SecKeyRSAAESGCMCopyEncryptedData(SecKeyOperationContext *context, SecKeyAlgorithm keyWrapAlgorithm,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFTypeRef result = NULL;
CFDictionaryRef parameters = NULL;
CFDataRef pubKeyData = NULL, wrappedKey = NULL, sessionKey = NULL;
CFMutableDataRef ciphertext = NULL;
require_action_quiet(parameters = SecKeyCopyAttributes(context->key), out,
SecError(errSecParam, error, CFSTR("Unable to export key parameters")));
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyType), kSecAttrKeyTypeRSA), out, result = kCFNull);
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyClass), kSecAttrKeyClassPublic), out, result = kCFNull);
CFArrayAppendValue(context->algorithm, keyWrapAlgorithm);
require_action_quiet(context->mode == kSecKeyOperationModePerform, out,
result = SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error));
require_quiet(pubKeyData = SecKeyCopyExternalRepresentation(context->key, error), out);
CFIndex keySize = SecKeyGetCFIndexFromRef(CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits));
require_action_quiet(sessionKey = CFDataCreateWithRandomBytes((keySize >= 4096) ? (256 / 8) : (128 / 8)), out,
SecError(errSecParam, error, CFSTR("Failed to generate session key")));
require_action_quiet(wrappedKey = SecKeyRunAlgorithmAndCopyResult(context, sessionKey, NULL, error), out,
CFReleaseNull(result));
ciphertext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(wrappedKey) + CFDataGetLength(in1) + kSecKeyIESTagLength);
UInt8 *resultBuffer = CFDataGetMutableBytePtr(ciphertext);
CFDataGetBytes(wrappedKey, CFRangeMake(0, CFDataGetLength(wrappedKey)), resultBuffer);
resultBuffer += CFDataGetLength(wrappedKey);
UInt8 *tagBuffer = resultBuffer + CFDataGetLength(in1);
require_action_quiet(ccgcm_one_shot(ccaes_gcm_encrypt_mode(),
CFDataGetLength(sessionKey), CFDataGetBytePtr(sessionKey),
sizeof(kSecKeyIESIV), kSecKeyIESIV,
CFDataGetLength(pubKeyData), CFDataGetBytePtr(pubKeyData),
CFDataGetLength(in1), CFDataGetBytePtr(in1), resultBuffer,
kSecKeyIESTagLength, tagBuffer) == 0, out,
SecError(errSecParam, error, CFSTR("RSAWRAP: Failed to aes-gcm encrypt data")));
result = CFRetain(ciphertext);
out:
CFReleaseSafe(parameters);
CFReleaseSafe(pubKeyData);
CFReleaseSafe(wrappedKey);
CFReleaseSafe(sessionKey);
CFReleaseSafe(ciphertext);
return result;
}
static CFTypeRef SecKeyRSAAESGCMCopyDecryptedData(SecKeyOperationContext *context, SecKeyAlgorithm keyWrapAlgorithm,
CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
CFTypeRef result = NULL;
CFDictionaryRef parameters = NULL;
CFMutableDataRef plaintext = NULL, tag = NULL;
CFDataRef pubKeyData = NULL, sessionKey = NULL;
SecKeyRef pubKey = NULL;
require_action_quiet(parameters = SecKeyCopyAttributes(context->key), out,
SecError(errSecParam, error, CFSTR("Unable to export key parameters")));
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyType), kSecAttrKeyTypeRSA), out, result = kCFNull);
require_action_quiet(CFEqual(CFDictionaryGetValue(parameters, kSecAttrKeyClass), kSecAttrKeyClassPrivate), out, result = kCFNull);
CFArrayAppendValue(context->algorithm, keyWrapAlgorithm);
require_action_quiet(context->mode == kSecKeyOperationModePerform, out,
result = SecKeyRunAlgorithmAndCopyResult(context, NULL, NULL, error));
require_action_quiet(pubKey = SecKeyCopyPublicKey(context->key), out,
SecError(errSecParam, error, CFSTR("%@: unable to get public key"), context->key));
require_quiet(pubKeyData = SecKeyCopyExternalRepresentation(pubKey, error), out);
CFIndex wrappedKeySize = SecKeyGetBlockSize(context->key);
require_action_quiet(CFDataGetLength(in1) >= wrappedKeySize + kSecKeyIESTagLength, out,
SecError(errSecParam, error, CFSTR("RSA-WRAP too short input data")));
sessionKey = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, CFDataGetBytePtr(in1), wrappedKeySize, kCFAllocatorNull);
CFAssignRetained(sessionKey, SecKeyRunAlgorithmAndCopyResult(context, sessionKey, NULL, error));
require_quiet(sessionKey, out);
CFIndex keySize = SecKeyGetCFIndexFromRef(CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits));
keySize = (keySize >= 4096) ? (256 / 8) : (128 / 8);
require_action_quiet(CFDataGetLength(sessionKey) == keySize, out,
SecError(errSecParam, error, CFSTR("RSA-WRAP bad ciphertext, unexpected session key size")));
plaintext = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), CFDataGetLength(in1) - wrappedKeySize - kSecKeyIESTagLength);
tag = CFDataCreateMutableWithScratch(kCFAllocatorDefault, kSecKeyIESTagLength);
CFDataGetBytes(in1, CFRangeMake(CFDataGetLength(in1) - kSecKeyIESTagLength, kSecKeyIESTagLength),
CFDataGetMutableBytePtr(tag));
const UInt8 *ciphertextBuffer = CFDataGetBytePtr(in1);
ciphertextBuffer += wrappedKeySize;
require_action_quiet(ccgcm_one_shot(ccaes_gcm_decrypt_mode(),
CFDataGetLength(sessionKey), CFDataGetBytePtr(sessionKey),
sizeof(kSecKeyIESIV), kSecKeyIESIV,
CFDataGetLength(pubKeyData), CFDataGetBytePtr(pubKeyData),
CFDataGetLength(plaintext), ciphertextBuffer, CFDataGetMutableBytePtr(plaintext),
kSecKeyIESTagLength, CFDataGetMutableBytePtr(tag)) == 0, out,
SecError(errSecParam, error, CFSTR("RSA-WRAP: Failed to aes-gcm decrypt data")));
result = CFRetain(plaintext);
out:
CFReleaseSafe(parameters);
CFReleaseSafe(sessionKey);
CFReleaseSafe(tag);
CFReleaseSafe(pubKeyData);
CFReleaseSafe(pubKey);
CFReleaseSafe(plaintext);
return result;
}
#define RSA_OAEP_AESGCM_ADAPTOR(hashname) \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEP ## hashname ## AESGCM( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSAAESGCMCopyEncryptedData(context, kSecKeyAlgorithmRSAEncryptionOAEP ## hashname, in1, in2, error); \
} \
static CFTypeRef SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEP ## hashname ## AESGCM( \
SecKeyOperationContext *context, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { \
return SecKeyRSAAESGCMCopyDecryptedData(context, kSecKeyAlgorithmRSAEncryptionOAEP ## hashname, in1, in2, error); \
}
RSA_OAEP_AESGCM_ADAPTOR(SHA1)
RSA_OAEP_AESGCM_ADAPTOR(SHA224)
RSA_OAEP_AESGCM_ADAPTOR(SHA256)
RSA_OAEP_AESGCM_ADAPTOR(SHA384)
RSA_OAEP_AESGCM_ADAPTOR(SHA512)
#undef RSA_OAEP_AESGCM_ADAPTOR
SecKeyAlgorithmAdaptor SecKeyGetAlgorithmAdaptor(SecKeyOperationType operation, SecKeyAlgorithm algorithm) {
static CFDictionaryRef adaptors[kSecKeyOperationTypeCount];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
const void *signKeys[] = {
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5,
kSecKeyAlgorithmRSASignatureRaw,
kSecKeyAlgorithmRSASignatureRawCCUnit,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5,
kSecKeyAlgorithmECDSASignatureMessageX962SHA1,
kSecKeyAlgorithmECDSASignatureMessageX962SHA224,
kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
kSecKeyAlgorithmECDSASignatureMessageX962SHA384,
kSecKeyAlgorithmECDSASignatureMessageX962SHA512,
kSecKeyAlgorithmECDSASignatureDigestX962SHA1,
kSecKeyAlgorithmECDSASignatureDigestX962SHA224,
kSecKeyAlgorithmECDSASignatureDigestX962SHA256,
kSecKeyAlgorithmECDSASignatureDigestX962SHA384,
kSecKeyAlgorithmECDSASignatureDigestX962SHA512,
};
const void *signValues[] = {
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15SHA1,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15SHA224,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15SHA256,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15SHA384,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15SHA512,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15Raw,
SecKeyAlgorithmAdaptorCopyResult_Sign_RSASignatureDigestPKCS1v15MD5,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureRaw,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureRawCCUnit,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA512,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15MD5,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA512,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA512,
};
check_compile_time(array_size(signKeys) == array_size(signValues));
adaptors[kSecKeyOperationTypeSign] = CFDictionaryCreate(kCFAllocatorDefault, signKeys, signValues,
array_size(signKeys), &kCFTypeDictionaryKeyCallBacks, NULL);
const void *verifyKeys[] = {
kSecKeyAlgorithmRSASignatureRaw,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw,
kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,
kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5,
kSecKeyAlgorithmECDSASignatureMessageX962SHA1,
kSecKeyAlgorithmECDSASignatureMessageX962SHA224,
kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
kSecKeyAlgorithmECDSASignatureMessageX962SHA384,
kSecKeyAlgorithmECDSASignatureMessageX962SHA512,
kSecKeyAlgorithmECDSASignatureDigestX962SHA1,
kSecKeyAlgorithmECDSASignatureDigestX962SHA224,
kSecKeyAlgorithmECDSASignatureDigestX962SHA256,
kSecKeyAlgorithmECDSASignatureDigestX962SHA384,
kSecKeyAlgorithmECDSASignatureDigestX962SHA512,
};
const void *verifyValues[] = {
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureRaw,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15SHA1,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15SHA224,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15SHA256,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15SHA384,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15SHA512,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15Raw,
SecKeyAlgorithmAdaptorCopyResult_Verify_RSASignatureDigestPKCS1v15MD5,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15SHA512,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_RSASignatureMessagePKCS1v15MD5,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureMessageX962SHA512,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA1,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA224,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA256,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA384,
SecKeyAlgorithmAdaptorCopyResult_SignVerify_ECDSASignatureDigestX962SHA512,
};
check_compile_time(array_size(verifyKeys) == array_size(verifyValues));
adaptors[kSecKeyOperationTypeVerify] = CFDictionaryCreate(kCFAllocatorDefault, verifyKeys, verifyValues,
array_size(verifyKeys), &kCFTypeDictionaryKeyCallBacks, NULL);
const void *encryptKeys[] = {
kSecKeyAlgorithmRSAEncryptionRaw,
kSecKeyAlgorithmRSAEncryptionRawCCUnit,
kSecKeyAlgorithmRSAEncryptionPKCS1,
kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM,
};
const void *encryptValues[] = {
SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRaw,
SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRawCCUnit,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionPKCS1,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA1,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA224,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA256,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA384,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA512,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA1AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA224AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA256AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA384AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_RSAEncryptionOAEPSHA512AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESStandardX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESStandardX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESStandardX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESStandardX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESStandardX963SHA512,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESCofactorX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESCofactorX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESCofactorX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESCofactorX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_Encrypt_ECIESCofactorX963SHA512,
};
check_compile_time(array_size(encryptKeys) == array_size(encryptValues));
adaptors[kSecKeyOperationTypeEncrypt] = CFDictionaryCreate(kCFAllocatorDefault, encryptKeys, encryptValues,
array_size(encryptKeys), &kCFTypeDictionaryKeyCallBacks, NULL);
const void *decryptKeys[] = {
kSecKeyAlgorithmRSAEncryptionRaw,
kSecKeyAlgorithmRSAEncryptionRawCCUnit,
kSecKeyAlgorithmRSAEncryptionPKCS1,
kSecKeyAlgorithmRSAEncryptionOAEPSHA1,
kSecKeyAlgorithmRSAEncryptionOAEPSHA224,
kSecKeyAlgorithmRSAEncryptionOAEPSHA256,
kSecKeyAlgorithmRSAEncryptionOAEPSHA384,
kSecKeyAlgorithmRSAEncryptionOAEPSHA512,
kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM,
kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM,
kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM,
kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM,
kSecKeyAlgorithmECIESEncryptionAKSSmartCard,
};
const void *decryptValues[] = {
SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRaw,
SecKeyAlgorithmAdaptorCopyResult_EncryptDecrypt_RSAEncryptionRawCCUnit,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionPKCS1,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA1,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA224,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA256,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA384,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA512,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA1AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA224AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA256AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA384AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_RSAEncryptionOAEPSHA512AESGCM,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESStandardX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESStandardX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESStandardX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESStandardX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESStandardX963SHA512,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESCofactorX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESCofactorX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESCofactorX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESCofactorX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIESCofactorX963SHA512,
SecKeyAlgorithmAdaptorCopyResult_Decrypt_ECIES_Standard_SHA256_2PubKeys,
};
check_compile_time(array_size(decryptKeys) == array_size(decryptValues));
adaptors[kSecKeyOperationTypeDecrypt] = CFDictionaryCreate(kCFAllocatorDefault, decryptKeys, decryptValues,
array_size(decryptKeys), &kCFTypeDictionaryKeyCallBacks, NULL);
const void *keyExchangeKeys[] = {
kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,
kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224,
kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256,
kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384,
kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512,
kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1,
kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224,
kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256,
kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384,
kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512,
};
const void *keyExchangeValues[] = {
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHStandardX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHStandardX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHStandardX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHStandardX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHStandardX963SHA512,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHCofactorX963SHA1,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHCofactorX963SHA224,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHCofactorX963SHA256,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHCofactorX963SHA384,
SecKeyAlgorithmAdaptorCopyResult_KeyExchange_ECDHCofactorX963SHA512,
};
check_compile_time(array_size(keyExchangeKeys) == array_size(keyExchangeKeys));
adaptors[kSecKeyOperationTypeKeyExchange] = CFDictionaryCreate(kCFAllocatorDefault, keyExchangeKeys, keyExchangeValues,
array_size(keyExchangeKeys), &kCFTypeDictionaryKeyCallBacks, NULL);
});
return CFDictionaryGetValue(adaptors[operation], algorithm);
}