diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index d2ac7a324..0d322a9a1 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -18,6 +18,7 @@ #include "crypto/libpcrypto.h" #include "crypto/asn1utils.h" +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include "libpcrypto.h" #include "util.h" #include "ui.h" @@ -632,3 +634,34 @@ int blowfish_decrypt(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, return 0; } + +// Implementation from http://www.secg.org/sec1-v2.pdf#subsubsection.3.6.1 +int ansi_x963_sha256(uint8_t *sharedSecret, size_t sharedSecretLen, uint8_t *sharedInfo, size_t sharedInfoLen, size_t keyDataLen, uint8_t *keyData) { + // sha256 hash has (practically) no max input len, so skipping that step + + if (keyDataLen >= 32 * (pow(2, 32) - 1)) { + return 1; + } + + uint32_t counter = 0x00000001; + + for (int i = 0; i < (keyDataLen / 32); ++i) { + uint8_t *hashMaterial = malloc(4 + sharedSecretLen + sharedInfoLen); + memcpy(hashMaterial, sharedSecret, sharedSecretLen); + hashMaterial[sharedSecretLen] = (counter >> 24); + hashMaterial[sharedSecretLen + 1] = (counter >> 16) & 0xFF; + hashMaterial[sharedSecretLen + 2] = (counter >> 8) & 0xFF; + hashMaterial[sharedSecretLen + 3] = counter & 0xFF; + memcpy(hashMaterial + sharedSecretLen + 4, sharedInfo, sharedInfoLen); + + uint8_t hash[32] = {0}; + sha256hash(hashMaterial, 4 + sharedSecretLen + sharedInfoLen, hash); + free(hashMaterial); + + memcpy(keyData + (32 * i), hash, 32); + + counter++; + } + + return 0; +} diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 301633fde..5d10b10ee 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -64,4 +64,7 @@ size_t FindISO9797M2PaddingDataLen(const uint8_t *data, size_t datalen); // BLOWFISH int blowfish_decrypt(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); +// KDF +int ansi_x963_sha256(uint8_t *sharedSecret, size_t sharedSecretLen, uint8_t *sharedInfo, size_t sharedInfoLen, size_t keyDataLen, uint8_t *keyData); + #endif /* libpcrypto.h */