1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <openssl/core_names.h> 12e1051a39Sopenharmony_ci#include <openssl/crypto.h> 13e1051a39Sopenharmony_ci#include <openssl/kdf.h> 14e1051a39Sopenharmony_ci#include <openssl/obj_mac.h> 15e1051a39Sopenharmony_ci#include <openssl/params.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci/* 18e1051a39Sopenharmony_ci * test vector from 19e1051a39Sopenharmony_ci * https://datatracker.ietf.org/doc/html/rfc7914 20e1051a39Sopenharmony_ci */ 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci/* 23e1051a39Sopenharmony_ci * Hard coding a password into an application is very bad. 24e1051a39Sopenharmony_ci * It is done here solely for educational purposes. 25e1051a39Sopenharmony_ci */ 26e1051a39Sopenharmony_cistatic unsigned char password[] = { 27e1051a39Sopenharmony_ci 'P', 'a', 's', 's', 'w', 'o', 'r', 'd' 28e1051a39Sopenharmony_ci}; 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/* 31e1051a39Sopenharmony_ci * The salt is better not being hard coded too. Each password should have a 32e1051a39Sopenharmony_ci * different salt if possible. The salt is not considered secret information 33e1051a39Sopenharmony_ci * and is safe to store with an encrypted password. 34e1051a39Sopenharmony_ci */ 35e1051a39Sopenharmony_cistatic unsigned char pbkdf2_salt[] = { 36e1051a39Sopenharmony_ci 'N', 'a', 'C', 'l' 37e1051a39Sopenharmony_ci}; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci/* 40e1051a39Sopenharmony_ci * The iteration parameter can be variable or hard coded. The disadvantage with 41e1051a39Sopenharmony_ci * hard coding them is that they cannot easily be adjusted for future 42e1051a39Sopenharmony_ci * technological improvements appear. 43e1051a39Sopenharmony_ci */ 44e1051a39Sopenharmony_cistatic unsigned int pbkdf2_iterations = 80000; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_cistatic const unsigned char expected_output[] = { 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci 0x4d, 0xdc, 0xd8, 0xf6, 0x0b, 0x98, 0xbe, 0x21, 49e1051a39Sopenharmony_ci 0x83, 0x0c, 0xee, 0x5e, 0xf2, 0x27, 0x01, 0xf9, 50e1051a39Sopenharmony_ci 0x64, 0x1a, 0x44, 0x18, 0xd0, 0x4c, 0x04, 0x14, 51e1051a39Sopenharmony_ci 0xae, 0xff, 0x08, 0x87, 0x6b, 0x34, 0xab, 0x56, 52e1051a39Sopenharmony_ci 0xa1, 0xd4, 0x25, 0xa1, 0x22, 0x58, 0x33, 0x54, 53e1051a39Sopenharmony_ci 0x9a, 0xdb, 0x84, 0x1b, 0x51, 0xc9, 0xb3, 0x17, 54e1051a39Sopenharmony_ci 0x6a, 0x27, 0x2b, 0xde, 0xbb, 0xa1, 0xd0, 0x78, 55e1051a39Sopenharmony_ci 0x47, 0x8f, 0x62, 0xb3, 0x97, 0xf3, 0x3c, 0x8d 56e1051a39Sopenharmony_ci}; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ciint main(int argc, char **argv) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci int rv = 1; 61e1051a39Sopenharmony_ci EVP_KDF *kdf = NULL; 62e1051a39Sopenharmony_ci EVP_KDF_CTX *kctx = NULL; 63e1051a39Sopenharmony_ci unsigned char out[64]; 64e1051a39Sopenharmony_ci OSSL_PARAM params[5], *p = params; 65e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context = NULL; 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 68e1051a39Sopenharmony_ci if (library_context == NULL) { 69e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 70e1051a39Sopenharmony_ci goto end; 71e1051a39Sopenharmony_ci } 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci /* Fetch the key derivation function implementation */ 74e1051a39Sopenharmony_ci kdf = EVP_KDF_fetch(library_context, "PBKDF2", NULL); 75e1051a39Sopenharmony_ci if (kdf == NULL) { 76e1051a39Sopenharmony_ci fprintf(stderr, "EVP_KDF_fetch() returned NULL\n"); 77e1051a39Sopenharmony_ci goto end; 78e1051a39Sopenharmony_ci } 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci /* Create a context for the key derivation operation */ 81e1051a39Sopenharmony_ci kctx = EVP_KDF_CTX_new(kdf); 82e1051a39Sopenharmony_ci if (kctx == NULL) { 83e1051a39Sopenharmony_ci fprintf(stderr, "EVP_KDF_CTX_new() returned NULL\n"); 84e1051a39Sopenharmony_ci goto end; 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci /* Set password */ 88e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, password, 89e1051a39Sopenharmony_ci sizeof(password)); 90e1051a39Sopenharmony_ci /* Set salt */ 91e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, pbkdf2_salt, 92e1051a39Sopenharmony_ci sizeof(pbkdf2_salt)); 93e1051a39Sopenharmony_ci /* Set iteration count (default 2048) */ 94e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, &pbkdf2_iterations); 95e1051a39Sopenharmony_ci /* Set the underlying hash function used to derive the key */ 96e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, 97e1051a39Sopenharmony_ci "SHA256", 0); 98e1051a39Sopenharmony_ci *p = OSSL_PARAM_construct_end(); 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci /* Derive the key */ 101e1051a39Sopenharmony_ci if (EVP_KDF_derive(kctx, out, sizeof(out), params) != 1) { 102e1051a39Sopenharmony_ci fprintf(stderr, "EVP_KDF_derive() failed\n"); 103e1051a39Sopenharmony_ci goto end; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) { 107e1051a39Sopenharmony_ci fprintf(stderr, "Generated key does not match expected value\n"); 108e1051a39Sopenharmony_ci goto end; 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci rv = 0; 112e1051a39Sopenharmony_ciend: 113e1051a39Sopenharmony_ci EVP_KDF_CTX_free(kctx); 114e1051a39Sopenharmony_ci EVP_KDF_free(kdf); 115e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 116e1051a39Sopenharmony_ci return rv; 117e1051a39Sopenharmony_ci} 118