From: slontis Date: Fri, 13 Feb 2026 08:55:52 +0000 (+1100) Subject: SRTP: Fixup settable input limits and test them. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5b310281af9a77d180a81c6dc0a093022931b1cb;p=thirdparty%2Fopenssl.git SRTP: Fixup settable input limits and test them. Reported by https://github.com/1seal Reviewed-by: Tim Hudson Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/30001) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 3d0e69ec39b..c64b3aa2f9d 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1063,6 +1063,7 @@ PROV_R_INIT_CALL_OUT_OF_ORDER:238:init call out of order PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength PROV_R_INVALID_AAD:108:invalid aad PROV_R_INVALID_AEAD:231:invalid aead +PROV_R_INVALID_CIPHER:260:invalid cipher PROV_R_INVALID_CONFIG_DATA:211:invalid config data PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length PROV_R_INVALID_CURVE:176:invalid curve @@ -1074,6 +1075,7 @@ PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION:243:\ invalid eddsa instance for attempted operation PROV_R_INVALID_FUNCTION_NAME:258:invalid function name +PROV_R_INVALID_INDEX_LENGTH:259:invalid index length PROV_R_INVALID_INPUT_LENGTH:230:invalid input length PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count PROV_R_INVALID_IV_LENGTH:109:invalid iv length diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index fa59c0d3070..d32984a5b2c 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -56,6 +56,7 @@ #define PROV_R_INSUFFICIENT_DRBG_STRENGTH 181 #define PROV_R_INVALID_AAD 108 #define PROV_R_INVALID_AEAD 231 +#define PROV_R_INVALID_CIPHER 260 #define PROV_R_INVALID_CONFIG_DATA 211 #define PROV_R_INVALID_CONSTANT_LENGTH 157 #define PROV_R_INVALID_CURVE 176 @@ -66,6 +67,7 @@ #define PROV_R_INVALID_DIGEST_SIZE 218 #define PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION 243 #define PROV_R_INVALID_FUNCTION_NAME 258 +#define PROV_R_INVALID_INDEX_LENGTH 259 #define PROV_R_INVALID_INPUT_LENGTH 230 #define PROV_R_INVALID_ITERATION_COUNT 123 #define PROV_R_INVALID_IV_LENGTH 109 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index ed72958abf6..3392e0e4756 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -78,6 +78,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "insufficient drbg strength" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AEAD), "invalid aead" }, + { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CIPHER), "invalid cipher" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONFIG_DATA), "invalid config data" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONSTANT_LENGTH), @@ -95,6 +96,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "invalid eddsa instance for attempted operation" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_FUNCTION_NAME), "invalid function name" }, + { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_INDEX_LENGTH), + "invalid index length" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_INPUT_LENGTH), "invalid input length" }, { ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT), diff --git a/providers/implementations/kdfs/srtpkdf.c b/providers/implementations/kdfs/srtpkdf.c index 8a4cb9c05d5..cf388d1d7a5 100644 --- a/providers/implementations/kdfs/srtpkdf.c +++ b/providers/implementations/kdfs/srtpkdf.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -50,9 +51,10 @@ static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_srtpkdf_gettable_ctx_params; static OSSL_FUNC_kdf_get_ctx_params_fn kdf_srtpkdf_get_ctx_params; static int SRTPKDF(OSSL_LIB_CTX *provctx, const EVP_CIPHER *cipher, - const unsigned char *mkey, const unsigned char *msalt, const unsigned char *index, + const uint8_t *mkey, const uint8_t *msalt, + const uint8_t *index, size_t index_len, const uint32_t kdr, const uint32_t kdr_n, - const uint32_t label, unsigned char *obuffer, const size_t keylen); + const uint32_t label, uint8_t *obuffer, const size_t keylen); typedef struct { /* Warning: Any changes to this structure may require you to update kdf_srtpkdf_dup */ @@ -168,6 +170,23 @@ static int is_power_of_two(uint32_t x, uint32_t *n) return 1; } +static int kdf_srtpkdf_check_key(KDF_SRTPKDF *ctx) +{ + const EVP_CIPHER *cipher = cipher = ossl_prov_cipher_cipher(&ctx->cipher); + + if (cipher != NULL) { + if (ctx->key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return 0; + } + if (ctx->key_len != (size_t)EVP_CIPHER_get_key_length(cipher)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; +} + static int kdf_srtpkdf_derive(void *vctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]) { @@ -183,30 +202,15 @@ static int kdf_srtpkdf_derive(void *vctx, unsigned char *key, size_t keylen, ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER); return 0; } - if (ctx->key == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + if (!kdf_srtpkdf_check_key(ctx)) return 0; - } if (ctx->salt == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT); return 0; } - if (ctx->kdr > 0) { - uint32_t n = 0; - if (!is_power_of_two(ctx->kdr, &n) - || n > KDF_SRTP_MAX_KDR) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KDR); - return 0; - } - ctx->kdr_n = n; - } - if (ctx->label > KDF_SRTP_MAX_LABEL) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_LABEL); - return 0; - } - - return SRTPKDF(libctx, cipher, ctx->key, ctx->salt, ctx->index, - ctx->kdr, ctx->kdr_n, ctx->label, key, keylen); + return SRTPKDF(libctx, cipher, ctx->key, ctx->salt, + ctx->index, ctx->index_len, ctx->kdr, ctx->kdr_n, ctx->label, + key, keylen); } static int kdf_srtpkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) @@ -214,8 +218,6 @@ static int kdf_srtpkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) struct srtp_set_ctx_params_st p; KDF_SRTPKDF *ctx = vctx; OSSL_LIB_CTX *libctx; - const EVP_CIPHER *cipher; - int key_len; if (params == NULL) return 1; @@ -225,45 +227,65 @@ static int kdf_srtpkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) libctx = PROV_LIBCTX_OF(ctx->provctx); - if ((p.cipher != NULL) - && !ossl_prov_cipher_load(&ctx->cipher, p.cipher, p.propq, libctx)) - return 0; - - cipher = ossl_prov_cipher_cipher(&ctx->cipher); - if (cipher == NULL) - return 0; - - if (!EVP_CIPHER_is_a(cipher, "AES-128-CTR") && !EVP_CIPHER_is_a(cipher, "AES-192-CTR") - && !EVP_CIPHER_is_a(cipher, "AES-256-CTR")) - return 0; + if (p.cipher != NULL) { + const EVP_CIPHER *cipher = NULL; + if (!ossl_prov_cipher_load(&ctx->cipher, p.cipher, p.propq, libctx)) + return 0; + cipher = ossl_prov_cipher_cipher(&ctx->cipher); + if (cipher == NULL) + return 0; + if (!EVP_CIPHER_is_a(cipher, "AES-128-CTR") + && !EVP_CIPHER_is_a(cipher, "AES-192-CTR") + && !EVP_CIPHER_is_a(cipher, "AES-256-CTR")) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CIPHER); + return 0; + } + } if (p.key != NULL) { - key_len = EVP_CIPHER_get_key_length(cipher); if (!srtpkdf_set_membuf(&ctx->key, &ctx->key_len, p.key)) return 0; - if (ctx->key_len != (size_t)key_len) + if (!kdf_srtpkdf_check_key(ctx)) return 0; } - if (p.salt != NULL) { if (!srtpkdf_set_membuf(&ctx->salt, &ctx->salt_len, p.salt)) return 0; - if (ctx->salt_len < KDF_SRTP_SALT_LEN) + if (ctx->salt_len < KDF_SRTP_SALT_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); return 0; + } } - - if ((p.index != NULL) - && !srtpkdf_set_membuf(&ctx->index, &ctx->index_len, p.index)) - return 0; - if (p.kdr != NULL) { if (!OSSL_PARAM_get_uint32(p.kdr, &ctx->kdr)) return 0; + if (ctx->kdr > 0) { + uint32_t n = 0; + + if (!is_power_of_two(ctx->kdr, &n) + || n > KDF_SRTP_MAX_KDR) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KDR); + return 0; + } + ctx->kdr_n = n; + } } if (p.label != NULL) { if (!OSSL_PARAM_get_uint32(p.label, &ctx->label)) return 0; + if (ctx->label > KDF_SRTP_MAX_LABEL) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_LABEL); + return 0; + } + } + if (p.index != NULL) { + if (!srtpkdf_set_membuf(&ctx->index, &ctx->index_len, p.index)) + return 0; + /* + * Defer checking the index until the derive() since it is dependant + * on values of kdr and label. + */ } return 1; @@ -315,6 +337,21 @@ const OSSL_DISPATCH ossl_kdf_srtpkdf_functions[] = { { 0, NULL } }; +static bool is_srtp(uint32_t label) +{ + static const bool strp_table[] = { + true, /* 0 */ + true, /* 1 */ + true, /* 2 */ + false, /* 3 */ + false, /* 4 */ + false, /* 5 */ + true, /* 6 */ + true, /* 7 */ + }; + return strp_table[label]; +} + /* * SRTPKDF - In compliance with SP800-135 and RFC3711, calculate * various keys defined by label using a master key, @@ -343,76 +380,63 @@ const OSSL_DISPATCH ossl_kdf_srtpkdf_functions[] = { * cipher - AES cipher * mkey - pointer to master key * msalt - pointer to master salt - * idx - pointer to index + * index - pointer to index + * idxlen - size of the index buffer * kdr - key derivation rate * kdr_n - power of kdr (2**kdr_n = kdr) * label - 8-bit label - * obuffer - buffer for output - * keylen - length of output buffer + * keylen - size of obuffer * Output: * obuffer - filled with derived key * return - 1 on pass, 0 fail */ int SRTPKDF(OSSL_LIB_CTX *provctx, const EVP_CIPHER *cipher, - const unsigned char *mkey, const unsigned char *msalt, const unsigned char *index, + const uint8_t *mkey, const uint8_t *msalt, + const uint8_t *index, size_t idxlen, const uint32_t kdr, const uint32_t kdr_n, - const uint32_t label, unsigned char *obuffer, const size_t keylen) + const uint32_t label, uint8_t *obuffer, const size_t keylen) { EVP_CIPHER_CTX *ctx = NULL; int outl, i, index_len = 0, o_len = 0, salt_len = 0; - unsigned char buf[EVP_MAX_KEY_LENGTH]; - unsigned char iv[KDF_SRTP_IV_LEN]; - unsigned char local_salt[KDF_SRTP_MAX_SALT_LEN]; - unsigned char master_salt[KDF_SRTP_MAX_SALT_LEN]; + uint8_t buf[EVP_MAX_KEY_LENGTH]; + uint8_t iv[KDF_SRTP_IV_LEN]; + uint8_t local_salt[KDF_SRTP_MAX_SALT_LEN]; + uint8_t master_salt[KDF_SRTP_MAX_SALT_LEN]; BIGNUM *bn_index = NULL, *bn_salt = NULL; int ret, iv_len = KDF_SRTP_IV_LEN, rv = 0; - salt_len = KDF_SRTP_SALT_LEN; - + if (obuffer == NULL || keylen > INT_MAX) + return rv; /* get label-specific lengths */ switch (label) { case 0: - index_len = KDF_SRTP_IDX_LEN; + case 3: + case 6: o_len = EVP_CIPHER_key_length(cipher); break; case 1: - index_len = KDF_SRTP_IDX_LEN; o_len = KDF_SRTP_AUTH_KEY_LEN; break; - case 2: - index_len = KDF_SRTP_IDX_LEN; - o_len = KDF_SRTP_SALT_KEY_LEN; - break; - case 3: - index_len = KDF_SRTCP_IDX_LEN; - o_len = EVP_CIPHER_key_length(cipher); - break; case 4: - index_len = KDF_SRTCP_IDX_LEN; o_len = KDF_SRTCP_AUTH_KEY_LEN; break; - case 5: - index_len = KDF_SRTCP_IDX_LEN; - o_len = KDF_SRTCP_SALT_KEY_LEN; - break; - case 6: - index_len = KDF_SRTP_IDX_LEN; - o_len = EVP_CIPHER_key_length(cipher); - break; + case 2: case 7: - index_len = KDF_SRTP_IDX_LEN; o_len = KDF_SRTP_SALT_KEY_LEN; break; + case 5: + o_len = KDF_SRTCP_SALT_KEY_LEN; + break; default: return rv; } - - if ((obuffer == NULL) || (keylen > INT_MAX) || (o_len > (int)keylen)) + if (o_len > (int)keylen) return rv; /* set up a couple of work areas for the final logic on the salt */ + salt_len = KDF_SRTP_SALT_LEN; memset(iv, 0, KDF_SRTP_IV_LEN); - memset(master_salt, 0, KDF_SRTP_MAX_SALT_LEN); + memset(master_salt, 0, sizeof(master_salt)); memcpy(master_salt, msalt, salt_len); /* gather some bignums for some math */ @@ -424,8 +448,13 @@ int SRTPKDF(OSSL_LIB_CTX *provctx, const EVP_CIPHER *cipher, return rv; } + index_len = is_srtp(label) ? KDF_SRTP_IDX_LEN : KDF_SRTCP_IDX_LEN; /* if index is NULL or kdr=0, then index and kdr are not in play */ - if ((index != NULL) && (kdr > 0)) { + if (index != NULL && idxlen > 0 && kdr > 0) { + if ((int)idxlen < index_len) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INDEX_LENGTH); + goto err; + } if (!BN_bin2bn(index, index_len, bn_index)) goto err; diff --git a/test/recipes/30-test_evp_data/evpkdf_srtp.txt b/test/recipes/30-test_evp_data/evpkdf_srtp.txt index a810b908257..3eb53d63c18 100644 --- a/test/recipes/30-test_evp_data/evpkdf_srtp.txt +++ b/test/recipes/30-test_evp_data/evpkdf_srtp.txt @@ -94,7 +94,8 @@ Ctrl.kdr = kdr:0 Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 -Result = KDF_CTRL_ERROR +Result = KDF_DERIVE_ERROR +Reason = missing cipher # Negative Test case 2, invalid cipher FIPSversion = >=4.0.0 @@ -107,6 +108,7 @@ Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 Result = KDF_CTRL_ERROR +Reason = invalid cipher # Negative Test case 3, missing key FIPSversion = >=4.0.0 @@ -118,6 +120,7 @@ Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 Result = KDF_DERIVE_ERROR +Reason = missing key # Negative Test case 4, missing salt FIPSversion = >=4.0.0 @@ -129,6 +132,7 @@ Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 Result = KDF_DERIVE_ERROR +Reason = missing salt # Negative Test case 5, invalid label FIPSversion = >=4.0.0 @@ -140,7 +144,8 @@ Ctrl.kdr = kdr:0 Ctrl.index = hexindex:000000000000 Ctrl.label = label:8 Output = C61E7A93744F39EE10734AFE3FF7A087 -Result = KDF_DERIVE_ERROR +Result = KDF_CTRL_ERROR +Reason = invalid label # Negative Test case 6, invalid kdr (not power of 2) FIPSversion = >=4.0.0 @@ -152,7 +157,8 @@ Ctrl.kdr = kdr:5 Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 -Result = KDF_DERIVE_ERROR +Result = KDF_CTRL_ERROR +Reason = invalid kdr # Negative Test case 7, invalid kdr (kdr out of range) FIPSversion = >=4.0.0 @@ -164,7 +170,8 @@ Ctrl.kdr = kdr:0x10000000 Ctrl.index = hexindex:000000000000 Ctrl.label = label:0 Output = C61E7A93744F39EE10734AFE3FF7A087 -Result = KDF_DERIVE_ERROR +Result = KDF_CTRL_ERROR +Reason = invalid kdr # Additional tests from # https://github.com/usnistgov/ACVP-Server/tree/master/gen-val/json-files/kdf-components-srtp-1.0 @@ -394,3 +401,69 @@ Ctrl.hexsalt = hexsalt:E1D109B42D6C16A8830F9E7DDF4B Ctrl.index = hexindex:8E5BDF08FA78 Ctrl.label = label:2 Output = B27816A7A139D73E71A55FCD7006 + +# The following tests are copies of one of the above tests with +# invalid sizes for different inputs. + +# Test index size too small for label 0 (SRTP) +FIPSversion = >=4.0.0 +KDF = SRTPKDF +Ctrl.cipher = cipher:AES-128-CTR +Ctrl.hexkey = hexkey:8C307F105F79D5D2C26B1A933AE22CD5 +Ctrl.hexsalt = hexsalt:563B4C15458D977B68080242CEE1 +Ctrl.kdr = kdr:1 +Ctrl.index = hexindex:08284B49F5 +Ctrl.label = label:0 +Output = A920DF50EAA111D03FBE9B203121C07D +Result = KDF_DERIVE_ERROR +Reason = invalid index length + +# Test index size too small for label 4 (SRTCP) +FIPSversion = >=4.0.0 +KDF = SRTPKDF +Ctrl.cipher = cipher:AES-128-CTR +Ctrl.hexkey = hexkey:8C307F105F79D5D2C26B1A933AE22CD5 +Ctrl.hexsalt = hexsalt:563B4C15458D977B68080242CEE1 +Ctrl.kdr = kdr:1 +Ctrl.index = hexindex:69B621 +Ctrl.label = label:4 +Output = FA02251D693645BC1001f83C5A13CB3E3D77F7EA +Result = KDF_DERIVE_ERROR +Reason = invalid index length + +# Test salt size is too small +FIPSversion = >=4.0.0 +KDF = SRTPKDF +Ctrl.cipher = cipher:AES-128-CTR +Ctrl.hexkey = hexkey:8C307F105F79D5D2C26B1A933AE22CD5 +Ctrl.hexsalt = hexsalt:563B +Ctrl.kdr = kdr:1 +Ctrl.index = hexindex:69B62109 +Ctrl.label = label:4 +Output = FA02251D693645BC1001f83C5A13CB3E3D77F7EA +Result = KDF_CTRL_ERROR +Reason = invalid salt length + +# Test invalid key size fails +FIPSversion = >=4.0.0 +KDF = SRTPKDF +Ctrl.cipher = cipher:AES-128-CTR +Ctrl.hexkey = hexkey:8C307F +Ctrl.hexsalt = hexsalt:563B4C15458D977B68080242CEE1 +Ctrl.kdr = kdr:1 +Ctrl.index = hexindex:69B62109 +Ctrl.label = label:4 +Output = FA02251D693645BC1001f83C5A13CB3E3D77F7EA +Result = KDF_CTRL_ERROR +Reason = invalid key length + +# Test Case 1.3, variation, zero length index +FIPSversion = >=4.0.0 +KDF = SRTPKDF +Ctrl.cipher = cipher:AES-128-CTR +Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139 +Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6 +Ctrl.index = hexindex: +Ctrl.kdr = kdr:1 +Ctrl.label = label:0 +Output = C61E7A93744F39EE10734AFE3FF7A087