+++ /dev/null
-/*
- * Copyright (c) 2010-2015 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * SecECKey.c - CoreFoundation based rsa key object
- */
-
-#include "SecECKey.h"
-#include "SecECKeyPriv.h"
-
-#include <Security/SecKeyInternal.h>
-#include <Security/SecItem.h>
-#include <Security/SecBasePriv.h>
-#include <AssertMacros.h>
-#include <Security/SecureTransport.h> /* For error codes. */
-#include <CoreFoundation/CFData.h> /* For error codes. */
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <CoreFoundation/CFNumber.h>
-#include <Security/SecFramework.h>
-#include <Security/SecRandom.h>
-#include <utilities/debugging.h>
-#include "SecItemPriv.h"
-#include <Security/SecInternal.h>
-#include <utilities/SecCFError.h>
-#include <utilities/SecCFWrappers.h>
-#include <utilities/array_size.h>
-#include <corecrypto/ccec.h>
-#include <corecrypto/ccsha1.h>
-#include <corecrypto/ccsha2.h>
-#include <corecrypto/ccrng.h>
-#include <corecrypto/ccder_decode_eckey.h>
-
-#define kMaximumECKeySize 521
-
-static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) {
- return kSecECDSAAlgorithmID;
-}
-
-
-/*
- *
- * Public Key
- *
- */
-
-/* Public key static functions. */
-static void SecECPublicKeyDestroy(SecKeyRef key) {
- /* Zero out the public key */
- ccec_pub_ctx_t pubkey = key->key;
- if (ccec_ctx_cp(pubkey))
- cc_clear(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey);
-}
-
-static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length)
-{
- size_t keysize = ccec_x963_import_pub_size(encoded_length);
- if(ccec_keysize_is_supported(keysize)) {
- return ccec_get_cp(keysize);
- }
- return NULL;
-}
-
-static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length)
-{
- size_t keysize = ccec_x963_import_priv_size(encoded_length);
- if(ccec_keysize_is_supported(keysize)) {
- return ccec_get_cp(keysize);
- }
- return NULL;
-}
-
-static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1;
-static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1;
-static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1;
-static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1;
-static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1;
-
-static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid)
-{
- if (oid!=NULL) {
- if (ccoid_equal(oid, ccoid_secp192r1)) {
- return ccec_cp_192();
- } else if (ccoid_equal(oid, ccoid_secp256r1)) {
- return ccec_cp_256();
- } else if (ccoid_equal(oid, ccoid_secp224r1)) {
- return ccec_cp_224();
- } else if (ccoid_equal(oid, ccoid_secp384r1)) {
- return ccec_cp_384();
- } else if (ccoid_equal(oid, ccoid_secp521r1)) {
- return ccec_cp_521();
- }
- }
- return (ccec_const_cp_t){NULL};
-}
-
-static OSStatus SecECPublicKeyInit(SecKeyRef key,
- const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
- ccec_pub_ctx_t pubkey = 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);
- require_action_quiet(cp, errOut, err = errSecDecode);
-
- /* 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);
- require_action_quiet(cp, errOut, err = errSecDecode);
- err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey)
- ? errSecDecode : errSecSuccess);
- break;
- }
- case kSecExtractPublicFromPrivate:
- {
- ccec_full_ctx_t fullKey = (ccec_full_ctx_t)keyData;
-
- cc_size fullKeyN = ccec_ctx_n(fullKey);
- require_quiet(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut);
- memcpy(pubkey, fullKey, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN)));
- err = errSecSuccess;
- break;
- }
- case kSecKeyEncodingApplePkcs1:
- default:
- err = errSecParam;
- break;
- }
-
-errOut:
- return err;
-}
-
-static CFTypeRef SecECPublicKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
- CFArrayRef algorithms, SecKeyOperationMode mode,
- CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
- if (operation != kSecKeyOperationTypeVerify) {
- // EC public key supports only signature verification.
- return kCFNull;
- }
-
- if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754) || CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
- if (mode == kSecKeyOperationModePerform) {
- bool valid = false;
- int err = -1;
- size_t sigLen = CFDataGetLength(in2);
- uint8_t *sig = (uint8_t *)CFDataGetBytePtr(in2);
- ccec_pub_ctx_t pubkey = key->key;
-
- if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
- err = ccec_verify(pubkey, CFDataGetLength(in1), CFDataGetBytePtr(in1), sigLen, sig, &valid);
- } else {
- if (ccec_signature_r_s_size(pubkey) * 2 != sigLen) {
- SecError(errSecParam, error, CFSTR("bad signature size, got %d, expecting %d bytes"),
- (int)sigLen, (int)ccec_signature_r_s_size(pubkey) * 2);
- return NULL;
- }
- err = ccec_verify_composite(pubkey, CFDataGetLength(in1), CFDataGetBytePtr(in1),
- sig, sig + (sigLen >> 1), &valid);
- }
-
- if (err != 0) {
- SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed (ccerr %d)"), err);
- return NULL;
- } else if (!valid) {
- SecError(errSecVerifyFailed, error, CFSTR("EC signature verification failed, no match"));
- return NULL;
- } else {
- return kCFBooleanTrue;
- }
- } else {
- // Algorithm is supported.
- return kCFBooleanTrue;
- }
- } else {
- // Other algorithms are unsupported.
- return kCFNull;
- }
-}
-
-static size_t SecECPublicKeyBlockSize(SecKeyRef key) {
- /* Get key size in octets */
- return ccec_ctx_size(ccec_ctx_pub(key->key));
-}
-
-/* Encode the public key and return it in a newly allocated CFDataRef. */
-static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator,
- ccec_pub_ctx_t pubkey) {
- size_t pub_size = ccec_export_pub_size(pubkey);
- CFMutableDataRef blob = CFDataCreateMutableWithScratch(allocator, pub_size);
- ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob));
- return blob;
-}
-
-static CFDataRef SecECPublicKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
- ccec_pub_ctx_t pubkey = key->key;
- return SecECPublicKeyExport(NULL, pubkey);
-}
-
-static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
-{
- ccec_pub_ctx_t pubkey = key->key;
-
- CFAllocatorRef allocator = CFGetAllocator(key);
- *serailziation = SecECPublicKeyExport(allocator, pubkey);
-
- if (NULL == *serailziation)
- return errSecDecode;
- else
- return errSecSuccess;
-}
-
-static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) {
- CFDictionaryRef dict = SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC);
- CFMutableDictionaryRef mutableDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
- CFDictionarySetValue(mutableDict, kSecAttrCanDerive, kCFBooleanFalse);
- CFAssignRetained(dict, mutableDict);
- return dict;
-}
-
-static const char *
-getCurveName(SecKeyRef key)
-{
- SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
-
- switch (curveType)
- {
- case kSecECCurveSecp256r1:
- return "kSecECCurveSecp256r1";
- break;
- case kSecECCurveSecp384r1:
- return "kSecECCurveSecp384r1";
- break;
- case kSecECCurveSecp521r1:
- return "kSecECCurveSecp521r1";
- default:
- return "kSecECCurveNone";
- }
-}
-
-static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key)
-{
- CFStringRef keyDescription = NULL;
- CFMutableStringRef strings[2] = { NULL, };
- const char* curve = getCurveName(key);
-
- ccec_pub_ctx_t ecPubkey = key->key;
- size_t len = ccec_ctx_size(ecPubkey);
- uint8_t buffer[len];
- for (int i = 0; i < 2; ++i) {
- ccn_write_uint(ccec_ctx_n(ecPubkey), (i == 0) ? ccec_ctx_x(ecPubkey) : ccec_ctx_y(ecPubkey), len, buffer);
- require_quiet(strings[i] = CFStringCreateMutable(kCFAllocatorDefault, len * 2), fail);
- for (size_t byteIndex = 0; byteIndex < len; ++byteIndex) {
- CFStringAppendFormat(strings[i], NULL, CFSTR("%02X"), buffer[byteIndex]);
- }
- }
-
- keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
- CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>"),
- curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version,
- 8 * SecKeyGetBlockSize(key), strings[1], strings[0], key);
-
-fail:
- CFReleaseSafe(strings[0]);
- CFReleaseSafe(strings[1]);
- if(!keyDescription)
- keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
- CFSTR("<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"),
- curve,(long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version,
- 8 * SecKeyGetBlockSize(key), key);
-
- return keyDescription;
-}
-
-static const struct ccec_rfc6637_curve * get_rfc6637_curve(SecKeyRef key)
-{
- SecECNamedCurve curveType = SecECKeyGetNamedCurve(key);
-
- if (curveType == kSecECCurveSecp256r1) {
- return &ccec_rfc6637_dh_curve_p256;
- } else if (curveType == kSecECCurveSecp521r1) {
- return &ccec_rfc6637_dh_curve_p521;
- }
- return NULL;
-}
-
-static CFDataRef SecECKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
-{
- ccec_pub_ctx_t pubkey = key->key;
- int err = errSecUnimplemented;
- const struct ccec_rfc6637_curve *curve;
- const struct ccec_rfc6637_wrap *wrap = NULL;
- uint8_t sym_alg = 0;
- int32_t flags = 0;
-
- if (type != kSecKeyWrapPublicKeyPGP) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unsupported key wrapping algorithm"));
- return NULL;
- }
-
- curve = get_rfc6637_curve(key);
- if (curve == NULL) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
- return NULL;
- }
-
- CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPSymAlg);
- if (!isNumber(num) || !CFNumberGetValue(num, kCFNumberSInt8Type, &sym_alg)) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unknown symalg given"));
- return NULL;
- }
-
- CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
- if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
- SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
- return NULL;
- }
-
- CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
- if (wrapAlg == NULL) {
- SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
- return NULL;
- } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
- wrap = &ccec_rfc6637_wrap_sha256_kek_aes128;
- } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
- wrap = &ccec_rfc6637_wrap_sha512_kek_aes256;
- } else {
- SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
- return NULL;
- }
-
- num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
- if (isNumber(num)) {
- if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
- SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
- return NULL;
- }
- } else if (num) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
- return NULL;
- }
-
- CFIndex unwrappedKey_size = CFDataGetLength(unwrappedKey);
-
- CFIndex output_size = ccec_rfc6637_wrap_key_size(pubkey, flags, unwrappedKey_size);
- if (output_size == 0) {
- SecError(errSecUnsupportedOperation, error, CFSTR("can't wrap that key, can't build size"));
- return NULL;
- }
-
- CFMutableDataRef data = CFDataCreateMutableWithScratch(NULL, output_size);
- require_quiet(data, errOut);
-
- err = ccec_rfc6637_wrap_key(pubkey, CFDataGetMutableBytePtr(data), flags,
- sym_alg, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey),
- curve, wrap, CFDataGetBytePtr(fingerprint),
- ccrng_seckey);
- if (err) {
- SecError(errSecUnsupportedOperation, error, CFSTR("Failed to wrap key"));
- CFReleaseNull(data);
- }
-
-errOut:
- return data;
-}
-
-SecKeyDescriptor kSecECPublicKeyDescriptor = {
- .version = kSecKeyDescriptorVersion,
- .name = "ECPublicKey",
- .extraBytes = ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)),
- .init = SecECPublicKeyInit,
- .destroy = SecECPublicKeyDestroy,
- .blockSize = SecECPublicKeyBlockSize,
- .copyDictionary = SecECPublicKeyCopyAttributeDictionary,
- .copyExternalRepresentation = SecECPublicKeyCopyExternalRepresentation,
- .describe = SecECPublicKeyCopyKeyDescription,
- .getAlgorithmID = SecECKeyGetAlgorithmID,
- .copyPublic = SecECPublicKeyCopyPublicOctets,
- .copyWrapKey = SecECKeyCopyWrapKey,
- .copyOperationResult = SecECPublicKeyCopyOperationResult,
-};
-
-/* Public Key API functions. */
-SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator,
- const uint8_t *keyData, CFIndex keyDataLength,
- SecKeyEncoding encoding) {
- return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData,
- keyDataLength, encoding);
-}
-
-
-
-/*
- *
- * Private Key
- *
- */
-
-/* Private key static functions. */
-static void SecECPrivateKeyDestroy(SecKeyRef key) {
- /* Zero out the public key */
- ccec_full_ctx_t fullkey = key->key;
-
- if (ccec_ctx_cp(fullkey))
- cc_clear(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey);
-}
-
-
-static OSStatus SecECPrivateKeyInit(SecKeyRef key,
- const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
- ccec_full_ctx_t fullkey = 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 */
- const unsigned char *oid;
- size_t n;
- ccec_const_cp_t cp;
-
- require_noerr_quiet(ccec_der_import_priv_keytype(keyDataLength, keyData, (ccoid_t*)&oid, &n), abort);
- cp = ccec_cp_for_oid(oid);
- if (cp == 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_quiet(cp != NULL, abort, err = errSecDecode);
- ccec_ctx_init(cp, fullkey);
-
- require_noerr_quiet(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort);
- err = errSecSuccess;
- break;
- }
- case kSecKeyEncodingBytes:
- {
- ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength);
- require_quiet(cp != NULL, abort);
-
- ccec_ctx_init(cp, fullkey);
- size_t pubSize = ccec_export_pub_size(ccec_ctx_pub(fullkey));
-
- require(pubSize < (size_t) keyDataLength, abort);
- require_noerr_action_quiet(ccec_import_pub(cp, pubSize, keyData, ccec_ctx_pub(fullkey)),
- abort,
- err = errSecDecode);
-
-
- keyData += pubSize;
- keyDataLength -= pubSize;
-
- cc_unit *k = ccec_ctx_k(fullkey);
- require_noerr_action_quiet(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) {
- secwarning("Invalid or missing key size in: %@", parameters);
- return errSecKeySizeNotAllowed;
- }
-
- if (!ccec_generate_key_fips(cp, ccrng_seckey, fullkey))
- err = errSecSuccess;
- break;
- }
-
- default:
- break;
- }
-abort:
- return err;
-}
-
-static CFTypeRef SecECPrivateKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm,
- CFArrayRef allAlgorithms, SecKeyOperationMode mode,
- CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) {
- // Default answer is 'unsupported', unless we find out that we can support it.
- CFTypeRef result = kCFNull;
-
- ccec_full_ctx_t fullkey = key->key;
- switch (operation) {
- case kSecKeyOperationTypeSign: {
- if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754)) {
- if (mode == kSecKeyOperationModePerform) {
- // Perform r/s mode of signature.
- cc_size r_s_size = ccec_signature_r_s_size(ccec_ctx_public(fullkey));
- result = CFDataCreateMutableWithScratch(NULL, r_s_size << 1);
- uint8_t *signatureBuffer = CFDataGetMutableBytePtr((CFMutableDataRef)result);
- int err = ccec_sign_composite(fullkey, CFDataGetLength(in1), CFDataGetBytePtr(in1),
- signatureBuffer, signatureBuffer + r_s_size, ccrng_seckey);
- require_action_quiet(err == 0, out, (CFReleaseNull(result),
- SecError(errSecParam, error, CFSTR("%@: RFC4754 signing failed (ccerr %d)"),
- key, err)));
- } else {
- // Operation is supported.
- result = kCFBooleanTrue;
- }
- } else if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) {
- if (mode == kSecKeyOperationModePerform) {
- // Perform x962 mode of signature.
- size_t size = ccec_sign_max_size(ccec_ctx_cp(fullkey));
- result = CFDataCreateMutableWithScratch(NULL, size);
- int err = ccec_sign(fullkey, CFDataGetLength(in1), CFDataGetBytePtr(in1),
- &size, CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey);
- require_action_quiet(err == 0, out, (CFReleaseNull(result),
- SecError(errSecParam, error, CFSTR("%@: X962 signing failed (ccerr %d)"),
- key, err)));
- CFDataSetLength((CFMutableDataRef)result, size);
- } else {
- // Operation is supported.
- result = kCFBooleanTrue;
- }
- }
- break;
- }
- case kSecKeyOperationTypeKeyExchange:
- if (CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeStandard) ||
- CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactor)) {
- if (mode == kSecKeyOperationModePerform) {
- int err;
- ccec_const_cp_t cp = getCPForPublicSize(CFDataGetLength(in1));
- require_action_quiet(cp != NULL, out,
- SecError(errSecParam, error, CFSTR("ECpriv sharedsecret: bad public key")));
- ccec_pub_ctx_decl_cp(cp, pubkey);
- err = ccec_import_pub(cp, CFDataGetLength(in1), CFDataGetBytePtr(in1), pubkey);
- require_noerr_action_quiet(err, out, SecError(errSecParam, error,
- CFSTR("ECpriv sharedsecret: bad public key (err %d)"), err));
- size_t size = ccec_ccn_size(cp);
- result = CFDataCreateMutableWithScratch(NULL, size);
- err = ccecdh_compute_shared_secret(fullkey, pubkey, &size,
- CFDataGetMutableBytePtr((CFMutableDataRef)result), ccrng_seckey);
- require_noerr_action_quiet(err, out, (CFReleaseNull(result),
- SecError(errSecDecode, error,
- CFSTR("ECpriv failed to compute shared secret (err %d)"), err)));
- CFDataSetLength((CFMutableDataRef)result, size);
- } else {
- // Operation is supported.
- result = kCFBooleanTrue;
- }
- }
- break;
- default:
- break;
- }
-
-out:
- return result;
-}
-
-static size_t SecECPrivateKeyBlockSize(SecKeyRef key) {
- ccec_full_ctx_t fullkey = key->key;
- /* Get key size in octets */
- return ccec_ctx_size(fullkey);
-}
-
-static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation)
-{
- ccec_full_ctx_t fullkey = key->key;
-
- CFAllocatorRef allocator = CFGetAllocator(key);
- *serailziation = SecECPublicKeyExport(allocator, ccec_ctx_pub(fullkey));
-
- if (NULL == *serailziation)
- return errSecDecode;
- else
- return errSecSuccess;
-}
-
-static CFDataRef SecECPrivateKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) {
- ccec_full_ctx_t fullkey = key->key;
- size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey));
- size_t key_size = ccec_export_pub_size(ccec_ctx_pub(fullkey)) + prime_size;
- CFMutableDataRef blob = CFDataCreateMutableWithScratch(NULL, key_size);
- ccec_export_pub(ccec_ctx_pub(fullkey), CFDataGetMutableBytePtr(blob));
- UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(ccec_ctx_pub(fullkey));
- const cc_unit *k = ccec_ctx_k(fullkey);
- ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest);
- return blob;
-}
-
-static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) {
- /* Export the full ec key pair. */
- CFDataRef fullKeyBlob = SecECPrivateKeyCopyExternalRepresentation(key, NULL);
-
- CFDictionaryRef dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob);
- CFReleaseSafe(fullKeyBlob);
- return dict;
-}
-static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) {
-
- const char* curve = getCurveName(key);
-
- return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve, (long)SecKeyGetAlgorithmId(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key);
-
-}
-
-static CFDataRef SecECKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error)
-{
- const struct ccec_rfc6637_curve *curve;
- const struct ccec_rfc6637_unwrap *unwrap;
- ccec_full_ctx_t fullkey = key->key;
- CFMutableDataRef data;
- int res;
- uint8_t sym_alg = 0;
- int32_t flags = 0;
-
- curve = get_rfc6637_curve(key);
- if (curve == NULL) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve"));
- return NULL;
- }
-
- CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg);
- if (wrapAlg == NULL) {
- SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg"));
- return NULL;
- } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) {
- unwrap = &ccec_rfc6637_unwrap_sha256_kek_aes128;
- } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) {
- unwrap = &ccec_rfc6637_unwrap_sha512_kek_aes256;
- } else {
- SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg"));
- return NULL;
- }
-
- CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint);
- if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) {
- SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint"));
- return NULL;
- }
-
- CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags);
- if (isNumber(num)) {
- if (!CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
- SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num);
- return NULL;
- }
- } else if (num) {
- SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags"));
- return NULL;
- }
-
- size_t keysize = CFDataGetLength(wrappedKey);
- data = CFDataCreateMutableWithScratch(NULL, keysize);
- if (data == NULL)
- return NULL;
-
- res = ccec_rfc6637_unwrap_key(fullkey, &keysize, CFDataGetMutableBytePtr(data),
- flags, &sym_alg, curve, unwrap,
- CFDataGetBytePtr(fingerprint),
- CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey));
- if (res != 0) {
- CFReleaseNull(data);
- SecError(errSecUnsupportedOperation, error, CFSTR("failed to wrap key"));
- return NULL;
- }
- assert(keysize <= (size_t)CFDataGetLength(data));
- CFDataSetLength(data, keysize);
-
- if (outParam) {
- CFMutableDictionaryRef out = CFDictionaryCreateMutableForCFTypes(NULL);
- if (out) {
- CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg);
- if (num) {
- CFDictionarySetValue(out, _kSecKeyWrapPGPSymAlg, num);
- CFRelease(num);
- }
- *outParam = out;
- }
- }
-
- return data;
-}
-
-SecKeyDescriptor kSecECPrivateKeyDescriptor = {
- .version = kSecKeyDescriptorVersion,
- .name = "ECPrivateKey",
- .extraBytes = ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)),
-
- .init = SecECPrivateKeyInit,
- .destroy = SecECPrivateKeyDestroy,
- .blockSize = SecECPrivateKeyBlockSize,
- .copyDictionary = SecECPrivateKeyCopyAttributeDictionary,
- .describe = SecECPrivateKeyCopyKeyDescription,
- .getAlgorithmID = SecECKeyGetAlgorithmID,
- .copyPublic = SecECPrivateKeyCopyPublicOctets,
- .copyExternalRepresentation = SecECPrivateKeyCopyExternalRepresentation,
- .copyWrapKey = SecECKeyCopyWrapKey,
- .copyUnwrapKey = SecECKeyCopyUnwrapKey,
- .copyOperationResult = SecECPrivateKeyCopyOperationResult,
-};
-
-/* Private Key API functions. */
-SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator,
- const uint8_t *keyData, CFIndex keyDataLength,
- SecKeyEncoding encoding) {
- return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData,
- keyDataLength, encoding);
-}
-
-
-OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters,
- SecKeyRef *publicKey, SecKeyRef *privateKey) {
- OSStatus status = errSecParam;
-
- CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */
- SecKeyRef pubKey = NULL;
-
- SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor,
- (const void*) parameters, 0, kSecGenerateKey);
-
- require(privKey, errOut);
-
- /* Create SecKeyRef's from the pkcs1 encoded keys. */
- pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor,
- privKey->key, 0, kSecExtractPublicFromPrivate);
-
- require(pubKey, errOut);
-
- if (publicKey) {
- *publicKey = pubKey;
- pubKey = NULL;
- }
- if (privateKey) {
- *privateKey = privKey;
- privKey = NULL;
- }
-
- status = errSecSuccess;
-
-errOut:
- CFReleaseSafe(pubKey);
- CFReleaseSafe(privKey);
-
- return status;
-}
-
-
-/* It's debatable whether this belongs here or in the ssl code since the
- curve values come from a tls related rfc4492. */
-SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) {
- SecECNamedCurve result = kSecECCurveNone;
- CFDictionaryRef attributes = NULL;
- require_quiet(SecKeyGetAlgorithmId(key) == kSecECDSAAlgorithmID, out);
- require_quiet(attributes = SecKeyCopyAttributes(key), out);
- CFTypeRef bitsRef = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits);
- CFIndex bits = 0;
- require_quiet(bitsRef != NULL && CFGetTypeID(bitsRef) == CFNumberGetTypeID() &&
- CFNumberGetValue(bitsRef, kCFNumberCFIndexType, &bits), out);
- switch (bits) {
-#if 0
- case 192:
- result = kSecECCurveSecp192r1;
- break;
- case 224:
- result = kSecECCurveSecp224r1;
- break;
-#endif
- case 256:
- result = kSecECCurveSecp256r1;
- break;
- case 384:
- result = kSecECCurveSecp384r1;
- break;
- case 521:
- result = kSecECCurveSecp521r1;
- break;
- }
-
-out:
- CFReleaseSafe(attributes);
- return result;
-}
-
-CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) {
- CFDataRef bytes = NULL;
- SecKeyCopyPublicBytes(key, &bytes);
- return bytes;
-}
-
-/* Vile accessors that get us the pub or priv key to use temporarily */
-
-bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_full_ctx_t private)) {
- if (key->key_class == &kSecECPrivateKeyDescriptor) {
- action(key->key);
- } else {
- return SecError(errSecParam, error, CFSTR("Not an EC Full Key object, sorry can't do."));
- }
-
- return true;
-}
-
-bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t public)) {
- if (key->key_class == &kSecECPublicKeyDescriptor) {
- action(key->key);
- } else {
- return SecError(errSecParam, error, CFSTR("Not an EC Public Key object, sorry can't do."));
- }
-
- return true;
-}
-