Wrong HMAC in the implementation of ECIES IEEE1363a

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Wrong HMAC in the implementation of ECIES IEEE1363a

Luca Di Mauro
Hi guys,
I have to implement the ECIES scheme as specified at https://wiki.plugtests.net/ITS-CMS6/images/4/4a/1609.2-consolidated-v4-d8-clean.pdf paragraph 5.3.5, with the KDF and encryption function specified here https://www.etsi.org/deliver/etsi_ts/102900_102999/102941/01.03.01_60/ts_102941v010301p.pdf at annex E.

I wrote an implementation, but the HMAC seems to be wrong.
Here I compute the shared secret and the HMAC value with:
// Computing shared secret using ECSVDP-DHC
EC_KEY_set_flags(osslEphKey, EC_FLAG_COFACTOR_ECDH);
ECDH_compute_key (K, sizeof(K), osslEncPubKey, osslEphKey, &(this->etsiKdf));
free (osslEncPubKey);
free (osslEphKey);
// Setting Ke value (the left-most 16 byte of K)
std::memcpy (Ke, K, Ke_KEY_LENGTH);
// Setting Km value (the remaining 256 bits of K)
memcpy (Km, K+Ke_KEY_LENGTH, Km_KEY_LENGTH);
/* Encrypting "aesKey": C = aesKey XOR Ke */
for(int i=0; i<AES_KEY_SIZE; i++) {
C[i] = aesKeyBuffer[i] ^ Ke[i];
}
// Computing the tag with HMAC (we'll retain the leftmost 16 octets)
if (HMAC(EVP_sha256(), Km, sizeof(Km), C, sizeof(C), hmacResult, &hmacLength) == NULL) {
throw NoesCryptoException ("Cannot perform HMAC");
}

Here :
    "osslEncPubKey" and "osslEphKey" are, respectively, the encryption public key of receiver and the just created ephemeral key;
    "K" is a byte array containing the result of KDF function;
    "Ke" and "Km" the keys used to compute the other encrypted or signed parts;
    "aesKeyBuffer" a byte array containing the AES key used to encrypt with AES-CCM;

The "etsiKdf" function called by ECDH_compute_key is:
void* noes::securityManager::NoesCrypto::etsiKdf (const void* in, size_t inLength, void* out, size_t* outLength) { // TODO FIXME Check me
/* counter 1..2^32
* CB=big endian counter on 32 bits
* SHA256(in||CB)
* counter++, and we do again while we need to generate stream
*/
void *ret = NULL;
int counter = 1;
unsigned char CB[4];
unsigned char HB[EVP_MAX_MD_SIZE];
unsigned int HB_len;
int outputedlen = 0,
remains = *outLength;
EVP_MD_CTX *ctx = NULL;
ctx = EVP_MD_CTX_create();
while (remains > 0) {
// counter++
CB[0] = counter >> 24;
CB[1] = (counter >> 16) & 0xff;
CB[2] = (counter >> 8) & 0xff;
CB[3] = counter & 0xff;
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, in, inLength);
EVP_DigestUpdate(ctx, CB, sizeof(CB));
EVP_DigestFinal_ex(ctx, HB, &HB_len);
if (remains > HB_len) {
memcpy((void*)out+outputedlen, HB, HB_len);
outputedlen += HB_len;
remains -= HB_len;
}
else {
memcpy((void*)out+outputedlen, HB, remains);
outputedlen += remains;
remains -= remains;
}
counter++;
}
ret = out;
std::cout << "\nKDF output length " << *outLength << std::endl;
EVP_MD_CTX_destroy(ctx);
return ret;
}


Can you help me to find the bug?

Luca