Key Derivation Function (KDF)

Updated: April 19, 2023

The qcrypto library API includes cryptographic KDF functions.

See the library reference for detailed descriptions of the following functions:

KDF examples

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <qcrypto/qcrypto.h>
#include <qcrypto/qcrypto_error.h>
#include <qcrypto/qcrypto_keys.h>
#include <private/qcrypto/qcrypto_internal.h>

int main(void)
{
    int ret;
    int result;
    qcrypto_ctx_t *qctx = NULL;
    qcrypto_ctx_t *qkeyctx = NULL;
    qcrypto_key_t *qkey = NULL;

    const char inkey_hex[] = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b";
    const size_t inkeysize = (sizeof(inkey_hex)-1)/2;
    uint8_t inkeybuf[inkeysize];
    uint8_t *inkey_bin = inkeybuf;

    const char salt_hex[] = "000102030405060708090a0b0c";
    const size_t saltsize = (sizeof(salt_hex)-1)/2;
    uint8_t saltbuf[saltsize];
    uint8_t *salt_bin = saltbuf;

    const char info_hex[] = "f0f1f2f3f4f5f6f7f8f9";
    const size_t infosize = (sizeof(info_hex)-1)/2;
    uint8_t infobuf[infosize];
    uint8_t *info_bin = infobuf;

    const char outkey_hex[] = "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865";
    size_t outkeysize = (sizeof(outkey_hex)-1)/2;
    uint8_t outkey_cmpbuf[outkeysize];
    uint8_t *outkey_cmp = outkey_cmpbuf;
    char outkey_cmp_hexbuf[outkeysize*2];
    char *outkey_cmp_hex = outkey_cmp_hexbuf;

    /* Initialize the Qcrypto Library */
    ret = qcrypto_init(QCRYPTO_INIT_LAZY, NULL);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcryto_init() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Request hkdf-sha256 */
    ret = qcrypto_kdf_request("hkdf-sha256", NULL, 0, &qctx);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_kdf_request() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Convert inkey */
    ret = qcrypto_hex2bin(inkey_bin, inkey_hex, inkeysize);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_hex2bin() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Convert salt */
    ret = qcrypto_hex2bin(salt_bin, salt_hex, saltsize);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_hex2bin() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Convert info */
    ret = qcrypto_hex2bin(info_bin, info_hex, infosize);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_hex2bin() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Initialize KDF arguments */
    qcrypto_kdf_args_t kargs = {
        .secret = inkey_bin,
        .secretsize = inkeysize,
        .salt = salt_bin,
        .saltsize = saltsize,
        .hkdf.info = info_bin,
        .hkdf.infosize = infosize,
    };

    /* Generate a symmetric key via the KDF */
    ret = qcrypto_kdf_generate(qctx, &qkey, outkeysize, &kargs, &qkeyctx);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_kdf_generate() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Save the outkey to a buffer */
    ret = qcrypto_key_to_mem(qkeyctx, qkey, outkey_cmp, &outkeysize);
    if (ret != QCRYPTO_R_EOK) {
        fprintf(stderr, "qcrypto_key_to_mem() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
        goto done;
    }

    /* Convert the outkey */
    qcrypto_bin2hex(outkey_cmp_hex, outkey_cmp, outkeysize);

    /* Compare the results */
    result = memcmp(outkey_cmp_hex, outkey_hex, outkeysize);
    if(result == 0) {
         printf("Computed key matches with expected key\n");
    } else {
         fprintf(stderr, "Computed key failed to match with expected key\n");
    }
    goto done;

done:
    /* Release all context handles */
    qcrypto_release_ctx(qctx);
    qcrypto_release_ctx(qkeyctx);

    /* Release the key handle */
    qcrypto_release_key(qkey);

    /* Uninitialize the Qcrypto Library */
    qcrypto_uninit();

    return ret;
}

#if defined(__QNXNTO__) && defined(__USESRCVERSION)
#include <sys/srcversion.h>
__SRCVERSION("$URL$ $Rev$")
#endif