Fix parameter types in sshkdf

Handling of parameter OSSL_KDF_PARAM_SSHKDF_TYPE mixed integer and string
parameters.  This caused endianness problems on big-endian machines.  As a
result, it is not possible to pass FIPS tests since the parameter was stored
with an integer value but read via a cast to char pointer.  While this works
on little endian machines, big endian s390 read the most significant bits
instead of the least significant (as done by, e.g., x86).  Change the
parameter to char array and fix the usages.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Patrick Steuer <patrick.steuer@de.ibm.com>
(Merged from https://github.com/openssl/openssl/pull/13781)
This commit is contained in:
Juergen Christ 2020-12-14 17:36:22 +01:00 committed by Patrick Steuer
parent 732a4d15b0
commit 270a5ce1d9
6 changed files with 31 additions and 26 deletions

View File

@ -41,9 +41,9 @@ These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
These parameters set the respective values for the KDF.
If a value is already set, the contents are replaced.
=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <integer>
=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <UTF8 string>
This parameter sets the type for the SSHHKDF operation.
This parameter sets the type for the SSHKDF operation.
There are six supported types:
=over 4
@ -51,32 +51,32 @@ There are six supported types:
=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV
The Initial IV from client to server.
A single char of value 65 (ASCII char 'A').
Char array initializer of value {65, 0}, i.e., ASCII string "A".
=item EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI
The Initial IV from server to client
A single char of value 66 (ASCII char 'B').
Char array initializer of value {66, 0}, i.e., ASCII string "B".
=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV
The Encryption Key from client to server
A single char of value 67 (ASCII char 'C').
Char array initializer of value {67, 0}, i.e., ASCII string "C".
=item EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI
The Encryption Key from server to client
A single char of value 68 (ASCII char 'D').
Char array initializer of value {68, 0}, i.e., ASCII string "D".
=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV
The Integrity Key from client to server
A single char of value 69 (ASCII char 'E').
Char array initializer of value {69, 0}, i.e., ASCII string "E".
=item EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI
The Integrity Key from client to server
A single char of value 70 (ASCII char 'F').
Char array initializer of value {70, 0}, i.e., ASCII string "F".
=back
@ -103,6 +103,7 @@ This example derives an 8 byte IV using SHA-256 with a 1K "key" and appropriate
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
const char type[] = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
unsigned char key[1024] = "01234...";
unsigned char xcghash[32] = "012345...";
unsigned char session_id[32] = "012345...";
@ -122,8 +123,8 @@ This example derives an 8 byte IV using SHA-256 with a 1K "key" and appropriate
xcghash, (size_t)32);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
session_id, (size_t)32);
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_SSHKDF_TYPE,
EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE,
type, sizeof(type));
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_CTX_set_params(kctx, params) <= 0)
/* Error */

View File

@ -246,7 +246,7 @@ Sets the xcghash in the associated KDF ctx.
Sets the session ID in the associated KDF ctx.
=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <integer>
=item "type" (B<OSSL_KDF_PARAM_SSHKDF_TYPE>) <UTF8 string>
Sets the SSH KDF type parameter in the associated KDF ctx.
There are six supported types:

View File

@ -85,12 +85,14 @@ void EVP_KDF_names_do_all(const EVP_KDF *kdf,
# define EVP_KDF_HKDF_MODE_EXTRACT_ONLY 1
# define EVP_KDF_HKDF_MODE_EXPAND_ONLY 2
#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV 65
#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI 66
#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV 67
#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI 68
#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV 69
#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI 70
/* SSHKDF key exchange stages.*/
/* See https://tools.ietf.org/html/rfc4253#section-7.2 */
#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV {65, 0}
#define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI {66, 0}
#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV {67, 0}
#define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_SRV_TO_CLI {68, 0}
#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV {69, 0}
#define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI {70, 0}
/**** The legacy PKEY-based KDF API follows. ****/

View File

@ -351,7 +351,7 @@ static const ST_KAT_PARAM pbkdf2_params[] = {
};
static const char sshkdf_digest[] = "SHA1";
static int sshkdf_type = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
static const char sshkdf_type[] = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
static const unsigned char sshkdf_key[] = {
0x00, 0x00, 0x00, 0x80, 0x55, 0xba, 0xe9, 0x31,
0xc0, 0x7f, 0xd8, 0x24, 0xbf, 0x10, 0xad, 0xd1,
@ -386,7 +386,7 @@ static const unsigned char sshkdf_expected[] = {
};
static const ST_KAT_PARAM sshkdf_params[] = {
ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, sshkdf_digest),
ST_KAT_PARAM_INT(OSSL_KDF_PARAM_SSHKDF_TYPE, sshkdf_type),
ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_SSHKDF_TYPE, sshkdf_type),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, sshkdf_key),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SSHKDF_XCGHASH, sshkdf_xcghash),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, sshkdf_session_id),

View File

@ -135,7 +135,6 @@ static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
const OSSL_PARAM *p;
KDF_SSHKDF *ctx = vctx;
OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
int t;
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
return 0;
@ -156,14 +155,17 @@ static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_TYPE))
!= NULL) {
if (p->data == NULL || p->data_size == 0)
const char *kdftype;
if (!OSSL_PARAM_get_utf8_string_ptr(p, &kdftype))
return 0;
t = *(unsigned char *)p->data;
if (t < 65 || t > 70) {
if (kdftype == NULL || kdftype[0] == '\0' || kdftype[1] != '\0')
return 0;
if (kdftype[0] < 65 || kdftype[0] > 70) {
ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR);
return 0;
}
ctx->type = (char)t;
ctx->type = kdftype[0];
}
return 1;
}

View File

@ -1207,7 +1207,7 @@ static int test_kdf_sshkdf(void)
int ret;
EVP_KDF_CTX *kctx;
OSSL_PARAM params[6], *p = params;
char kdftype = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
char kdftype[] = EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV;
unsigned char out[8];
/* Test data from NIST CAVS 14.1 test vectors */
static unsigned char key[] = {
@ -1247,7 +1247,7 @@ static int test_kdf_sshkdf(void)
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
sessid, sizeof(sessid));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE,
&kdftype, sizeof(kdftype));
kdftype, sizeof(kdftype));
*p = OSSL_PARAM_construct_end();
ret =