| Updated: October 28, 2024 |
The qcrypto library API includes cryptographic KDF functions.
#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