Ejemplo n.º 1
0
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;
}