Single step kdf implementation
authorShane Lontis <shane.lontis@oracle.com>
Fri, 4 Jan 2019 08:41:21 +0000 (18:41 +1000)
committerMatt Caswell <matt@openssl.org>
Tue, 19 Mar 2019 11:03:45 +0000 (11:03 +0000)
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8230)

17 files changed:
CHANGES
crypto/err/openssl.txt
crypto/evp/kdf_lib.c
crypto/include/internal/evp_int.h
crypto/kdf/build.info
crypto/kdf/kdf_err.c
crypto/kdf/sskdf.c [new file with mode: 0644]
crypto/objects/obj_dat.h
crypto/objects/obj_mac.num
crypto/objects/objects.txt
doc/man3/EVP_KDF_CTX.pod
doc/man7/EVP_KDF_SS.pod [new file with mode: 0644]
include/openssl/kdf.h
include/openssl/kdferr.h
include/openssl/obj_mac.h
test/evp_kdf_test.c
test/recipes/30-test_evp_data/evpkdf.txt

diff --git a/CHANGES b/CHANGES
index 0f7b77a45be951b9b869d1d3cfaaf64358d0315b..95ae4335019c3888870c8fdbcf3c86bd0a0c30d0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      'enable-buildtest-c++'.
      [Richard Levitte]
 
+  *) Add Single Step KDF (EVP_KDF_SS) to EVP_KDF.
+     [Shane Lontis]
+
+  *) Add KMAC to EVP_MAC.
+     [Shane Lontis]
+
   *) Added property based algorithm implementation selection framework to
      the core.
      [Paul Dale]
index 7c915d46450fc234315e981b66fee33358a38c56..4853a053315bffbf09d606c0cc8475e944df76c3 100644 (file)
@@ -898,6 +898,11 @@ KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
 KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
 KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
 KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf
+KDF_F_SSKDF_CTRL_STR:134:sskdf_ctrl_str
+KDF_F_SSKDF_DERIVE:135:sskdf_derive
+KDF_F_SSKDF_MAC2CTRL:136:sskdf_mac2ctrl
+KDF_F_SSKDF_NEW:137:sskdf_new
+KDF_F_SSKDF_SIZE:138:sskdf_size
 KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
 OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
 OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
@@ -2128,7 +2133,6 @@ CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
 CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
 CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value
 CRMF_R_BAD_PBM_ITERATIONCOUNT:100:bad pbm iterationcount
-CRMF_R_MALFORMED_IV:101:malformed iv
 CRMF_R_CRMFERROR:102:crmferror
 CRMF_R_ERROR:103:error
 CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate
@@ -2136,6 +2140,7 @@ CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate
 CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key
 CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
 CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
+CRMF_R_MALFORMED_IV:101:malformed iv
 CRMF_R_NULL_ARGUMENT:109:null argument
 CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
 CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
@@ -2402,6 +2407,7 @@ EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type
 EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
 EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
 KDF_R_INVALID_DIGEST:100:invalid digest
+KDF_R_INVALID_MAC_TYPE:116:invalid mac type
 KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count
 KDF_R_MISSING_KEY:104:missing key
 KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest
@@ -2414,6 +2420,7 @@ KDF_R_MISSING_SESSION_ID:113:missing session id
 KDF_R_MISSING_TYPE:114:missing type
 KDF_R_MISSING_XCGHASH:115:missing xcghash
 KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
+KDF_R_UNSUPPORTED_MAC_TYPE:117:unsupported mac type
 KDF_R_VALUE_ERROR:108:value error
 KDF_R_VALUE_MISSING:102:value missing
 KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size
index 811fe727f69fbf358fffa3cb110a98e2a8fe0d25..de2ab232e3e98cf92a12b60513e3d6a26b509fbf 100644 (file)
@@ -31,6 +31,7 @@ static const EVP_KDF_METHOD *standard_methods[] = {
     &tls1_prf_kdf_meth,
     &hkdf_kdf_meth,
     &sshkdf_kdf_meth,
+    &ss_kdf_meth
 };
 
 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
index e55c1d9e5b90ca59b10a194d9f347367157ab002..f6f99edb142b69c281ad86c31644e71dc1b99294 100644 (file)
@@ -169,6 +169,7 @@ extern const EVP_KDF_METHOD scrypt_kdf_meth;
 extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
 extern const EVP_KDF_METHOD hkdf_kdf_meth;
 extern const EVP_KDF_METHOD sshkdf_kdf_meth;
+extern const EVP_KDF_METHOD ss_kdf_meth;
 
 struct evp_md_st {
     int type;
index f483c779ddfebdf47adb798b638ddcac00c7babd..52e40a4f2f6488b8d2513709645c3b8653bc3824 100644 (file)
@@ -1,3 +1,4 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
-        tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c sshkdf.c
+        tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c sshkdf.c \
+        sskdf.c
index a70f5219a760165480929f270d897f2f957e690a..84c330fafb4ddc56919b97f53100f288c86f10c9 100644 (file)
@@ -59,12 +59,18 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
      "pkey_tls1_prf_derive"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_SCRYPT_SET_MEMBUF, 0), "scrypt_set_membuf"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_CTRL_STR, 0), "sskdf_ctrl_str"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_DERIVE, 0), "sskdf_derive"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_MAC2CTRL, 0), "sskdf_mac2ctrl"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_NEW, 0), "sskdf_new"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_SIZE, 0), "sskdf_size"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
     {0, NULL}
 };
 
 static const ERR_STRING_DATA KDF_str_reasons[] = {
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_DIGEST), "invalid digest"},
+    {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_MAC_TYPE), "invalid mac type"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_ITERATION_COUNT),
     "missing iteration count"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_KEY), "missing key"},
@@ -80,6 +86,8 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_XCGHASH), "missing xcghash"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE),
     "unknown parameter type"},
