/* Public key static functions. */ static void SecECPublicKeyDestroy(SecKeyRef key) { /* Zero out the public key */ ccec_pub_ctx_t pubkey; pubkey.pub = key->key; if (ccec_ctx_cp(pubkey).zp) cc_zero(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub); }
/* Private key static functions. */ static void SecECPrivateKeyDestroy(SecKeyRef key) { /* Zero out the public key */ ccec_full_ctx_t fullkey; fullkey.hdr = key->key; if (ccec_ctx_cp(fullkey).zp) cc_zero(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr); }
static OSStatus SecECPublicKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { ccec_pub_ctx_t pubkey; pubkey.pub = key->key; OSStatus err = errSecParam; switch (encoding) { case kSecDERKeyEncoding: { const SecDERKey *derKey = (const SecDERKey *)keyData; if (keyDataLength != sizeof(SecDERKey)) { err = errSecDecode; break; } ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength); /* TODO: Parse and use real params from passed in derKey->algId.params */ err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) ? errSecDecode : errSecSuccess); break; } case kSecKeyEncodingBytes: { ccec_const_cp_t cp = getCPForPublicSize(keyDataLength); err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey) ? errSecDecode : errSecSuccess); break; } case kSecExtractPublicFromPrivate: { ccec_full_ctx_t fullKey; fullKey._full = (ccec_full_ctx *) keyData; cc_size fullKeyN = ccec_ctx_n(fullKey); require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut); memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN))); err = errSecSuccess; break; } case kSecKeyEncodingApplePkcs1: default: err = errSecParam; break; } errOut: return err; }
static CFDataRef SecECPPrivateKeyExport(CFAllocatorRef allocator, ccec_full_ctx_t fullkey) { size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey)); size_t key_size = ccec_export_pub_size(fullkey) + prime_size; CFMutableDataRef blob = CFDataCreateMutable(allocator, key_size); if (blob) { CFDataSetLength(blob, key_size); ccec_export_pub(fullkey, CFDataGetMutableBytePtr(blob)); UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(fullkey); const cc_unit *k = ccec_ctx_k(fullkey); ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest); } return blob; }
int ccec_get_fullkey_components(ccec_full_ctx_t key, size_t *nbits, uint8_t *x, size_t *xsize, uint8_t *y, size_t *ysize, uint8_t *d, size_t *dsize) { cc_size n = ccec_ctx_n(key); size_t len; if(ccec_get_pubkey_components(key, nbits, x, xsize, y, ysize)) return -1; if((len = ccn_write_uint_size(n, ccec_ctx_k(key))) > *dsize) return -1; *dsize = len; ccn_write_uint(n, ccec_ctx_k(key), *dsize, d); return 0; }
static OSStatus SecECPrivateKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { ccec_full_ctx_t fullkey; fullkey.hdr = key->key; OSStatus err = errSecParam; switch (encoding) { case kSecKeyEncodingPkcs1: { /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */ //err = ecc_import(keyData, keyDataLength, fullkey); /* DER != PKCS#1, but we'll go along with it */ ccoid_t oid; size_t n; ccec_const_cp_t cp; require_noerr(ccec_der_import_priv_keytype(keyDataLength, keyData, &oid, &n), abort); cp = ccec_cp_for_oid(oid); if (cp.zp == NULL) { cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */, ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL); } require_action(cp.zp != NULL, abort, err = errSecDecode); ccec_ctx_init(cp, fullkey); require_noerr(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort); err = errSecSuccess; break; } case kSecKeyEncodingBytes: { ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength); require(cp.zp != NULL, abort); ccec_ctx_init(cp, fullkey); size_t pubSize = ccec_export_pub_size(fullkey); require(pubSize < (size_t) keyDataLength, abort); require_noerr_action(ccec_import_pub(cp, pubSize, keyData, fullkey), abort, err = errSecDecode); keyData += pubSize; keyDataLength -= pubSize; cc_unit *k = ccec_ctx_k(fullkey); require_noerr_action(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData), abort, err = errSecDecode); err = errSecSuccess; break; } case kSecGenerateKey: { CFDictionaryRef parameters = (CFDictionaryRef) keyData; CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); CFIndex keyLengthInBits = getIntValue(ksize); ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits); if (!cp.zp) { secwarning("Invalid or missing key size in: %@", parameters); return errSecKeySizeNotAllowed; } if (!ccec_generate_key(cp, ccrng_seckey, fullkey)) err = errSecSuccess; break; } default: break; } abort: return err; }