/* 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 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 ccecies_encrypt_gcm_composite(ccec_pub_ctx_t public_key, const ccecies_gcm_t ecies, uint8_t *exported_public_key, /* output - length from ccecies_pub_key_size */ uint8_t *ciphertext, /* output - length same as plaintext_len */ uint8_t *mac_tag, /* output - length ecies->mac_length */ size_t plaintext_len, const uint8_t *plaintext, size_t sharedinfo1_byte_len, const void *sharedinfo_1, size_t sharedinfo2_byte_len, const void *sharedinfo_2 ) { int status=-1; // Contexts: ccec_full_ctx_decl_cp(ccec_ctx_cp(public_key), ephemeral_key); size_t skey_size = ccec_cp_prime_size(ccec_ctx_cp(public_key)); uint8_t skey[skey_size]; const struct ccmode_gcm *gcm_encrypt=ecies->gcm; ccgcm_ctx_decl(gcm_encrypt->size,gcm_ctx); size_t exported_public_key_size; // 1) Generate ephemeral EC key pair cc_assert(ecies->rng!=NULL); cc_require(ccecdh_generate_key(ccec_ctx_cp(public_key), ecies->rng, ephemeral_key)==0,errOut); #if CC_DEBUG_ECIES ccec_print_full_key("Ephemeral key",ephemeral_key); #endif // 2) ECDH with input public key cc_require(ccecdh_compute_shared_secret(ephemeral_key, public_key, &skey_size, skey,ecies->rng)==0,errOut); #if CC_DEBUG_ECIES cc_print("Shared secret key",skey_size,skey); #endif // 3) Export ephemeral public key cc_require( ccecies_export(0, ecies->options, exported_public_key, ephemeral_key)==0, errOut); // 4) Derive Enc / Mac key // Hash(skey|00000001|sharedinfo_1) cc_assert(ecies->key_length<=skey_size); exported_public_key_size=ccecies_pub_key_size(ephemeral_key,ecies); if (ECIES_EPH_PUBKEY_IN_SHAREDINFO1 == (ecies->options & ECIES_EPH_PUBKEY_IN_SHAREDINFO1)) { // use ephemeral public key as shared info 1 cc_require(ccansikdf_x963(ecies->di, skey_size,skey, exported_public_key_size,exported_public_key, ecies->key_length,skey)==0,errOut); } else { cc_require(ccansikdf_x963(ecies->di, skey_size,skey, sharedinfo1_byte_len,sharedinfo_1, ecies->key_length,skey)==0,errOut); } #if CC_DEBUG_ECIES cc_print("Cipher key",ecies->key_length,skey); #endif // 5) Encrypt ccgcm_init(gcm_encrypt, gcm_ctx,ecies->key_length,skey); ccgcm_set_iv(gcm_encrypt,gcm_ctx,sizeof(ecies_iv_data),ecies_iv_data); if ((sharedinfo_2!=NULL) && (sharedinfo2_byte_len>0)) { ccgcm_gmac(gcm_encrypt,gcm_ctx,sharedinfo2_byte_len,sharedinfo_2); } else { ccgcm_gmac(gcm_encrypt,gcm_ctx,0,NULL); } ccgcm_update(gcm_encrypt,gcm_ctx, plaintext_len,plaintext, ciphertext); #if CC_DEBUG_ECIES cc_print("Encrypted message",plaintext_len,ciphertext); #endif // 6) Mac (with SharedInfo 2) // sec1, p51: recommended: SharedInfo2 ended in a counter giving its length. ccgcm_finalize(gcm_encrypt,gcm_ctx,ecies->mac_length,mac_tag); #if CC_DEBUG_ECIES cc_print("Mac Tag",ecies->mac_length,mac_tag); #endif // Success status=0; errOut: // Clear key material info ccgcm_ctx_clear(gcm_encrypt->size,gcm_ctx); cc_clear(sizeof(skey),skey); ccec_full_ctx_clear_cp(ccec_ctx_cp(public_key), ephemeral_key); return status; }