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