+    {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNSUPPORTED_MAC_TYPE),
+    "unsupported mac type"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_OUTPUT_BUFFER_SIZE),
diff --git a/crypto/kdf/sskdf.c b/crypto/kdf/sskdf.c
new file mode 100644 (file)
index 0000000..e999b54
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4.1.
+ *
+ * The Single Step KDF algorithm is given by:
+ *
+ * Result(0) = empty bit string (i.e., the null string).
+ * For i = 1 to reps, do the following:
+ *   Increment counter by 1.
+ *   Result(i) = Result(i – 1) || H(counter || Z || FixedInfo).
+ * DKM = LeftmostBits(Result(reps), L))
+ *
+ * NOTES:
+ *   Z is a shared secret required to produce the derived key material.
+ *   counter is a 4 byte buffer.
+ *   FixedInfo is a bit string containing context specific data.
+ *   DKM is the output derived key material.
+ *   L is the required size of the DKM.
+ *   reps = [L / H_outputBits]
+ *   H(x) is the auxiliary function that can be either a hash, HMAC or KMAC.
+ *   H_outputBits is the length of the output of the auxiliary function H(x).
+ *
+ * Currently there is not a comprehensive list of test vectors for this
+ * algorithm, especially for H(x) = HMAC and H(x) = KMAC.
+ * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests.
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include "internal/cryptlib.h"
+#include "internal/evp_int.h"
+#include "kdf_local.h"
+
+struct evp_kdf_impl_st {
+    const EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */
+    const EVP_MD *md;   /* H(x) = hash OR when H(x) = HMAC_hash */
+    unsigned char *secret;
+    size_t secret_len;
+    unsigned char *info;
+    size_t info_len;
+    unsigned char *salt;
+    size_t salt_len;
+    size_t out_len; /* optional KMAC parameter */
+};
+
+#define SSKDF_MAX_INLEN (1<<30)
+#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4)
+#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4)
+
+/* KMAC uses a Customisation string of 'KDF' */
+static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4. One-Step Key Derivation using H(x) = hash(x)
+ */
+static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
+                          const unsigned char *z, size_t z_len,
+                          const unsigned char *info, size_t info_len,
+                          unsigned char *derived_key, size_t derived_key_len)
+{
+    int ret = 0, hlen;
+    size_t counter, out_len, len = derived_key_len;
+    unsigned char c[4];
+    unsigned char mac[EVP_MAX_MD_SIZE];
+    unsigned char *out = derived_key;
+    EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
+
+    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
+            || derived_key_len > SSKDF_MAX_INLEN
+            || derived_key_len == 0)
+        return 0;
+
+    hlen = EVP_MD_size(kdf_md);
+    if (hlen <= 0)
+        return 0;
+    out_len = (size_t)hlen;
+
+    ctx = EVP_MD_CTX_create();
+    ctx_init = EVP_MD_CTX_create();
+    if (ctx == NULL || ctx_init == NULL)
+        goto end;
+
+    if (!EVP_DigestInit(ctx_init, kdf_md))
+        goto end;
+
+    for (counter = 1;; counter++) {
+        c[0] = (unsigned char)((counter >> 24) & 0xff);
+        c[1] = (unsigned char)((counter >> 16) & 0xff);
+        c[2] = (unsigned char)((counter >> 8) & 0xff);
+        c[3] = (unsigned char)(counter & 0xff);
+
+        if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
+                && EVP_DigestUpdate(ctx, c, sizeof(c))
+                && EVP_DigestUpdate(ctx, z, z_len)
+                && EVP_DigestUpdate(ctx, info, info_len)))
+            goto end;
+        if (len >= out_len) {
+            if (!EVP_DigestFinal_ex(ctx, out, NULL))
+                goto end;
+            out += out_len;
+            len -= out_len;
+            if (len == 0)
+                break;
+        } else {
+            if (!EVP_DigestFinal_ex(ctx, mac, NULL))
+                goto end;
+            memcpy(out, mac, len);
+            break;
+        }
+    }
+    ret = 1;
+end:
+    EVP_MD_CTX_destroy(ctx);
+    EVP_MD_CTX_destroy(ctx_init);
+    OPENSSL_cleanse(mac, sizeof(mac));
+    return ret;
+}
+
+static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
+                     size_t custom_len, size_t kmac_out_len,
+                     size_t derived_key_len, unsigned char **out)
+{
+    /* Only KMAC has custom data - so return if not KMAC */
+    if (custom == NULL)
+        return 1;
+
+    if (!EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, custom, custom_len))
+        return 0;
+
+    /* By default only do one iteration if kmac_out_len is not specified */
+    if (kmac_out_len == 0)
+        kmac_out_len = derived_key_len;
+    /* otherwise check the size is valid */
+    else if (!(kmac_out_len == derived_key_len
+            || kmac_out_len == 20
+            || kmac_out_len == 28
+            || kmac_out_len == 32
+            || kmac_out_len == 48
+            || kmac_out_len == 64))
+        return 0;
+
+    if (!EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SIZE, kmac_out_len))
+        return 0;
+
+    /*
+     * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so
+     * alloc a buffer for this case.
+     */
+    if (kmac_out_len > EVP_MAX_MD_SIZE) {
+        *out = OPENSSL_zalloc(kmac_out_len);
+        if (*out == NULL)
+            return 0;
+    }
+    return 1;
+}
+
+/*
+ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
+ * Section 4. One-Step Key Derivation using MAC: i.e either
+ *     H(x) = HMAC-hash(salt, x) OR
+ *     H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
+ */
+static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
+                         const unsigned char *kmac_custom,
+                         size_t kmac_custom_len, size_t kmac_out_len,
+                         const unsigned char *salt, size_t salt_len,
+                         const unsigned char *z, size_t z_len,
+                         const unsigned char *info, size_t info_len,
+                         unsigned char *derived_key, size_t derived_key_len)
+{
+    int ret = 0;
+    size_t counter, out_len, len;
+    unsigned char c[4];
+    unsigned char mac_buf[EVP_MAX_MD_SIZE];
+    unsigned char *out = derived_key;
+    EVP_MAC_CTX *ctx = NULL, *ctx_init = NULL;
+    unsigned char *mac = mac_buf, *kmac_buffer = NULL;
+
+    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
+            || derived_key_len > SSKDF_MAX_INLEN
+            || derived_key_len == 0)
+        return 0;
+
+    ctx = EVP_MAC_CTX_new(kdf_mac);
+    ctx_init = EVP_MAC_CTX_new(kdf_mac);
+    if (ctx == NULL || ctx_init == NULL)
+        goto end;
+    if (hmac_md != NULL &&
+            !EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, hmac_md))
+        goto end;
+
+    if (!EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, salt, salt_len))
+        goto end;
+
+    if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
+                   derived_key_len, &kmac_buffer))
+        goto end;
+    if (kmac_buffer != NULL)
+        mac = kmac_buffer;
+
+    if (!EVP_MAC_init(ctx_init))
+        goto end;
+
+    out_len = EVP_MAC_size(ctx_init); /* output size */
+    if (out_len <= 0)
+        goto end;
+    len = derived_key_len;
+
+    for (counter = 1;; counter++) {
+        c[0] = (unsigned char)((counter >> 24) & 0xff);
+        c[1] = (unsigned char)((counter >> 16) & 0xff);
+        c[2] = (unsigned char)((counter >> 8) & 0xff);
+        c[3] = (unsigned char)(counter & 0xff);
+
+        if (!(EVP_MAC_CTX_copy(ctx, ctx_init)
+                && EVP_MAC_update(ctx, c, sizeof(c))
+                && EVP_MAC_update(ctx, z, z_len)
+                && EVP_MAC_update(ctx, info, info_len)))
+            goto end;
+        if (len >= out_len) {
+            if (!EVP_MAC_final(ctx, out, NULL))
+                goto end;
+            out += out_len;
+            len -= out_len;
+            if (len == 0)
+                break;
+        } else {
+            if (!EVP_MAC_final(ctx, mac, NULL))
+                goto end;
+            memcpy(out, mac, len);
+            break;
+        }
+    }
+    ret = 1;
+end:
+    OPENSSL_free(kmac_buffer);
+    EVP_MAC_CTX_free(ctx);
+    EVP_MAC_CTX_free(ctx_init);
+    OPENSSL_cleanse(mac, sizeof(mac));
+    return ret;
+}
+
+static EVP_KDF_IMPL *sskdf_new(void)
+{
+    EVP_KDF_IMPL *impl;
+
+    if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
+        KDFerr(KDF_F_SSKDF_NEW, ERR_R_MALLOC_FAILURE);
+    return impl;
+}
+
+static void sskdf_reset(EVP_KDF_IMPL *impl)
+{
+    OPENSSL_clear_free(impl->secret, impl->secret_len);
+    OPENSSL_clear_free(impl->info, impl->info_len);
+    OPENSSL_clear_free(impl->salt, impl->salt_len);
+    memset(impl, 0, sizeof(*impl));
+}
+
+static void sskdf_free(EVP_KDF_IMPL *impl)
+{
+    sskdf_reset(impl);
+    OPENSSL_free(impl);
+}
+
+static int sskdf_set_buffer(va_list args, unsigned char **out, size_t *out_len)
+{
+    const unsigned char *p;
+    size_t len;
+
+    p = va_arg(args, const unsigned char *);
+    len = va_arg(args, size_t);
+    if (len == 0 || p == NULL)
+        return 1;
+
+    OPENSSL_free(*out);
+    *out = OPENSSL_memdup(p, len);
+    if (*out == NULL)
+        return 0;
+
+    *out_len = len;
+    return 1;
+}
+
+static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
+{
+    const EVP_MD *md;
+    const EVP_MAC *mac;
+
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_KEY:
+        return sskdf_set_buffer(args, &impl->secret, &impl->secret_len);
+
+    case EVP_KDF_CTRL_SET_SSKDF_INFO:
+        return sskdf_set_buffer(args, &impl->info, &impl->info_len);
+
+    case EVP_KDF_CTRL_SET_MD:
+        md = va_arg(args, const EVP_MD *);
+        if (md == NULL)
+            return 0;
+
+        impl->md = md;
+        return 1;
+
+    case EVP_KDF_CTRL_SET_MAC:
+        mac = va_arg(args, const EVP_MAC *);
+        if (mac == NULL)
+            return 0;
+
+        impl->mac = mac;
+        return 1;
+
+    case EVP_KDF_CTRL_SET_SALT:
+        return sskdf_set_buffer(args, &impl->salt, &impl->salt_len);
+
+    case EVP_KDF_CTRL_SET_MAC_SIZE:
+        impl->out_len = va_arg(args, size_t);
+        return 1;
+
+    default:
+        return -2;
+    }
+}
+
+/* Pass a mac to a ctrl */
+static int sskdf_mac2ctrl(EVP_KDF_IMPL *impl,
+                          int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                          int cmd, const char *mac_name)
+{
+    const EVP_MAC *mac;
+
+    if (mac_name == NULL || (mac = EVP_get_macbyname(mac_name)) == NULL) {
+        KDFerr(KDF_F_SSKDF_MAC2CTRL, KDF_R_INVALID_MAC_TYPE);
+        return 0;
+    }
+    return call_ctrl(ctrl, impl, cmd, mac);
+}
+
+static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
+                          const char *value)
+{
+    if (strcmp(type, "secret") == 0 || strcmp(type, "key") == 0)
+         return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_KEY,
+                             value);
+
+    if (strcmp(type, "hexsecret") == 0 || strcmp(type, "hexkey") == 0)
+        return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_KEY,
+                            value);
+
+    if (strcmp(type, "info") == 0)
+        return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SSKDF_INFO,
+                            value);
+
+    if (strcmp(type, "hexinfo") == 0)
+        return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SSKDF_INFO,
+                            value);
+
+    if (strcmp(type, "digest") == 0)
+        return kdf_md2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
+
+    if (strcmp(type, "mac") == 0)
+        return sskdf_mac2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value);
+
+    if (strcmp(type, "salt") == 0)
+        return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
+
+    if (strcmp(type, "hexsalt") == 0)
+        return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
+
+
+    if (strcmp(type, "maclen") == 0) {
+        int val = atoi(value);
+        if (val < 0) {
+            KDFerr(KDF_F_SSKDF_CTRL_STR, KDF_R_VALUE_ERROR);
+            return 0;
+        }
+        return call_ctrl(sskdf_ctrl, impl, EVP_KDF_CTRL_SET_MAC_SIZE,
+                         (size_t)val);
+    }
+    return -2;
+}
+
+static size_t sskdf_size(EVP_KDF_IMPL *impl)
+{
+    int len;
+
+    if (impl->md == NULL) {
+        KDFerr(KDF_F_SSKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST);
+        return 0;
+    }
+    len = EVP_MD_size(impl->md);
+    return (len <= 0) ? 0 : (size_t)len;
+}
+
+static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
+{
+    if (impl->secret == NULL) {
+        KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_SECRET);
+        return 0;
+    }
+
+    if (impl->mac != NULL) {
+        /* H(x) = KMAC or H(x) = HMAC */
+        int ret;
+        const unsigned char *custom = NULL;
+        size_t custom_len = 0;
+        int nid;
+        int default_salt_len;
+
+        nid = EVP_MAC_nid(impl->mac);
+        if (nid == EVP_MAC_HMAC) {
+            /* H(x) = HMAC(x, salt, hash) */
+            if (impl->md == NULL) {
+                KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+                return 0;
+            }
+            default_salt_len = EVP_MD_block_size(impl->md);
+            if (default_salt_len <= 0)
+                return 0;
+        } else if (nid == EVP_MAC_KMAC128 || nid == EVP_MAC_KMAC256) {
+            /* H(x) = KMACzzz(x, salt, custom) */
+            custom = kmac_custom_str;
+            custom_len = sizeof(kmac_custom_str);
+            if (nid == EVP_MAC_KMAC128)
+                default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
+            else
+                default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;
+        } else {
+            KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_UNSUPPORTED_MAC_TYPE);
+            return 0;
+        }
+        /* If no salt is set then use a default_salt of zeros */
+        if (impl->salt == NULL || impl->salt_len <= 0) {
+            impl->salt = OPENSSL_zalloc(default_salt_len);
+            if (impl->salt == NULL) {
+                KDFerr(KDF_F_SSKDF_DERIVE, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            impl->salt_len = default_salt_len;
+        }
+        ret = SSKDF_mac_kdm(impl->mac, impl->md,
+                            custom, custom_len, impl->out_len,
+                            impl->salt, impl->salt_len,
+                            impl->secret, impl->secret_len,
+                            impl->info, impl->info_len, key, keylen);
+        return ret;
+    } else {
+        /* H(x) = hash */
+        if (impl->md == NULL) {
+            KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+            return 0;
+        }
+        return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len,
+                              impl->info, impl->info_len, key, keylen);
+    }
+}
+
+const EVP_KDF_METHOD ss_kdf_meth = {
+    EVP_KDF_SS,
+    sskdf_new,
+    sskdf_free,
+    sskdf_reset,
+    sskdf_ctrl,
+    sskdf_ctrl_str,
+    sskdf_size,
+    sskdf_derive
+};
index 913e107974a425287979041276af501420471086..c778d45aa962b9b93d5c738931a9afbf05ed380c 100644 (file)
@@ -1080,7 +1080,7 @@ static const unsigned char so[7775] = {
     0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75,       /* [ 7766] OBJ_SM2_with_SM3 */
 };
 
-#define NUM_NID 1205
+#define NUM_NID 1206
 static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"UNDEF", "undefined", NID_undef},
     {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2287,9 +2287,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"BLAKE2SMAC", "blake2smac", NID_blake2smac},
     {"SSHKDF", "sshkdf", NID_sshkdf},
     {"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7766]},
+    {"SSKDF", "sskdf", NID_sskdf},
 };
 
-#define NUM_SN 1196
+#define NUM_SN 1197
 static const unsigned int sn_objs[NUM_SN] = {
      364,    /* "AD_DVCS" */
      419,    /* "AES-128-CBC" */
@@ -2577,6 +2578,7 @@ static const unsigned int sn_objs[NUM_SN] = {
      100,    /* "SN" */
     1006,    /* "SNILS" */
     1203,    /* "SSHKDF" */
+    1205,    /* "SSKDF" */
       16,    /* "ST" */
      143,    /* "SXNetID" */
     1062,    /* "SipHash" */
@@ -3489,7 +3491,7 @@ static const unsigned int sn_objs[NUM_SN] = {
     1093,    /* "x509ExtAdmission" */
 };
 
-#define NUM_LN 1196
+#define NUM_LN 1197
 static const unsigned int ln_objs[NUM_LN] = {
      363,    /* "AD Time Stamping" */
      405,    /* "ANSI X9.62" */
@@ -4641,6 +4643,7 @@ static const unsigned int ln_objs[NUM_LN] = {
     1133,    /* "sm4-ecb" */
     1135,    /* "sm4-ofb" */
     1203,    /* "sshkdf" */
+    1205,    /* "sskdf" */
       16,    /* "stateOrProvinceName" */
      660,    /* "streetAddress" */
      498,    /* "subtreeMaximumQuality" */
index cfd06d4c291faaad1e039a7855c630b9a2bfa54a..44820a7c8d049208c2fe6239cc90851f2946b1f2 100644 (file)
@@ -1202,3 +1202,4 @@ blake2bmac                1201
 blake2smac             1202
 sshkdf         1203
 SM2_with_SM3           1204
+sskdf          1205
index 78ebff6adac1096a881305c922811ba605f913ce..2240916ff4438ee98cea7723c960c310c83674ac 100644 (file)
@@ -1614,6 +1614,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
 # NID for SSHKDF
                             : SSHKDF            : sshkdf
 
+# NID for SSKDF
+                            : SSKDF              : sskdf
+
 # RFC 4556
 1 3 6 1 5 2 3 : id-pkinit
 id-pkinit 4                     : pkInitClientAuth      : PKINIT Client Auth
index b01c719ceac805b5a7ff6e7df8c196c55537d437..4ca8d94b6e726226aaa1bfaf29c6b06d6916b18c 100644 (file)
@@ -135,6 +135,17 @@ EVP_KDF_ctrl_str() type string: "iter"
 
 The value string is expected to be a decimal number.
 
+=item B<EVP_KDF_CTRL_SET_MAC>
+
+This control expects one argument: C<EVP_MAC *mac>
+
+Some KDF implementations use a MAC as an underlying computation
+algorithm, this control sets what the MAC algorithm should be.
+
+EVP_KDF_ctrl_str() type string: "mac"
+
+The value string is expected to be the name of a MAC.
+
 =item B<EVP_KDF_CTRL_SET_MD>
 
 This control expects one argument: C<EVP_MD *md>
@@ -168,6 +179,19 @@ decoded before being passed on as the control value.
 
 =back
 
+=item B<EVP_KDF_CTRL_SET_MAC_SIZE>
+
+This control expects one argument: C<size_t size>
+
+Used by implementations that use a MAC with a variable output size (KMAC). For
+those KDF implementations that support it, this control sets the MAC output size.
+
+The default value, if any, is implementation dependent.
+
+EVP_KDF_ctrl_str() type string: "outlen"
+
+The value string is expected to be a decimal number.
+
 =item B<EVP_KDF_CTRL_SET_MAXMEM_BYTES>
 
 This control expects one argument: C<uint64_t maxmem_bytes>
@@ -204,10 +228,18 @@ supported by the KDF algorithm.
 =head1 SEE ALSO
 
 L<EVP_KDF_SCRYPT(7)>
+L<EVP_KDF_TLS1_PRF(7)>
+L<EVP_KDF_PBKDF2(7)>
+L<EVP_KDF_HKDF(7)>
+L<EVP_KDF_SS(7)>
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.0.
 
 =head1 COPYRIGHT
 
-Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/doc/man7/EVP_KDF_SS.pod b/doc/man7/EVP_KDF_SS.pod
new file mode 100644 (file)
index 0000000..3702ffe
--- /dev/null
@@ -0,0 +1,226 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF_SS - The Single Step / One Step EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+The EVP_KDF_SS algorithm implements the Single Step key derivation function (SSKDF).
+SSKDF derives a key using input such as a shared secret key (that was generated
+during the execution of a key establishment scheme) and fixedinfo.
+SSKDF is also informally referred to as 'Concat KDF'.
+
+=head2 Auxilary function
+
+The implementation uses a selectable auxiliary function H, which can be one of:
+
+=over 4
+
+=item B<H(x) = hash(x, digest=md)>
+
+=item B<H(x) = HMAC_hash(x, key=salt, digest=md)>
+
+=item B<H(x) = KMACxxx(x, key=salt, custom="KDF", outlen=mac_size)>
+
+=back
+
+Both the HMAC and KMAC implementations set the key using the 'salt' value.
+The hash and HMAC also require the digest to be set.
+
+=head2 Numeric identity
+
+B<EVP_KDF_SS> is the numeric identity for this implementation; it
+can be used with the EVP_KDF_CTX_new_id() function.
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_MD>
+
+=item B<EVP_KDF_CTRL_SET_MAC>
+
+=item B<EVP_MAC_CTRL_SET_MAC_SIZE>
+
+=item B<EVP_KDF_CTRL_SET_SALT>
+
+These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
+
+=item B<EVP_KDF_CTRL_SET_KEY>
+
+This control expects two arguments: C<unsigned char *secret>, C<size_t secretlen>
+
+The shared secret used for key derivation.  This control sets the secret.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "secret"
+
+The value string is used as is.
+
+=item "hexsecret"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_SET_SSKDF_INFO>
+
+This control expects two arguments: C<unsigned char *info>, C<size_t infolen>
+
+An optional value for fixedinfo, also known as otherinfo. This control sets the fixedinfo.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "info"
+
+The value string is used as is.
+
+=item "hexinfo"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=back
+
+=head1 NOTES
+
+A context for SSKDF can be obtained by calling:
+
+EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+
+The output length of an SSKDF is specified via the C<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using H(x) = SHA-256, with the secret key "secret"
+and fixedinfo value "label":
+
+  EVP_KDF_CTX *kctx;
+  unsigned char out[10];
+
+  kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+      error("EVP_KDF_CTRL_SET_MD");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
+      error("EVP_KDF_CTRL_SET_KEY");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, "label", (size_t)5) <= 0) {
+      error("EVP_KDF_CTRL_SET_SSKDF_INFO");
+  }
+  if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+      error("EVP_KDF_derive");
+  }
+
+  EVP_KDF_CTX_free(kctx);
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using H(x) = HMAC(SHA-256), with the secret key "secret",
+fixedinfo value "label" and salt "salt":
+
+  EVP_KDF_CTX *kctx;
+  unsigned char out[10];
+
+  kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC, EVP_get_macbyname("HMAC")) <= 0) {
+      error("EVP_KDF_CTRL_SET_MAC");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+      error("EVP_KDF_CTRL_SET_MD");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
+      error("EVP_KDF_CTRL_SET_KEY");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, "label", (size_t)5) <= 0) {
+      error("EVP_KDF_CTRL_SET_SSKDF_INFO");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
+      error("EVP_KDF_CTRL_SET_SALT");
+  }
+  if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+      error("EVP_KDF_derive");
+  }
+
+  EVP_KDF_CTX_free(kctx);
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using H(x) = KMAC128(x,salt,outlen), with the secret key "secret"
+fixedinfo value "label", salt of "salt" and KMAC outlen of 20:
+
+  EVP_KDF_CTX *kctx;
+  unsigned char out[10];
+
+  kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC, EVP_get_macbyname("KMAC128")) <= 0) {
+      error("EVP_KDF_CTRL_SET_MAC");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+      error("EVP_KDF_CTRL_SET_MD");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
+      error("EVP_KDF_CTRL_SET_KEY");
+  }
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, "label", (size_t)5) <= 0) {
+      error("EVP_KDF_CTRL_SET_SSKDF_INFO");
+  }
+  /* If not specified the salt will be set to a default value */
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
+      error("EVP_KDF_CTRL_SET_SALT");
+  }
+  /* If not specified the default size will be the size of the derived key */
+  if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC_SIZE, (size_t)20) <= 0) {
+      error("EVP_KDF_CTRL_SET_MAC_SIZE");
+  }
+  if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+      error("EVP_KDF_derive");
+  }
+
+  EVP_KDF_CTX_free(kctx);
+
+
+=head1 CONFORMING TO
+
+NIST SP800-56Cr1.
+
+=head1 SEE ALSO
+
+L<EVP_KDF_CTX>,
+L<EVP_KDF_CTX_new_id(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_ctrl(3)>,
+L<EVP_KDF_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF_CTX(3)/CONTROLS>
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.  Copyright
+(c) 2019, Oracle and/or its affiliates.  All rights reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
index acd94491b3cc74c2b084ab7117648a79347a96d5..3a14662800d9583afeccc01968d5f01d0aaf528d 100644 (file)
@@ -23,6 +23,7 @@ extern "C" {
 # define EVP_KDF_TLS1_PRF   NID_tls1_prf
 # define EVP_KDF_HKDF       NID_hkdf
 # define EVP_KDF_SSHKDF     NID_sshkdf
+# define EVP_KDF_SS         NID_sskdf
 
 EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id);
 void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
@@ -53,6 +54,9 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen);
 # define EVP_KDF_CTRL_SET_SSHKDF_XCGHASH    0x10 /* unsigned char *, size_t */
 # define EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID 0x11 /* unsigned char *, size_t */
 # define EVP_KDF_CTRL_SET_SSHKDF_TYPE       0x12 /* int */
+# define EVP_KDF_CTRL_SET_MAC           0x13 /* EVP_MAC * */
+# define EVP_KDF_CTRL_SET_MAC_SIZE      0x14 /* size_t */
+# define EVP_KDF_CTRL_SET_SSKDF_INFO    0x15 /* unsigned char *, size_t */
 
 # define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND  0
 # define EVP_KDF_HKDF_MODE_EXTRACT_ONLY        1
index 9a1d980dac59f7ab23e7d8f7c422758ba227e8f5..bad8f13c42cba3aaaa9d06bc6043374e860db749 100644 (file)
@@ -56,12 +56,18 @@ int ERR_load_KDF_strings(void);
 # define KDF_F_PKEY_TLS1_PRF_DERIVE                       101
 # define KDF_F_PKEY_TLS1_PRF_INIT                         110
 # define KDF_F_SCRYPT_SET_MEMBUF                          129
+# define KDF_F_SSKDF_CTRL_STR                             134
+# define KDF_F_SSKDF_DERIVE                               135
+# define KDF_F_SSKDF_MAC2CTRL                             136
+# define KDF_F_SSKDF_NEW                                  137
+# define KDF_F_SSKDF_SIZE                                 138
 # define KDF_F_TLS1_PRF_ALG                               111
 
 /*
  * KDF reason codes.
  */
 # define KDF_R_INVALID_DIGEST                             100
+# define KDF_R_INVALID_MAC_TYPE                           116
 # define KDF_R_MISSING_ITERATION_COUNT                    109
 # define KDF_R_MISSING_KEY                                104
 # define KDF_R_MISSING_MESSAGE_DIGEST                     105
@@ -74,6 +80,7 @@ int ERR_load_KDF_strings(void);
 # define KDF_R_MISSING_TYPE                               114
 # define KDF_R_MISSING_XCGHASH                            115
 # define KDF_R_UNKNOWN_PARAMETER_TYPE                     103
+# define KDF_R_UNSUPPORTED_MAC_TYPE                       117
 # define KDF_R_VALUE_ERROR                                108
 # define KDF_R_VALUE_MISSING                              102
 # define KDF_R_WRONG_OUTPUT_BUFFER_SIZE                   112
index c8cb5ce92de547bf83efbd4cce19c51d5f07fd28..a0d4eed358fb848e76e07299411a4e174cf72dca 100644 (file)
 #define LN_sshkdf               "sshkdf"
 #define NID_sshkdf              1203
 
+#define SN_sskdf                "SSKDF"
+#define LN_sskdf                "sskdf"
+#define NID_sskdf               1205
+
 #define SN_id_pkinit            "id-pkinit"
 #define NID_id_pkinit           1031
 #define OBJ_id_pkinit           1L,3L,6L,1L,5L,2L,3L
index 923e9aef53af9a6a8810dfb83aef3cc6dbe3dcfc..a664995457e881771b492a10979e68c1f8ec5959 100644 (file)
@@ -225,6 +225,170 @@ err:
 }
 #endif
 
+static int test_kdf_ss_hash(void)
+{
+    EVP_KDF_CTX *kctx;
+    const unsigned char z[] = {
+        0x6d,0xbd,0xc2,0x3f,0x04,0x54,0x88,0xe4,0x06,0x27,0x57,0xb0,0x6b,0x9e,
+        0xba,0xe1,0x83,0xfc,0x5a,0x59,0x46,0xd8,0x0d,0xb9,0x3f,0xec,0x6f,0x62,
+        0xec,0x07,0xe3,0x72,0x7f,0x01,0x26,0xae,0xd1,0x2c,0xe4,0xb2,0x62,0xf4,
+        0x7d,0x48,0xd5,0x42,0x87,0xf8,0x1d,0x47,0x4c,0x7c,0x3b,0x18,0x50,0xe9
+    };
+    const unsigned char other[] = {
+        0xa1,0xb2,0xc3,0xd4,0xe5,0x43,0x41,0x56,0x53,0x69,0x64,0x3c,0x83,0x2e,
+        0x98,0x49,0xdc,0xdb,0xa7,0x1e,0x9a,0x31,0x39,0xe6,0x06,0xe0,0x95,0xde,
+        0x3c,0x26,0x4a,0x66,0xe9,0x8a,0x16,0x58,0x54,0xcd,0x07,0x98,0x9b,0x1e,
+        0xe0,0xec,0x3f,0x8d,0xbe
+    };
+    const unsigned char expected[] = {
+        0xa4,0x62,0xde,0x16,0xa8,0x9d,0xe8,0x46,0x6e,0xf5,0x46,0x0b,0x47,0xb8
+    };
+    unsigned char out[14];
+
+    kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha224()) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MD");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, z, sizeof(z)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_KEY");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, other,
+                     sizeof(other)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_OTHER");
+        return 0;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        return 0;
+    }
+
+    if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
+        return 0;
+
+    EVP_KDF_CTX_free(kctx);
+    return 1;
+}
+
+static int test_kdf_ss_hmac(void)
+{
+    EVP_KDF_CTX *kctx;
+    const EVP_MAC *mac;
+
+    const unsigned char z[] = {
+        0xb7,0x4a,0x14,0x9a,0x16,0x15,0x46,0xf8,0xc2,0x0b,0x06,0xac,0x4e,0xd4
+    };
+    const unsigned char other[] = {
+        0x34,0x8a,0x37,0xa2,0x7e,0xf1,0x28,0x2f,0x5f,0x02,0x0d,0xcc
+    };
+    const unsigned char salt[] = {
+        0x36,0x38,0x27,0x1c,0xcd,0x68,0xa2,0x5d,0xc2,0x4e,0xcd,0xdd,0x39,0xef,
+        0x3f,0x89
+    };
+    const unsigned char expected[] = {
+        0x44,0xf6,0x76,0xe8,0x5c,0x1b,0x1a,0x8b,0xbc,0x3d,0x31,0x92,0x18,0x63,
+        0x1c,0xa3
+    };
+    unsigned char out[16];
+
+    kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+    mac = EVP_get_macbyname("HMAC");
+
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC, mac) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MAC");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MD");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, z, sizeof(z)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_KEY");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, other,
+                     sizeof(other)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_OTHER");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, salt, sizeof(salt)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SALT");
+        return 0;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        return 0;
+    }
+
+    if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
+        return 0;
+
+    EVP_KDF_CTX_free(kctx);
+    return 1;
+}
+
+static int test_kdf_ss_kmac(void)
+{
+    EVP_KDF_CTX *kctx;
+    unsigned char out[64];
+    const EVP_MAC *mac;
+
+    const unsigned char z[] = {
+        0xb7,0x4a,0x14,0x9a,0x16,0x15,0x46,0xf8,0xc2,0x0b,0x06,0xac,0x4e,0xd4
+    };
+    const unsigned char other[] = {
+        0x34,0x8a,0x37,0xa2,0x7e,0xf1,0x28,0x2f,0x5f,0x02,0x0d,0xcc
+    };
+    const unsigned char salt[] = {
+        0x36,0x38,0x27,0x1c,0xcd,0x68,0xa2,0x5d,0xc2,0x4e,0xcd,0xdd,0x39,0xef,
+        0x3f,0x89
+    };
+    const unsigned char expected[] = {
+        0xe9,0xc1,0x84,0x53,0xa0,0x62,0xb5,0x3b,0xdb,0xfc,0xbb,0x5a,0x34,0xbd,
+        0xb8,0xe5,0xe7,0x07,0xee,0xbb,0x5d,0xd1,0x34,0x42,0x43,0xd8,0xcf,0xc2,
+        0xc2,0xe6,0x33,0x2f,0x91,0xbd,0xa5,0x86,0xf3,0x7d,0xe4,0x8a,0x65,0xd4,
+        0xc5,0x14,0xfd,0xef,0xaa,0x1e,0x67,0x54,0xf3,0x73,0xd2,0x38,0xe1,0x95,
+        0xae,0x15,0x7e,0x1d,0xe8,0x14,0x98,0x03
+    };
+
+    kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+    mac = EVP_get_macbyname("KMAC128");
+
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC, mac) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MAC");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, z, sizeof(z)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_KEY");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, other,
+                     sizeof(other)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_OTHER");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, salt, sizeof(salt)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SALT");
+        return 0;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAC_SIZE, (size_t)20) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MACSIZE");
+        return 0;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        return 0;
+    }
+
+    if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
+        return 0;
+
+    EVP_KDF_CTX_free(kctx);
+    return 1;
+}
+
 int setup_tests(void)
 {
     ADD_TEST(test_kdf_tls1_prf);
@@ -233,5 +397,8 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_SCRYPT
     ADD_TEST(test_kdf_scrypt);
 #endif
+    ADD_TEST(test_kdf_ss_hash);
+    ADD_TEST(test_kdf_ss_hmac);
+    ADD_TEST(test_kdf_ss_kmac);
     return 1;
 }
index bbaa24f9bc4ff04293b5143a12aeca5efc773cdb..b3f2b791bc8893f7296dddf0ea0bc1ed0fea75b1 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -5286,3 +5286,1091 @@ Ctrl.hexsession_id = hexsession_id:a4ebd45934f56792b5112dcd75a1075fdc889245
 Ctrl.type = type:A
 Output = FF
 Result = KDF_MISMATCH
