Search code examples
c#celliptic-curvediffie-hellmanmbedtls

ECDiffieHellman - mbedTLS vs C#


I need to use elliptic curve Diffie Hellman between a ARM cortex M3 and the PC. On the ARM, I use mbed TLS. On the PC side I want to us C# and the ECDiffieHellman(Cng) class.

I can do the ECDH on ARM vs ARM, but I do have trouble when I try to replace one side with the PC.

  1. Problem was the key exchange. I found out, that the key is exported by mbed TLS as <LEN><0x04><X><Y>.

Thus, In C# I am importing the public key using

private static EC

DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
{
    var keyLength = 32;

    if (publicKey[0] != (2 + 2 * keyLength) - 1)
        throw new ArgumentException("Invalid key length", nameof(publicKey));
    if (publicKey[1] != 0x04)
        throw new ArgumentException("Invalid key format", nameof(publicKey));

    var parameters = new ECParameters()
    {
        Curve = ECCurve.NamedCurves.brainpoolP256r1,
        Q = new ECPoint()
        {
            X = publicKey.Skip(2).Take(keyLength).ToArray(),
            Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
        }
    };

    using (var tmp = ECDiffieHellman.Create(parameters))
    {
        return tmp.PublicKey;
    }
}
  1. To generate the key I tried
var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Tls;
ecdh.Seed = new byte[32];
ecdh.Label = Encoding.ASCII.GetBytes("ECDiffieHellman");

new RNGCryptoServiceProvider().GetBytes(ecdh.Seed);

// ...

var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);

My problem is that the generated shared secret is of different length compared to the one generated by mbed TLS and does not match.

Did someone already solve this problem?

Thanks!

EDIT 1:

I forgot to mention, that I use bare ECDH on ARM. So I don't think there is any key derivation function executing. Is it sufficient to hash (SHA256) the result to match the C# side (when configuring SHA256 as KDF there)?


Solution

  • I solved the problem. In short: just hash the ECDH result.

    C/C++ side:

    1. EC Diffie Hellman
    mbedtls_ecdh_init(...);
    mbedtls_ecdh_setup(...);
    mbedtls_ecdh_make_public(...); //make own public key and send it to peer
    mbedtls_ecdh_read_public(...); //reed peers public key
    mbedtls_ecdh_calc_secret(...); //note: i pass in my own RND func because of no OS
    mbedtls_ecdh_free(...);
    
    1. SHA256
    mbedtls_sha256_init(...);
    mbedtls_sha256_starts_ret(...);
    mbedtls_sha256_update_ret(...);
    mbedtls_sha256_finish_ret(...);
    mbedtls_sha256_free(...);
    

    C# side:

    private void EllipticCurveDiffieHellman()
    {
        var ecdh = new ECDiffieHellmanCng(ECCurve.NamedCurves.brainpoolP256r1);
    
        ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        ecdh.HashAlgorithm = CngAlgorithm.Sha256;
    
        //get relevant point from own public key
        var ownPublicKey = ecdh.PublicKey.ExportExplicitParameters().Q;
    
        var peersPublicKey = SendPublicKey(ownPublicKey); //key exchange
        var sharedSecret = ecdh.DeriveKeyMaterial(peersPublicKey);
    
        Console.WriteLine("Key: " + HexValue.Parse(sharedSecret.ToArray()));
    }
    
    DiffieHellmanPublicKey ToPublicKey(byte[] publicKey)
    {
        var keyLength = 32;
    
        if (publicKey[0] != (2 + 2 * keyLength) - 1)
            throw new ArgumentException("Invalid key length", nameof(publicKey));
        if (publicKey[1] != 0x04)
            throw new ArgumentException("Invalid key format", nameof(publicKey));
    
        var parameters = new ECParameters()
        {
            Curve = ECCurve.NamedCurves.brainpoolP256r1,
            Q = new ECPoint()
            {
                X = publicKey.Skip(2).Take(keyLength).ToArray(),
                Y = publicKey.Skip(2 + keyLength).Take(keyLength).ToArray()
            }
        };
    
        using (var tmp = ECDiffieHellman.Create(parameters))
        {
            return tmp.PublicKey;
        }
    }