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