Where can I find the Curve25519 derive method implementation?

667 views Asked by At

I'm playing with python library cryptography using openssl and x25519.

By looking for the code of EVP_PKEY_derive

I can see:

ret = ctx->op.kex.exchange->derive(ctx->op.kex.exchprovctx, key, pkeylen,
                                       SIZE_MAX);

What I'm looking for is the implementation of the derive method for x25519.
But impossible to find it in the openSSL code.

Does someone know where can I find it?

2

There are 2 answers

0
Matt Caswell On BEST ANSWER

You are looking at the OpenSSL 3.0 (master branch) code. That code is in state of flux at the moment because all the internal plumbing is being rewritten. You are probably better looking at the 1.1.1 branch.

The X25519 derive code is here:

https://github.com/openssl/openssl/blob/bf4006a6f9be691ba6eef0e8629e63369a033ccf/crypto/ec/ecx_meth.c#L684-L695

With most of the interesting code in this file:

https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/ec/curve25519.c

0
Guillaume Cisco On

I've finally found where the code lives: libcrypto which can be found in the openbsd project.

EDIT: The below paragraph is for classic Elliptic curve, not X25519
Please see @Matt Caswell answer

EVP_PKEY_derive method can be found here. It uses:

return ctx->pmeth->derive(ctx, key, pkeylen);

leading to definition:

.derive = pkey_ec_kdf_derive,

leading to pkey_ec_kdf_derive and finally to pkey_ec_derive:

static int 
pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen)
{
    int ret;
    size_t outlen;
    const EC_POINT *pubkey = NULL;
    EC_KEY *eckey;
    EC_PKEY_CTX *dctx = ctx->data;

    if (!ctx->pkey || !ctx->peerkey) {
        ECerror(EC_R_KEYS_NOT_SET);
        return 0;
    }

    eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
    if (!key) {
        const EC_GROUP *group;
        group = EC_KEY_get0_group(eckey);
        *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
        return 1;
    }
    pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);

    /*
     * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is
     * not an error, the result is truncated.
     */

    outlen = *keylen;

    ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
    if (ret <= 0)
        return 0;

    *keylen = ret;

    return 1;
}

which uses ECDH_compute_key as expected.