static int kdf_sshkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen) { if (impl->md == NULL) { KDFerr(KDF_F_KDF_SSHKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); return 0; } if (impl->key == NULL) { KDFerr(KDF_F_KDF_SSHKDF_DERIVE, KDF_R_MISSING_KEY); return 0; } if (impl->xcghash == NULL) { KDFerr(KDF_F_KDF_SSHKDF_DERIVE, KDF_R_MISSING_XCGHASH); return 0; } if (impl->session_id == NULL) { KDFerr(KDF_F_KDF_SSHKDF_DERIVE, KDF_R_MISSING_SESSION_ID); return 0; } if (impl->type == 0) { KDFerr(KDF_F_KDF_SSHKDF_DERIVE, KDF_R_MISSING_TYPE); return 0; } return SSHKDF(impl->md, impl->key, impl->key_len, impl->xcghash, impl->xcghash_len, impl->session_id, impl->session_id_len, impl->type, key, keylen); }
static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (value == NULL) { KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING); return 0; } if (strcmp(type, "md") == 0) { TLS1_PRF_PKEY_CTX *kctx = ctx->data; const EVP_MD *md = EVP_get_digestbyname(value); if (md == NULL) { KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST); return 0; } kctx->md = md; return 1; } if (strcmp(type, "secret") == 0) return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); if (strcmp(type, "hexsecret") == 0) return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); if (strcmp(type, "seed") == 0) return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); if (strcmp(type, "hexseed") == 0) return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); return -2; }
static int kdf_sshkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, const char *value) { if (value == NULL) { KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_VALUE_MISSING); return 0; } if (strcmp(type, "md") == 0) return kdf_md2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_MD, value); if (strcmp(type, "key") == 0) return kdf_str2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value); if (strcmp(type, "hexkey") == 0) return kdf_hex2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value); if (strcmp(type, "xcghash") == 0) return kdf_str2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, value); if (strcmp(type, "hexxcghash") == 0) return kdf_hex2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, value); if (strcmp(type, "session_id") == 0) return kdf_str2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, value); if (strcmp(type, "hexsession_id") == 0) return kdf_hex2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, value); if (strcmp(type, "type") == 0) { if (strlen(value) != 1) { KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_VALUE_ERROR); return 0; } return call_ctrl(kdf_sshkdf_ctrl, impl, EVP_KDF_CTRL_SET_SSHKDF_TYPE, (int)value[0]); } KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); return -2; }
static EVP_KDF_IMPL *kdf_sshkdf_new(void) { EVP_KDF_IMPL *impl; if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL) KDFerr(KDF_F_KDF_SSHKDF_NEW, ERR_R_MALLOC_FAILURE); return impl; }
static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { TLS1_PRF_PKEY_CTX *kctx = ctx->data; if (kctx->md == NULL) { KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); return 0; } if (kctx->sec == NULL) { KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET); return 0; } if (kctx->seedlen == 0) { KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED); return 0; } return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen, kctx->seed, kctx->seedlen, key, *keylen); }
/* Pass a message digest to a ctrl */ int kdf_md2ctrl(EVP_KDF_IMPL *impl, int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args), int cmd, const char *md_name) { const EVP_MD *md; if (md_name == NULL || (md = EVP_get_digestbyname(md_name)) == NULL) { KDFerr(KDF_F_KDF_MD2CTRL, KDF_R_INVALID_DIGEST); return 0; } return call_ctrl(ctrl, impl, cmd, md); }
static int kdf_sshkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) { int t; switch (cmd) { case EVP_KDF_CTRL_SET_MD: impl->md = va_arg(args, const EVP_MD *); if (impl->md == NULL) return 0; return 1; case EVP_KDF_CTRL_SET_KEY: return kdf_sshkdf_parse_buffer_arg(&impl->key, &impl->key_len, args); case EVP_KDF_CTRL_SET_SSHKDF_XCGHASH: return kdf_sshkdf_parse_buffer_arg(&impl->xcghash, &impl->xcghash_len, args); case EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID: return kdf_sshkdf_parse_buffer_arg(&impl->session_id, &impl->session_id_len, args); case EVP_KDF_CTRL_SET_SSHKDF_TYPE: t = va_arg(args, int); if (t < 65 || t > 70) { KDFerr(KDF_F_KDF_SSHKDF_CTRL, KDF_R_VALUE_ERROR); return 0; } impl->type = (char)t; return 1; default: return -2; } }