Created
April 23, 2025 02:27
-
-
Save dmaclach/a0f51212e871e19165c6b970bc7158fb to your computer and use it in GitHub Desktop.
Code snippet for converting between OpenSSL types and SecKeyRefs. Hacky, but it worked for my needs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uint8_t get_EC_curve(const EC_key_t ec) | |
{ | |
int nid; | |
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); | |
return get_ec_curve_type(nid); | |
} | |
static EC_KEY *SecKeyToOpenSSLKey(SecKeyRef secKey, int public) { | |
CFErrorRef error; | |
CFDataRef data = SecKeyCopyExternalRepresentation(secKey, &error); | |
if (!data) { | |
fprintf(stderr, "unable to copy external representation"); | |
return NULL; | |
} | |
EC_KEY *ec; | |
if ((ec = EC_KEY_new_by_curve_name( | |
get_ec_curve_nid(get_EC_curve_darwin(secKey)))) == NULL) { | |
log_ssl_err("EC_KEY_new_by_curve_name failed"); | |
return NULL; | |
} | |
CFIndex keylen = CFDataGetLength(data); | |
const unsigned char *buf = CFDataGetBytePtr(data); | |
if (public) { | |
if (!o2i_ECPublicKey(&ec, &buf, keylen)) { | |
fprintf(stderr, "o2i_ECPublicKey failed"); | |
EC_KEY_free(ec); | |
return NULL; | |
} | |
} else { | |
CFDataRef derData; | |
OSStatus status = SecItemExport(secKey, kSecFormatOpenSSL, 0, NULL, &derData); | |
if (status != noErr) { | |
fprintf(stderr, "unable to export: %d", status); | |
return NULL; | |
} | |
unsigned char *defBuf = CFDataGetBytePtr(derData); | |
if (!d2i_ECPrivateKey(&ec, &defBuf, CFDataGetLength(derData))) { | |
fprintf(stderr, "d2i_ECPrivateKey failed"); | |
EC_KEY_free(ec); | |
CFRelease(derData); | |
return NULL; | |
} | |
CFRelease(derData); | |
} | |
if (!EC_KEY_check_key(ec)) { | |
fprintf(stderr, "Conversion Failed"); | |
EC_KEY_free(ec); | |
} | |
return ec; | |
} | |
static SecKeyRef OpenSSLKeyToSecKey(EC_KEY *key, int public) { | |
if (public) { | |
size_t keylen; | |
if ((keylen = i2o_ECPublicKey(key, NULL)) == 0) { | |
log0(0, 0, 0, "error getting size of EC key"); | |
return 0; | |
} | |
unsigned char *buf = safe_malloc(keylen); | |
unsigned char *tmp = buf; | |
// After this call, tmp points to (buf + keylen), | |
// but the exported key lives at buf | |
if (!i2o_ECPublicKey(key, &tmp)) { | |
fprintf(stderr, "i2o_ECPublicKey failed"); | |
free(buf); | |
return NULL; | |
} | |
CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, buf, keylen, kCFAllocatorMalloc); | |
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks , &kCFTypeDictionaryValueCallBacks); | |
CFDictionaryAddValue(dict, kSecAttrKeyType, kSecAttrKeyTypeECDSA); | |
CFDictionaryAddValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPublic); | |
CFErrorRef error; | |
SecKeyRef key = SecKeyCreateWithData(data, dict, &error); | |
CFRelease(data); | |
CFRelease(dict); | |
return key; | |
} else { | |
size_t keylen; | |
if ((keylen = i2d_ECPrivateKey(key, NULL)) == 0) { | |
fprintf(stderr, "error getting size of EC key"); | |
return 0; | |
} | |
unsigned char *buf = safe_malloc(keylen); | |
unsigned char *tmp = buf; | |
// After this call, tmp points to (buf + keylen), | |
// but the exported key lives at buf | |
if (!i2d_ECPrivateKey(key, &tmp)) { | |
fprintf(stderr, "i2o_ECPublicKey failed"); | |
free(buf); | |
return NULL; | |
} | |
CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, buf, keylen, kCFAllocatorMalloc); | |
CFArrayRef array; | |
SecItemImportExportKeyParameters params; | |
bzero(¶ms, sizeof(params)); | |
params.keyAttributes = CFArrayCreate(NULL, &kSecAttrIsExtractable, 1, &kCFTypeArrayCallBacks); | |
OSStatus status = SecItemImport(data, NULL, NULL, NULL, 0, ¶ms, NULL, &array); | |
CFRelease(params.keyAttributes); | |
if (status != noErr) { | |
fprintf(stderr, "SecItemImport failed %d", status); | |
return NULL; | |
} | |
SecKeyRef key = CFArrayGetValueAtIndex(array, 0); | |
CFRetain(key); | |
CFRelease(array); | |
return key; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment