summaryrefslogtreecommitdiffstats
path: root/crypto/kdf
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2019-05-16 11:43:41 +1000
committerPauli <paul.dale@oracle.com>2019-05-16 11:43:41 +1000
commit8bbeaaa4fc12f8b00fbea4dc649ef74b59f73b17 (patch)
treebf043355836767d39f96bd2a67b9bc3b7798dd9d /crypto/kdf
parent0211740fcc47a954be19cceb65fb57a6f7deb797 (diff)
Added X963KDF API
X963 KDF is used for CMS ec keyagree Recipient Info. The X963 KDF that is used by CMS EC Key Agreement has been moved into a EVP_KDF object. This KDF is almost identical to the the SSKDF hash variant, so it has been implemented inside the SSKDF code with its own method table. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/8902)
Diffstat (limited to 'crypto/kdf')
-rw-r--r--crypto/kdf/kdf_err.c2
-rw-r--r--crypto/kdf/sskdf.c43
2 files changed, 43 insertions, 2 deletions
diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c
index 84c330fafb..49028ab32f 100644
--- a/crypto/kdf/kdf_err.c
+++ b/crypto/kdf/kdf_err.c
@@ -65,6 +65,7 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
{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"},
+ {ERR_PACK(ERR_LIB_KDF, KDF_F_X963KDF_DERIVE, 0), "x963kdf_derive"},
{0, NULL}
};
@@ -84,6 +85,7 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SESSION_ID), "missing session id"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_TYPE), "missing type"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_XCGHASH), "missing xcghash"},
+ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_NOT_SUPPORTED), "not supported"},
{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),
diff --git a/crypto/kdf/sskdf.c b/crypto/kdf/sskdf.c
index 3dd5b78d26..92bf995425 100644
--- a/crypto/kdf/sskdf.c
+++ b/crypto/kdf/sskdf.c
@@ -66,10 +66,16 @@ 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)
+ * Note: X9.63 also uses this code with the only difference being that the
+ * counter is appended to the secret 'z'.
+ * i.e.
+ * result[i] = Hash(counter || z || info) for One Step OR
+ * result[i] = Hash(z || counter || info) for X9.63.
*/
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 int append_ctr,
unsigned char *derived_key, size_t derived_key_len)
{
int ret = 0, hlen;
@@ -104,8 +110,9 @@ static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
c[3] = (unsigned char)(counter & 0xff);
if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
- && EVP_DigestUpdate(ctx, c, sizeof(c))
+ && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
&& EVP_DigestUpdate(ctx, z, z_len)
+ && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
&& EVP_DigestUpdate(ctx, info, info_len)))
goto end;
if (len >= out_len) {
@@ -468,7 +475,28 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
return 0;
}
return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len,
- impl->info, impl->info_len, key, keylen);
+ impl->info, impl->info_len, 0, key, keylen);
+ }
+}
+
+static int x963kdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
+{
+ if (impl->secret == NULL) {
+ KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_MISSING_SECRET);
+ return 0;
+ }
+
+ if (impl->mac != NULL) {
+ KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_NOT_SUPPORTED);
+ return 0;
+ } else {
+ /* H(x) = hash */
+ if (impl->md == NULL) {
+ KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+ return 0;
+ }
+ return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len,
+ impl->info, impl->info_len, 1, key, keylen);
}
}
@@ -482,3 +510,14 @@ const EVP_KDF ss_kdf_meth = {
sskdf_size,
sskdf_derive
};
+
+const EVP_KDF x963_kdf_meth = {
+ EVP_KDF_X963,
+ sskdf_new,
+ sskdf_free,
+ sskdf_reset,
+ sskdf_ctrl,
+ sskdf_ctrl_str,
+ sskdf_size,
+ x963kdf_derive
+};