+
+#There are currently no official test vectors for Single Step KDF
+#https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
+Title = Single Step KDF tests
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:d09a6b1a472f930db4f5e6b967900744
+Ctrl.hexinfo = hexinfo:b117255ab5f1b6b96fc434b0
+Output = b5a3c52e97ae6e8c5069954354eab3c7
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:343666c0dd34b756e70f759f14c304f5
+Ctrl.hexinfo = hexinfo:722b28448d7eab85491bce09
+Output = 1003b650ddd3f0891a15166db5ec881d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:b84acf03ab08652dd7f82fa956933261
+Ctrl.hexinfo = hexinfo:3d8773ec068c86053a918565
+Output = 1635dcd1ce698f736831b4badb68ab2b
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:8cc24ca3f1d1a8b34783780b79890430
+Ctrl.hexinfo = hexinfo:f08d4f2d9a8e6d7105c0bc16
+Output = b8e716fb84a420aed4812cd76d9700ee
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:b616905a6f7562cd2689142ce21e42a3
+Ctrl.hexinfo = hexinfo:ead310159a909da87e7b4b40
+Output = 1b9201358c50fe5d5d42907c4a9fce78
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:3f57fd3fd56199b3eb33890f7ee28180
+Ctrl.hexinfo = hexinfo:7a5056ba4fdb034c7cb6c4fe
+Output = e51ebd30a8c4b8449b0fb29d9adc11af
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:fb9fb108d104e9f662d6593fc84cde69
+Ctrl.hexinfo = hexinfo:5faf29211c1bdbf1b2696a7c
+Output = 7a3a7e670656e48c390cdd7c51e167e0
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:237a39981794f4516dccffc3dda28396
+Ctrl.hexinfo = hexinfo:62ed9528d104c241e0f66275
+Output = 0c26fc9e90e1c5c5f943428301682045
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:b9b6c45f7279218fa09894e06366a3a1
+Ctrl.hexinfo = hexinfo:0f384339670aaed4b89ecb7e
+Output = ee5fad414e32fad5d52a2bf61a7f6c72
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:08b7140e2cd0a4abd79171e4d5a71cad
+Ctrl.hexinfo = hexinfo:099211f0d8a2e02dbb5958c0
+Output = 6162f5142e057efafd2c4f2bad5985a1
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a2
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f4853
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759a
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac704
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbe
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf1050
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f3
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8b
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f22
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f227688
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abf
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d480d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690
+Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b
+Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d480d9192
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:d7e6
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 31e798e9931b612a3ad1b9b1008faa8c
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:4646779d
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 139f68bcca879b490e268e569087d04d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:d9811c81d4c6
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 914dc4f09cb633a76e6c389e04c64485
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:8838f9d99ec46f09
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 4f07dfb6f7a5bf348689e08b2e29c948
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:3e0939b33f34e779f30e
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = b42c7a98c23be19d1187ff960e87557f
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:f36230cacca4d245d303058c
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 50f2068d8010d355d56c5e34aaffbc67
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:7005d32c3d4284c73c3aefc70438
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 66fd712ccf5462bbd41e89041ea7ea26
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:c01c83150b7734f8dbd6efd6f54d7365
+Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff
+Output = 5c5edb0ceda9cd0c7f1f3d9e239c67d5
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:9949
+Output = 33c83f54ed00fb1bccd2113e88550941
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:17144da6
+Output = a999c28961424cab35ec06015e8c376a
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:dffdee1062eb
+Output = 4101ad50e626ed6f957bff926dfbb7db
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:9f365043e23b4648
+Output = 4d3e4b971b88771f229df9f564984832
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:a885a0c4567ddc4f96da
+Output = bebbc30f5a83df5e9c9b57db33c0c879
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:c9d86183295bfe4c3d85f0fd
+Output = 87c947e45407db63eb94cbaa02d14e94
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:825fadce46964236a486732c5dad
+Output = 192370a85ff78e3c0245129d9b398558
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9
+Ctrl.hexinfo = hexinfo:5c0b5eb3ac9f342347d73d7a521723aa
+Output = c7b7634fd809383e87c4b1b3e728be56
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:8d7a4e7d5cf34b3f74873b862aeb33b7
+Output = 6a5594f402f74f69
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:9b208e7ee1e641fac1dff48fc1beb2d2
+Output = 556ed67e24ac0c7c46cc432da8bdb23c
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:4d2572539fed433211da28c8a0eebac3
+Output = 5a4054c59c5b92814025578f43c1b79fe84968fc284e240b
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:4e1e70c9886819a31bc29a537911add9
+Output = ddbfc440449aab4131c6d8aec08ce1496f2702241d0e27cc155c5c7c3cda75b5
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:68f144c952528e540c686dc353b766f2
+Output = 59ed66bb6f54a9688a0b891d0b2ea6743621d9e1b5cc098cf3a55e6f864f9af8a95e4d945d2f987f
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:b66c9d507c9f837fbe60b6675fdbf38b
+Output = c282787ddf421a72fc88811be81b08d0d6ab66c92d1011974aa58335a6bbbd62e9e982bfae5929865ea1d517247089d2
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:34e730b49e46c7ed2fb25975a4cccd2d
+Output = 39e76e6571cb00740260b9070accbdcc4a492c295cbef33d9e37dac21e5e9d07e0f12dc7063d2172641475d4e08b8e3712fb26a10c8376b8
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA1
+Ctrl.hexsecret = hexsecret:e340d87e2d7adbc1b95ec2dbdc3b82be
+Output = a660c0037a53f76f1e7667043f5869348ad07ac0e272e615ce31f16d4ab90d4b35fe5c370c0010ce79aff45682c6fb8b97f9a05b7d40b5af3c62999a10df9c6d
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:afc4e154498d4770aa8365f6903dc83b
+Ctrl.hexinfo = hexinfo:662af20379b29d5ef813e655
+Output = f0b80d6ae4c1e19e2105a37024e35dc6
+
+
+KDF = SSKDF
+Ctrl.digest = digest:SHA512
+Ctrl.hexsecret = hexsecret:108cf63318555c787fa578731dd4f037
+Ctrl.hexinfo = hexinfo:53191b1dd3f94d83084d61d6
+Output = 0ad475c1826da3007637970c8b92b993
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:6ee6c00d70a6cd14bd5a4e8fcfec8386
+Ctrl.hexsalt = hexsalt:532f5131e0a2fecc722f87e5aa2062cb
+Ctrl.hexinfo = hexinfo:861aa2886798231259bd0314
+Output = 13479e9a91dd20fdd757d68ffe8869fb
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:cb09b565de1ac27a50289b3704b93afd
+Ctrl.hexsalt = hexsalt:d504c1c41a499481ce88695d18ae2e8f
+Ctrl.hexinfo = hexinfo:5ed3768c2c7835943a789324
+Output = f081c0255b0cae16edc6ce1d6c9d12bc
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:98f50345fd970639a1b7935f501e1d7c
+Ctrl.hexsalt = hexsalt:3691939461247e9f74382ae4ef629b17
+Ctrl.hexinfo = hexinfo:6ddbdb1314663152c3ccc192
+Output = 56f42183ed3e287298dbbecf143f51ac
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a72b0076221727eca4d3ef8f4d88ac96
+Ctrl.hexsalt = hexsalt:397dc6807de2c1d5ba52e03c4e6c7a19
+Ctrl.hexinfo = hexinfo:12379bd7873a7dbabe894ac8
+Output = 26c0f937e8ca337a859b6c092fe22b9a
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0b09bf8ebe1e85a049174c521e35be64
+Ctrl.hexsalt = hexsalt:313d29bbeaa5ac9e52278f7619d29d93
+Ctrl.hexinfo = hexinfo:e2ac98de1486959bfc6363c0
+Output = 4bfdf78782a45e2a5858edb851c5783c
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e907ad4fe811ee047af77e0c4418226a
+Ctrl.hexsalt = hexsalt:5000ef57104ca2e86a5fec5883ea4ea8
+Ctrl.hexinfo = hexinfo:c4ee443920f2b7542eee2a24
+Output = 06bfbd9571462c920a5a1b589c765383
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:608dae15fe8b906d2dc649815bdee148
+Ctrl.hexsalt = hexsalt:742cc5a02a24d09c66fd9da0d0c571f6
+Ctrl.hexinfo = hexinfo:ba60ff781e2756cba07f6524
+Output = 7f7f9e5d8f89a8edd10289f1d690f629
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:eb39e8dc7c40b906216108e2592bb6cd
+Ctrl.hexsalt = hexsalt:af9f612da575c1afc8c4afff4ced34e1
+Ctrl.hexinfo = hexinfo:84b7f0628df0cb22baaa279a
+Output = 5202576c69c6276daedf4916de250d19
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:4bac0c1a963b8cf6933beb2ad191a31e
+Ctrl.hexsalt = hexsalt:debd24d71a1a7ae77f7e3aa24d939635
+Ctrl.hexinfo = hexinfo:9e51c8593cec92c89e82439a
+Output = ecb9889f9004f80716b56c44910f160c
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:8aa41e3c8076ea01ca6789dd18709a68
+Ctrl.hexsalt = hexsalt:7c9dacc409cde7b05efdae07bd9973db
+Ctrl.hexinfo = hexinfo:52651f0f2e858bbfbacb2533
+Output = b8683c9a982e0826d659a1ab77a603d7
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d3
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d8
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d89102
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be0
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f2
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c504
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a1
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca6
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd99
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995de
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c710
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca9091
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab6
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7fe19
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7fe193c95
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7fe193c9546d4
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7fe193c9546d45849
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:02b40d33e3f685aeae677ac344eeaf77
+Ctrl.hexsalt = hexsalt:0ad52c9357c85e4781296a36ca72039c
+Ctrl.hexinfo = hexinfo:c67c389580128f18f6cf8592
+Output = be32e7d306d891028be088f213f9f947c50420d9b5a12ca69818dd9995dedd8e6137c7104d67f2ca90915dda0ab68af2f355b904f9eb0388b5b7fe193c9546d45849133d
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:f4e1
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = 3f661ec46fcc1e110b88f33ee7dbc308
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:253554e5
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = 73ccb357554ca44967d507518262e38d
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e10d0e0bc95b
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = c4f1cf190980b6777bb35107654b25f9
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:451f7f2c23c51326
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = ddb2d7475d00cc65bff6904b4f0b54ba
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0f27277ee800d6cc5425
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = 1100a6049ae9d8be01ab3829754cecc2
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:20438ff1f26390dbc3a1a6d0
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = 5180382f740444ada597197f98e73e1e
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:b74a149a161546f8c20b06ac4ed4
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = 44f676e85c1b1a8bbc3d319218631ca3
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:8aa7df46b8cb3fe47228494f4e116b2c
+Ctrl.hexsalt = hexsalt:3638271ccd68a25dc24ecddd39ef3f89
+Ctrl.hexinfo = hexinfo:348a37a27ef1282f5f020dcc
+Output = ebb24413855a0a3249960d0de0f4750d
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:d851
+Output = 5dbe10ead8f81a81a29072eca4501658
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:b04da03c
+Output = 0a08d7616dcbec25a36f1936b82992ca
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:f9e8b47eade3
+Output = 84a29697445179b662d85dbc59bf8042
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:5b141bfa54fcf824
+Output = be7660c840644cec84d67d95ba7ebf2d
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:736e7ddb856f0ba14744
+Output = e3010b1fbcb02fd8baa8449ac71d0c62
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:c54320ff6e7d1a3b0b3aea00
+Output = df0ac84982999cda676e4cbf707c42f0
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:37ab143e1b4ab61d0294ea8afbc7
+Output = 93eec7f4dda18b7e710dbbd7570ebd13
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a678236b6ac82077b23f73a510c1d0e2
+Ctrl.hexsalt = hexsalt:46ee4f36a4167a09cde5a33b130c6e1c
+Ctrl.hexinfo = hexinfo:c3146575d2c60981511e700902fc2ac1
+Output = e9125f77d699faa53d5bc48f3fc2f7d0
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:1ae1
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = ddf7eedcd997eca3943d4519aaf414f4
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:3bda13b6
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = ec783ca20501df3cacac5ab4adbc6427
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:c792f52e5876
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = 9303a2562e6f8c418e3fcc081b94bdcf
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:a9b7a64840d52633
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = aab6b0dc19bae0dd7fa02391ac3d6ef1
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:8f62a3ec15cdf9b3522f
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = 1516d5ed7f46474d250408b0864647cf
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:55ed67cbdc98ed8e45214704
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = 38bf96a3d737a84dc10a835d340b6866
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:e4946aff3b2ab891b311234c77bc
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = 3ddd870471ff028a63c5f1bacc7e5b5c
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0031558fddb96e3db2e0496026302055
+Ctrl.hexsalt = hexsalt:91e8378de5348cea41f84c41e8546e34
+Ctrl.hexinfo = hexinfo:97ed3540c7466ab27395fe79
+Output = bf1eb0eab488b2393ad6a1c2eb804381
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:4ce16564db9615f75d46c6a9837af7ca
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = 0a102289b16cbf4b
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:2578fe1116e27e3a5e8e935e892e12eb
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = dd5773998893ad5a93f9819c8e798aab
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e9dd8bd75f29661e61703346bbf2df47
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = 32136643daa64aaac0e2886364f157ba923d7b36ada761eb
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e4640d3752cf48186a8ad2d7d4a81210
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = 6379d59efbe02576663af5efaccb9d063f596a22c8e1fed12cde7cdd7f327e88
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:3bd9a074a219d62273c3f639659a3ecd
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = cc45eb2ab80272c1e082b4f167ee4e086f12af3fbd0c812dda5568fea702928999cde3899cffc8a8
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:2147c0fb1c7587b22fa44ce3bf3d8f5b
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = 4e3a8827fcdb214686b35bfcc497ca69dccb78d3464aa4af0704ec0fba03c7bb10b9a4e31e27b1b2379a32e46935309c
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:2c2438b6321fed7a9eac200b91b3ac30
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = b402fda16e1c2719263be82158972c9080a7bafcbe0a3a6ede3504a3d5c8c0c0e00fe7e5f6bb3afdfa4d661b8fbe4bd7b950cfe0b2443bbd
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:0ffa4c40a822f6e3d86053aefe738eac
+Ctrl.hexsalt = hexsalt:6199187690823def2037e0632577c6b1
+Output = 0486d589aa71a603c09120fb76eeab3293eee2dc36a91b23eb954d6703ade8a7b660d920c5a6f7bf3898d0e81fbad3a680b74b33680e0cc6a16aa616d078b256
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a801d997ed539ae9aa05d17871eb7fab
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 1a5efa3aca87c1f4
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e9624e112f9e90e7bf8a749cf37d920c
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = ee93ca3986cc43516ae4e29fd7a90ef1
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:a92acdee54a84a4564d4782d47801ec0
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 3116b87eaffaa0cc48a72e6c1574df335d706f7c860b44e9
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:e60d902e63b1a2bf5dab733cadb47b10
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 3fde6c078dd6dc65aacf62beafa39398d2b3d7cfb4b0ee4807bfc98a15330eef
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:d3b747a1d1584a0fc5aefcd4dd8ef9c3
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 2c4363597d42f9f8736e8050b4a6dd033d7ddac6f7211c4810ef74aff01f101d885767d7ae6f1d7f
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:119559a2c0a8888e9c95b9989a460d97
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 97922585f69adf484930cf22b8378c797694438502fa47e2f19f0fee97ca11451f3bc81a20c1d74964c63ab2d5df1985
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:807f375266988df5d0ae878efac424fa
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = ba78ef8ab720fc583bb64581917634fca230876cc344e46b44fe61f3bdab556ee753743b78db4b16c0fcd8f987aebad15d0b7b13a10f6819
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:f7906f870b256753b5bc3ef408e47e9b
+Ctrl.hexinfo = hexinfo:03697296e42a6fdbdb24b3ec
+Output = 96bee2ae234f98c285aa970bd54c2e2891febf734bad58a91dc7a97490b6b05fe539f2156ae3acd2e661eced0d59084fda340cd1ba3daa7ca2a550d7b1c19462
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA512
+Ctrl.hexsecret = hexsecret:73b6e2ede34aae5680e2289e611ffc3a
+Ctrl.hexsalt = hexsalt:28df8439747d5a9b502e0838ca6999b2
+Ctrl.hexinfo = hexinfo:232941631fc04dd82f727a51
+Output = b0d36cd7d6b23b48ca6f89901bb784ec
+
+KDF = SSKDF
+Ctrl.mac = mac:HMAC
+Ctrl.digest = digest:SHA512
+Ctrl.hexsecret = hexsecret:abb7d7554c0de41cada5826a1f79d76f
+Ctrl.hexinfo = hexinfo:a80b9061879365b1669c87a8
+Output = 71e29fff69198eca92f5180bcb281fbdaf409ec7c99ca704b1f56e782d3c4db10cb4158e6634d793a46c13bffb6bdb71a01101936ea9b20f7dbe302558b1356c