Add SRTPKDF implementation

In compliance with RFC 3711, Section 4.3.3

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
MergeDate: Fri Jan 23 10:19:32 2026
(Merged from https://github.com/openssl/openssl/pull/29435)
This commit is contained in:
Helen Zhang 2025-12-17 21:45:26 +00:00 committed by Norbert Pocs
parent d2a126c20e
commit fe67753da4
28 changed files with 1181 additions and 10 deletions

View file

@ -105,6 +105,7 @@ jobs:
no-sm4,
no-snmpkdf,
no-sock,
no-srtpkdf,
no-sse2,
no-sshkdf,
no-sskdf,

1
.gitignore vendored
View file

@ -165,6 +165,7 @@ providers/implementations/digests/sha3_prov.inc
providers/implementations/digests/ml_dsa_mu_prov.inc
providers/implementations/include/prov/blake2_params.inc
providers/implementations/kdfs/snmpkdf.inc
providers/implementations/kdfs/srtpkdf.inc
providers/implementations/macs/cmac_prov.inc
providers/implementations/macs/gmac_prov.inc
providers/implementations/macs/hmac_prov.inc

View file

@ -167,6 +167,10 @@ OpenSSL 4.0
*Simo Sorce*
* Added SRTP KDF (EVP_KDF_SRTPKDF) to EVP_KDF
*Barry Fussell and Helen Zhang*
OpenSSL 3.6
-----------

View file

@ -535,6 +535,7 @@ my @disablables = (
"sock",
"srp",
"srtp",
"srtpkdf",
"sse2",
"sshkdf",
"sskdf",
@ -655,7 +656,7 @@ my @disable_cascades = (
"pvkkdf", "rc2", "rc4", "rmd160",
"scrypt", "seed", "siphash", "siv",
"slh-dsa", "sm3", "sm4", "snmpkdf",
"srp", "srtp", "sshkdf", "sskdf",
"srp", "srtp", "srtpkdf", "sshkdf", "sskdf",
"ssl-trace",
"tfo",
"ts", "ui-console", "whirlpool",

View file

@ -1177,7 +1177,7 @@ The `lms` algorithm support is currently limited to verification only as per
md4|mdc2|
ml-dsa|ml-kem|
ocb|poly1305|pvkkdf|rc2|rc4|rmd160|scrypt|
seed|siphash|siv|slh-dsa|sm2|sm3|sm4|snmpkdf|sshkdf|sskdf|
seed|siphash|siv|slh-dsa|sm2|sm3|sm4|snmpkdf|srtpkdf|sshkdf|sskdf|
x942kdf|x963kdf|whirlpool}
Build without support for the specified algorithm.

View file

@ -68,6 +68,7 @@ DEPEND[]=include/openssl/asn1.h \
providers/implementations/kdfs/pvkkdf.inc \
providers/implementations/kdfs/scrypt.inc \
providers/implementations/kdfs/snmpkdf.inc \
providers/implementations/kdfs/srtpkdf.inc \
providers/implementations/kdfs/sshkdf.inc \
providers/implementations/kdfs/sskdf.inc \
providers/implementations/kdfs/tls1_prf.inc \
@ -189,6 +190,7 @@ DEPEND[providers/implementations/asymciphers/rsa_enc.inc \
providers/implementations/kdfs/pvkkdf.inc \
providers/implementations/kdfs/scrypt.inc \
providers/implementations/kdfs/snmpkdf.inc \
providers/implementations/kdfs/srtpkdf.inc \
providers/implementations/kdfs/sshkdf.inc \
providers/implementations/kdfs/sskdf.inc \
providers/implementations/kdfs/tls1_prf.inc \
@ -301,6 +303,8 @@ GENERATE[providers/implementations/kdfs/scrypt.inc]=\
providers/implementations/kdfs/scrypt.inc.in
GENERATE[providers/implementations/kdfs/snmpkdf.inc]=\
providers/implementations/kdfs/snmpkdf.inc.in
GENERATE[providers/implementations/kdfs/srtpkdf.inc]=\
providers/implementations/kdfs/srtpkdf.inc.in
GENERATE[providers/implementations/kdfs/sshkdf.inc]=\
providers/implementations/kdfs/sshkdf.inc.in
GENERATE[providers/implementations/kdfs/sskdf.inc]=\

View file

@ -1,4 +1,4 @@
# Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
# Copyright 1999-2026 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
@ -1077,8 +1077,10 @@ 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
PROV_R_INVALID_KDF:232:invalid kdf
PROV_R_INVALID_KDR:256:invalid kdr
PROV_R_INVALID_KEY:158:invalid key
PROV_R_INVALID_KEY_LENGTH:105:invalid key length
PROV_R_INVALID_LABEL:257:invalid label
PROV_R_INVALID_MAC:151:invalid mac
PROV_R_INVALID_MEMORY_SIZE:235:invalid memory size
PROV_R_INVALID_MGF1_MD:167:invalid mgf1 md

View file

@ -4629,6 +4629,10 @@ DEPEND[html/man7/EVP_KDF-SNMPKDF.html]=man7/EVP_KDF-SNMPKDF.pod
GENERATE[html/man7/EVP_KDF-SNMPKDF.html]=man7/EVP_KDF-SNMPKDF.pod
DEPEND[man/man7/EVP_KDF-SNMPKDF.7]=man7/EVP_KDF-SNMPKDF.pod
GENERATE[man/man7/EVP_KDF-SNMPKDF.7]=man7/EVP_KDF-SNMPKDF.pod
DEPEND[html/man7/EVP_KDF-SRTPKDF.html]=man7/EVP_KDF-SRTPKDF.pod
GENERATE[html/man7/EVP_KDF-SRTPKDF.html]=man7/EVP_KDF-SRTPKDF.pod
DEPEND[man/man7/EVP_KDF-SRTPKDF.7]=man7/EVP_KDF-SRTPKDF.pod
GENERATE[man/man7/EVP_KDF-SRTPKDF.7]=man7/EVP_KDF-SRTPKDF.pod
DEPEND[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
GENERATE[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
DEPEND[man/man7/EVP_KDF-SS.7]=man7/EVP_KDF-SS.pod
@ -5204,6 +5208,7 @@ html/man7/EVP_KDF-PKCS12KDF.html \
html/man7/EVP_KDF-PVKKDF.html \
html/man7/EVP_KDF-SCRYPT.html \
html/man7/EVP_KDF-SNMPKDF.html \
html/man7/EVP_KDF-SRTPKDF.html \
html/man7/EVP_KDF-SS.html \
html/man7/EVP_KDF-SSHKDF.html \
html/man7/EVP_KDF-TLS13_KDF.html \
@ -5366,6 +5371,7 @@ man/man7/EVP_KDF-PKCS12KDF.7 \
man/man7/EVP_KDF-PVKKDF.7 \
man/man7/EVP_KDF-SCRYPT.7 \
man/man7/EVP_KDF-SNMPKDF.7 \
man/man7/EVP_KDF-SRTPKDF.7 \
man/man7/EVP_KDF-SS.7 \
man/man7/EVP_KDF-SSHKDF.7 \
man/man7/EVP_KDF-TLS13_KDF.7 \

View file

@ -141,7 +141,7 @@ This option is identical to the B<-mac> option.
Specifies the name of a supported KDF algorithm which will be used.
The supported algorithms names include TLS1-PRF, HKDF, SSKDF, PBKDF2,
SNMPKDF, SSHKDF, X942KDF-ASN1, X942KDF-CONCAT, X963KDF and SCRYPT.
SNMPKDF, SRTPKDF, SSHKDF, X942KDF-ASN1, X942KDF-CONCAT, X963KDF and SCRYPT.
=back
@ -181,6 +181,14 @@ Use SNMPKDF to create a hex-encoded derived key from an engine ID, hash and pass
-kdfopt pass:IFUcNbMl \
-kdfopt hexeid:800002b805123456789abcdef0123456789abcdef0123456789abcdef0123456 SNMPKDF
Use SRTPKDF to create a SRTP authentication derived key from a cipher, mkey, msalt,
kdr, index and label:
openssl kdf -keylen 20 -kdfopt cipher:AES-128-CTR \
-kdfopt key:E1F97A0D3E018BE0D64FA32C06DE4139 \
-kdfopt salt:0EC675AD498AFEEBB6960B3AABE6 \
-kdfopt index:000000000000 -kdfopt label:1 SRTPKDF
Use SSHKDF to create a hex-encoded derived key from a secret key, hash and session_id:
openssl kdf -keylen 16 -kdfopt digest:SHA2-256 \
@ -215,6 +223,7 @@ L<EVP_KDF-TLS1_PRF(7)>,
L<EVP_KDF-PBKDF2(7)>,
L<EVP_KDF-HKDF(7)>,
L<EVP_KDF-SNMPKDF(7)>,
L<EVP_KDF-SRTPKDF(7)>,
L<EVP_KDF-SS(7)>,
L<EVP_KDF-SSHKDF(7)>,
L<EVP_KDF-X942-ASN1(7)>,

View file

@ -0,0 +1,197 @@
=pod
=head1 NAME
EVP_KDF-SRTPKDF - The SRTP EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<SRTP> KDF through the B<EVP_KDF> API.
The EVP_KDF-SRTP algorithm implements the SRTP key derivation function.
SRTP follows the specification in RFC 3711 Section 4.3.3, where various
cryptographic keys (encryption, authentication, and salt keys) are derived
from a master key and master salt using AES encryption with specific labels.
The output keys are used for SRTP and SRTCP packet protection.
=head2 Identity
"SRTP" is the name for this implementation; it can be used with the
EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
This parameter sets the cipher to be used for the key derivation.
Typically "AES-128-CTR" or "AES-256-CTR" is used.
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
This parameter sets the master key value. This is typically 16 bytes
for AES-128 or 32 bytes for AES-256.
=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string>
This parameter sets the master salt value. This is typically 14 bytes
as specified in RFC 3711.
=item "kdr" (B<OSSL_KDF_PARAM_SRTPKDF_KDR>) <unsigned integer>
This parameter sets the key derivation rate (KDR). The KDR controls
how often keys are rederived. If not set or set to zero, no key
rederivation is performed. The KDR value is power of 2 (range 2^0 to 2^24).
=item "index" (B<OSSL_KDF_PARAM_SRTPKDF_INDEX>) <octet string>
This parameter sets the index value used in key derivation. For RTP
packets, this is typically a 48-bit (6 byte) value. For RTCP packets,
this is typically a 32-bit (4 byte) value. If not set, defaults to zero.
=item "label" (B<OSSL_KDF_PARAM_SRTPKDF_LABEL>) <unsigned integer>
This parameter sets the label that identifies the type of key to derive.
Valid values are:
=over 4
=item 0 - SRTP encryption key
=item 1 - SRTP authentication key
=item 2 - SRTP salt key
=item 3 - SRTCP encryption key
=item 4 - SRTCP authentication key
=item 5 - SRTCP salt key
=item 6 - SRTP encryption key (alternative)
=item 7 - SRTP salt key (alternative)
=back
=back
=head1 NOTES
A context for SRTP can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SRTP", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
The output length of the SRTP KDF operation is determined by the label:
=over 4
=item Labels 0, 3, 6: Output length equals the cipher key length
=item Labels 1, 4: Output length is 20 bytes (160 bits)
=item Labels 2, 5, 7: Output length is 14 bytes (112 bits)
=back
=head1 EXAMPLES
This example derives an SRTP encryption key (label 0) using AES-128-CTR
with a 16-byte master key and 14-byte master salt:
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[16];
unsigned char master_key[16] = { /* master key bytes */ };
unsigned char master_salt[14] = { /* master salt bytes */ };
uint32_t label = 0;
OSSL_PARAM params[5], *p = params;
kdf = EVP_KDF_fetch(NULL, "SRTP", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
"AES-128-CTR", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
master_key, sizeof(master_key));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
master_salt, sizeof(master_salt));
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SRTPKDF_LABEL, &label);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
This example derives an SRTP authentication key (label 1) with key derivation
rate and index:
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[20];
unsigned char master_key[16] = { /* master key bytes */ };
unsigned char master_salt[14] = { /* master salt bytes */ };
uint32_t kdr = 0x1000; /* KDR */
unsigned char index[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; /* index */
uint32_t label = 1;
OSSL_PARAM params[7], *p = params;
kdf = EVP_KDF_fetch(NULL, "SRTP", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
"AES-128-CTR", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
master_key, sizeof(master_key));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
master_salt, sizeof(master_salt));
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SRTPKDF_KDR, &kdr);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SRTPKDF_INDEX,
index, sizeof(index));
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SRTPKDF_LABEL, &label);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
RFC 3711 Section 4.3.3 (SRTP Key Derivation)
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF_CTX_new(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_CTX_set_params(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
The SRTPKDF was added in OpenSSL 4.0.0.
=head1 COPYRIGHT
Copyright 2026 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
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -121,6 +121,8 @@ KECCAK-KMAC is only used internally as a sub algorithm of KMAC.
=item SNMPKDF, see L<EVP_KDF-SNMPKDF(7)>
=item SRTPKDF, see L<EVP_KDF-SRTPKDF(7)>
=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
@ -489,6 +491,8 @@ Key agreement tests used with the "KAT_KA" type.
=item "SNMPKDF" (B<OSSL_SELF_TEST_DESC_KDF_SNMPKDF>)
=item "SRTPKDF" (B<OSSL_SELF_TEST_DESC_KDF_SRTPKDF>)
=item "SSHKDF" (B<OSSL_SELF_TEST_DESC_KDF_SSHKDF>)
=item "TLS12_PRF" (B<OSSL_SELF_TEST_DESC_KDF_TLS12_PRF>)

View file

@ -143,6 +143,8 @@ The OpenSSL default provider supports these operations and algorithms:
=item SNMPKDF, see L<EVP_KDF-SNMPKDF(7)>
=item SRTPKDF, see L<EVP_KDF-SRTPKDF(7)>
=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>

View file

@ -76,6 +76,7 @@ extern "C" {
#define OSSL_KDF_NAME_PBKDF2 "PBKDF2"
#define OSSL_KDF_NAME_SCRYPT "SCRYPT"
#define OSSL_KDF_NAME_SNMPKDF "SNMPKDF"
#define OSSL_KDF_NAME_SRTPKDF "SRTPKDF"
#define OSSL_KDF_NAME_SSHKDF "SSHKDF"
#define OSSL_KDF_NAME_SSKDF "SSKDF"
#define OSSL_KDF_NAME_TLS1_PRF "TLS1-PRF"

View file

@ -69,8 +69,10 @@
#define PROV_R_INVALID_ITERATION_COUNT 123
#define PROV_R_INVALID_IV_LENGTH 109
#define PROV_R_INVALID_KDF 232
#define PROV_R_INVALID_KDR 256
#define PROV_R_INVALID_KEY 158
#define PROV_R_INVALID_KEY_LENGTH 105
#define PROV_R_INVALID_LABEL 257
#define PROV_R_INVALID_MAC 151
#define PROV_R_INVALID_MEMORY_SIZE 235
#define PROV_R_INVALID_MGF1_MD 167

View file

@ -84,6 +84,7 @@ extern "C" {
#define OSSL_SELF_TEST_DESC_KDF_X942KDF "X942KDF"
#define OSSL_SELF_TEST_DESC_KDF_PBKDF2 "PBKDF2"
#define OSSL_SELF_TEST_DESC_KDF_SNMPKDF "SNMPKDF"
#define OSSL_SELF_TEST_DESC_KDF_SRTPKDF "SRTPKDF"
#define OSSL_SELF_TEST_DESC_KDF_SSHKDF "SSHKDF"
#define OSSL_SELF_TEST_DESC_KDF_TLS12_PRF "TLS12_PRF"
#define OSSL_SELF_TEST_DESC_KDF_KBKDF "KBKDF"

View file

@ -99,9 +99,11 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
"invalid iteration count" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IV_LENGTH), "invalid iv length" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KDF), "invalid kdf" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KDR), "invalid kdr" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY), "invalid key" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
"invalid key length" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_LABEL), "invalid label" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac" },
{ ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MEMORY_SIZE),
"invalid memory size" },

View file

@ -375,6 +375,9 @@ static const OSSL_ALGORITHM deflt_kdfs[] = {
#ifndef OPENSSL_NO_SNMPKDF
{ PROV_NAMES_SNMPKDF, "provider=default", ossl_kdf_snmpkdf_functions },
#endif
#ifndef OPENSSL_NO_SRTPKDF
{ PROV_NAMES_SRTPKDF, "provider=default", ossl_kdf_srtpkdf_functions },
#endif
#ifndef OPENSSL_NO_SSHKDF
{ PROV_NAMES_SSHKDF, "provider=default", ossl_kdf_sshkdf_functions },
#endif

View file

@ -447,6 +447,9 @@ static const OSSL_ALGORITHM fips_kdfs[] = {
#ifndef OPENSSL_NO_SNMPKDF
{ PROV_NAMES_SNMPKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_snmpkdf_functions },
#endif
#ifndef OPENSSL_NO_SRTPKDF
{ PROV_NAMES_SRTPKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_srtpkdf_functions },
#endif
#ifndef OPENSSL_NO_SSHKDF
{ PROV_NAMES_SSHKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_sshkdf_functions },
#endif
@ -471,6 +474,9 @@ static const OSSL_ALGORITHM fips_kdfs_internal[] = {
#ifndef OPENSSL_NO_SNMPKDF
{ PROV_NAMES_SNMPKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_snmpkdf_functions },
#endif
#ifndef OPENSSL_NO_SRTPKDF
{ PROV_NAMES_SRTPKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_srtpkdf_functions },
#endif
#ifndef OPENSSL_NO_SSHKDF
{ PROV_NAMES_SSHKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_sshkdf_functions },
#endif

View file

@ -533,6 +533,40 @@ static const ST_KAT_PARAM snmpkdf_params[] = {
};
#endif
#ifndef OPENSSL_NO_SRTPKDF
static const char srtpkdf_cipher[] = "AES-256-CTR";
static const int srtpkdf_kdr = 0x100;
static const unsigned char srtpkdf_key[] = {
0x4b, 0x26, 0xfa, 0xdc, 0x0a, 0x9b, 0xe8, 0x23,
0xdc, 0xd6, 0xab, 0xc8, 0x2c, 0x04, 0x39, 0x75,
0xa6, 0x03, 0xf0, 0x05, 0x87, 0xb8, 0x75, 0x34,
0x60, 0xba, 0xf0, 0x50, 0x2e, 0xee, 0x66, 0xbb };
static const unsigned char srtpkdf_salt[] = {
0x99, 0x74, 0xa3, 0x00, 0x33, 0x28, 0x84, 0xfb,
0xfa, 0x03, 0x71, 0x8c, 0xe0, 0xe0 };
static const unsigned char srtpkdf_index[] = {
0x6e, 0xe6, 0x30, 0x14 };
static const int srtpkdf_label = 5;
static const unsigned char srtpkdf_expected[] = {
0x5c, 0x4e, 0x98, 0xd3, 0x29, 0x6e, 0x00, 0x9b,
0x45, 0x38, 0x09, 0x6d, 0x72, 0xe4 };
static const ST_KAT_PARAM srtpkdf_params[] = {
ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_CIPHER, srtpkdf_cipher),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_KEY, srtpkdf_key),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SALT, srtpkdf_salt),
ST_KAT_PARAM_OCTET(OSSL_KDF_PARAM_SRTPKDF_INDEX, srtpkdf_index),
ST_KAT_PARAM_INT(OSSL_KDF_PARAM_SRTPKDF_KDR, srtpkdf_kdr),
ST_KAT_PARAM_INT(OSSL_KDF_PARAM_SRTPKDF_LABEL, srtpkdf_label),
ST_KAT_PARAM_END()
};
#endif
#ifndef OPENSSL_NO_SSKDF
static const char sskdf_digest[] = "SHA256";
static const unsigned char sskdf_secret[] = {
@ -864,6 +898,15 @@ static const ST_KAT_KDF st_kat_kdf_tests[] =
ITM(snmpkdf_expected)
},
#endif
#ifndef OPENSSL_NO_SRTPKDF
{
OSSL_SELF_TEST_DESC_KDF_SRTPKDF,
OSSL_KDF_NAME_SRTPKDF,
0,
srtpkdf_params,
ITM(srtpkdf_expected)
},
#endif
#ifndef OPENSSL_NO_SSKDF
{
OSSL_SELF_TEST_DESC_KDF_SSKDF,

View file

@ -292,6 +292,7 @@ extern const OSSL_DISPATCH ossl_kdf_hkdf_sha384_functions[];
extern const OSSL_DISPATCH ossl_kdf_hkdf_sha512_functions[];
extern const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_snmpkdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_srtpkdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_sshkdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_sskdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[];

View file

@ -296,6 +296,7 @@
#define PROV_NAMES_PBKDF2 "PBKDF2:1.2.840.113549.1.5.12"
#define PROV_NAMES_PVKKDF "PVKKDF"
#define PROV_NAMES_SNMPKDF "SNMPKDF"
#define PROV_NAMES_SRTPKDF "SRTPKDF"
#define PROV_NAMES_SSHKDF "SSHKDF"
#define PROV_NAMES_X963KDF "X963KDF:X942KDF-CONCAT"
#define PROV_NAMES_X942KDF_ASN1 "X942KDF-ASN1:X942KDF"

View file

@ -12,6 +12,7 @@ $PKCS12KDF_GOAL=../../libdefault.a
$SSKDF_GOAL=../../libdefault.a ../../libfips.a
$SCRYPT_GOAL=../../libdefault.a
$SNMPKDF_GOAL=../../libdefault.a ../../libfips.a
$SRTPKDF_GOAL=../../libdefault.a ../../libfips.a
$SSHKDF_GOAL=../../libdefault.a ../../libfips.a
$X942KDF_GOAL=../../libdefault.a ../../libfips.a
$HMAC_DRBG_KDF_GOAL=../../libdefault.a ../../libfips.a
@ -51,6 +52,10 @@ IF[{- !$disabled{snmpkdf} -}]
SOURCE[$SNMPKDF_GOAL]=snmpkdf.c
ENDIF
IF[{- !$disabled{srtpkdf} -}]
SOURCE[$SRTPKDF_GOAL]=srtpkdf.c
ENDIF
IF[{- !$disabled{sshkdf} -}]
SOURCE[$SSHKDF_GOAL]=sshkdf.c
ENDIF

View file

@ -265,18 +265,21 @@ const OSSL_DISPATCH ossl_kdf_snmpkdf_functions[] = {
*
* Shared_key = SHA-1(Derived_password || snmpEngineID || Derived_password).
*
* Input:
* e_id - engine ID(eid)
* e_len - engineID length
* password - password
* password_len - password length
* okey - pointer to key output, FIPS testing limited to SHA-1.
* okeylen - key output length
* return - 1 pass 0 for error
* keylen - key length
* Output:
* okey - filled with derived key
* return - 1 on pass, 0 fail
*/
static int SNMPKDF(const EVP_MD *evp_md,
const unsigned char *e_id, size_t e_len,
unsigned char *password, size_t password_len,
unsigned char *okey, size_t okeylen)
unsigned char *okey, size_t keylen)
{
EVP_MD_CTX *md = NULL;
unsigned char digest[EVP_MAX_MD_SIZE];
@ -285,7 +288,7 @@ static int SNMPKDF(const EVP_MD *evp_md,
int ret = 0;
/* Limited to SHA-1 and SHA-2 hashes presently */
if (okey == NULL || okeylen == 0)
if (okey == NULL || keylen == 0)
return 0;
md = EVP_MD_CTX_new();
@ -295,7 +298,7 @@ static int SNMPKDF(const EVP_MD *evp_md,
}
mdsize = EVP_MD_get_size(evp_md);
if (mdsize <= 0 || mdsize < okeylen)
if (mdsize <= 0 || mdsize > keylen)
goto err;
if (!EVP_DigestInit_ex(md, evp_md, NULL))
@ -315,7 +318,7 @@ static int SNMPKDF(const EVP_MD *evp_md,
|| !EVP_DigestFinal_ex(md, digest, &md_len))
goto err;
memcpy(okey, digest, okeylen);
memcpy(okey, digest, md_len);
ret = 1;

View file

@ -0,0 +1,445 @@
/*
* Copyright 2026 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/bn.h>
#include <openssl/core_names.h>
#include <openssl/proverr.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include "crypto/evp.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_util.h"
#include "providers/implementations/kdfs/srtpkdf.inc"
#define KDF_SRTP_AUTH_KEY_LEN 20
#define KDF_SRTP_SALT_KEY_LEN 14
#define KDF_SRTCP_AUTH_KEY_LEN KDF_SRTP_AUTH_KEY_LEN
#define KDF_SRTCP_SALT_KEY_LEN KDF_SRTP_SALT_KEY_LEN
#define KDF_SRTP_SALT_LEN 14
#define KDF_SRTP_KDR_LEN 6
#define KDF_SRTP_IDX_LEN 6
#define KDF_SRTCP_IDX_LEN 4
#define KDF_SRTP_IV_LEN 16
#define KDF_SRTP_MAX_KDR 24
#define KDF_SRTP_MAX_LABEL 7
#define KDF_SRTP_MAX_SALT_LEN (KDF_SRTP_SALT_LEN + 2)
/* See RFC 3711, Section 4.3.3 */
static OSSL_FUNC_kdf_newctx_fn kdf_srtpkdf_new;
static OSSL_FUNC_kdf_dupctx_fn kdf_srtpkdf_dup;
static OSSL_FUNC_kdf_freectx_fn kdf_srtpkdf_free;
static OSSL_FUNC_kdf_reset_fn kdf_srtpkdf_reset;
static OSSL_FUNC_kdf_derive_fn kdf_srtpkdf_derive;
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_srtpkdf_settable_ctx_params;
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_srtpkdf_set_ctx_params;
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 uint32_t kdr, const uint32_t kdr_n,
const uint32_t label, unsigned char *obuffer, const size_t keylen);
typedef struct {
/* Warning: Any changes to this structure may require you to update kdf_srtpkdf_dup */
void *provctx;
PROV_CIPHER cipher;
unsigned char *key;
size_t key_len;
unsigned char *salt;
size_t salt_len;
unsigned char *index;
size_t index_len;
uint32_t kdr;
uint32_t kdr_n; /* 2 ** kdr_n = kdr */
uint32_t label;
} KDF_SRTPKDF;
static void *kdf_srtpkdf_new(void *provctx)
{
KDF_SRTPKDF *ctx;
if (!ossl_prov_is_running())
return NULL;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL)
ctx->provctx = provctx;
return ctx;
}
static void *kdf_srtpkdf_dup(void *vsrc)
{
const KDF_SRTPKDF *src = (const KDF_SRTPKDF *)vsrc;
KDF_SRTPKDF *dest;
dest = kdf_srtpkdf_new(src->provctx);
if (dest != NULL) {
if (!ossl_prov_memdup(src->key, src->key_len,
&dest->key, &dest->key_len)
|| !ossl_prov_memdup(src->salt, src->salt_len,
&dest->salt, &dest->salt_len)
|| !ossl_prov_memdup(src->index, src->index_len,
&dest->index, &dest->index_len)
|| !ossl_prov_cipher_copy(&dest->cipher, &src->cipher))
goto err;
dest->kdr = src->kdr;
dest->kdr_n = src->kdr_n;
dest->label = src->label;
}
return dest;
err:
kdf_srtpkdf_free(dest);
return NULL;
}
static void kdf_srtpkdf_free(void *vctx)
{
KDF_SRTPKDF *ctx = (KDF_SRTPKDF *)vctx;
if (ctx != NULL) {
kdf_srtpkdf_reset(ctx);
OPENSSL_free(ctx);
}
}
static void kdf_srtpkdf_reset(void *vctx)
{
KDF_SRTPKDF *ctx = (KDF_SRTPKDF *)vctx;
void *provctx = ctx->provctx;
ossl_prov_cipher_reset(&ctx->cipher);
OPENSSL_clear_free(ctx->key, ctx->key_len);
OPENSSL_clear_free(ctx->index, ctx->index_len);
OPENSSL_clear_free(ctx->salt, ctx->salt_len);
memset(ctx, 0, sizeof(*ctx));
ctx->provctx = provctx;
}
static int srtpkdf_set_membuf(unsigned char **dst, size_t *dst_len,
const OSSL_PARAM *p)
{
OPENSSL_clear_free(*dst, *dst_len);
*dst = NULL;
*dst_len = 0;
return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len);
}
static int is_power_of_two(uint32_t x, uint32_t *n)
{
/* Check if we've been given an exact power of two */
if (x == 0 || (x & (x - 1)) != 0) {
*n = 0;
return 0;
}
/* Count the number of trailing bits in the passed value */
#ifdef __GNUC__
*n = __builtin_ctz(x);
#else
{
uint32_t count = 0;
while ((x & 1) == 0) {
count++;
x >>= 1;
}
*n = count;
}
#endif
return 1;
}
static int kdf_srtpkdf_derive(void *vctx, unsigned char *key, size_t keylen,
const OSSL_PARAM params[])
{
KDF_SRTPKDF *ctx = (KDF_SRTPKDF *)vctx;
const EVP_CIPHER *cipher;
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
if (!ossl_prov_is_running() || !kdf_srtpkdf_set_ctx_params(ctx, params))
return 0;
cipher = ossl_prov_cipher_cipher(&ctx->cipher);
if (cipher == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
return 0;
}
if (ctx->key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
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);
}
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 = PROV_LIBCTX_OF(ctx->provctx);
const EVP_CIPHER *cipher;
if (params == NULL)
return 1;
if (ctx == NULL || !srtp_set_ctx_params_decoder(params, &p))
return 0;
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.key != NULL)
&& !srtpkdf_set_membuf(&ctx->key, &ctx->key_len, p.key))
return 0;
if ((p.salt != NULL)
&& !srtpkdf_set_membuf(&ctx->salt, &ctx->salt_len, p.salt))
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 (p.label != NULL) {
if (!OSSL_PARAM_get_uint32(p.label, &ctx->label))
return 0;
}
return 1;
}
static const OSSL_PARAM *kdf_srtpkdf_settable_ctx_params(ossl_unused void *ctx,
ossl_unused void *p_ctx)
{
return srtp_set_ctx_params_list;
}
static int kdf_srtpkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
struct srtp_get_ctx_params_st p;
KDF_SRTPKDF *ctx = vctx;
if (ctx == NULL || !srtp_get_ctx_params_decoder(params, &p))
return 0;
if (p.size != NULL) {
size_t sz = EVP_CIPHER_key_length(ossl_prov_cipher_cipher(&ctx->cipher));
if (!OSSL_PARAM_set_size_t(p.size, sz))
return 0;
}
return 1;
}
static const OSSL_PARAM *kdf_srtpkdf_gettable_ctx_params(ossl_unused void *ctx,
ossl_unused void *p_ctx)
{
return srtp_get_ctx_params_list;
}
const OSSL_DISPATCH ossl_kdf_srtpkdf_functions[] = {
{ OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_srtpkdf_new },
{ OSSL_FUNC_KDF_DUPCTX, (void (*)(void))kdf_srtpkdf_dup },
{ OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_srtpkdf_free },
{ OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_srtpkdf_reset },
{ OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_srtpkdf_derive },
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
(void (*)(void))kdf_srtpkdf_settable_ctx_params },
{ OSSL_FUNC_KDF_SET_CTX_PARAMS,
(void (*)(void))kdf_srtpkdf_set_ctx_params },
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
(void (*)(void))kdf_srtpkdf_gettable_ctx_params },
{ OSSL_FUNC_KDF_GET_CTX_PARAMS,
(void (*)(void))kdf_srtpkdf_get_ctx_params },
{ 0, NULL }
};
/*
* SRTPKDF - In compliance with SP800-135 and RFC3711, calculate
* various keys defined by label using a master key,
* master salt, kdr(if non-zero) and index.
*
* Denote the cryptographic key (encryption key, cipher salt or
* authentication key(HMAC key), etc) to be derived as K. The
* length of K is denoted by L. Below is a description of the KDF.
*
* master_salt: a random non-salt value.
* kdr: the key derivation rate. kdr is a number from the set
* factor of 2.
* index: a 48-bit value in RTP or a 32-bit value in RTCP.
* See Sections 3.2.1 and 4.3.2 of RFC 3711 for details.
* A function, DIV, is defined as followed:
* a and x are non-negative integers.
* a DIV x = a | x (a DIV x) is represented as a bit string whose
* length (in bits) is the same as a.
* label: an 8-bit value represented by two hexadecimal numbers from
* the set of {0x00,0x01, 0x02, 0x03, 0x04, 0x05}.
* https://www.ietf.org/archive/id/draft-ietf-avtcore-srtp-encrypted-header-ext-01.html
* The values 06 and 07 are used.
* key_id = label || (index DIV kdr)
*
* Input:
* cipher - AES cipher
* mkey - pointer to master key
* msalt - pointer to master salt
* idx - pointer to index
* 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
* 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 uint32_t kdr, const uint32_t kdr_n,
const uint32_t label, unsigned char *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];
BIGNUM *bn_index = NULL, *bn_salt = NULL;
int ret, iv_len = KDF_SRTP_IV_LEN, rv = 0;
salt_len = KDF_SRTP_SALT_LEN;
/* get label-specific lengths */
switch (label) {
case 0:
index_len = KDF_SRTP_IDX_LEN;
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 7:
index_len = KDF_SRTP_IDX_LEN;
o_len = KDF_SRTP_SALT_KEY_LEN;
break;
default:
return rv;
}
if ((obuffer == NULL) || (keylen > INT_MAX) || (o_len > (int)keylen))
return rv;
/* set up a couple of work areas for the final logic on the salt */
memset(iv, 0, KDF_SRTP_IV_LEN);
memset(master_salt, 0, KDF_SRTP_MAX_SALT_LEN);
memcpy(master_salt, msalt, salt_len);
/* gather some bignums for some math */
bn_index = BN_new();
bn_salt = BN_new();
if ((bn_index == NULL) || (bn_salt == NULL)) {
BN_free(bn_index);
BN_free(bn_salt);
return rv;
}
/* if index is NULL or kdr=0, then index and kdr are not in play */
if ((index != NULL) && (kdr > 0)) {
if (!BN_bin2bn(index, index_len, bn_index))
goto err;
ret = BN_rshift(bn_salt, bn_index, kdr_n);
if (!ret)
goto err;
iv_len = BN_bn2bin(bn_salt, iv);
for (i = 1; i <= iv_len; i++)
master_salt[salt_len - i] ^= iv[iv_len - i];
}
/* take the munged up salt from above and add the label */
memset(local_salt, 0, KDF_SRTP_MAX_SALT_LEN);
memcpy(local_salt, master_salt, salt_len);
local_salt[((KDF_SRTP_SALT_LEN - 1) - index_len)] ^= label;
/* perform the AES encryption on the master key and derived salt */
memset(buf, 0, o_len);
if (!(ctx = EVP_CIPHER_CTX_new())
|| (EVP_EncryptInit_ex(ctx, cipher, NULL, mkey, local_salt) <= 0)
|| (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0)
|| (EVP_EncryptUpdate(ctx, (unsigned char *)obuffer, &outl, buf, o_len) <= 0)
|| (EVP_EncryptFinal_ex(ctx, (unsigned char *)obuffer, &outl) <= 0))
goto err;
rv = 1;
err:
EVP_CIPHER_CTX_free(ctx);
OPENSSL_cleanse(iv, KDF_SRTP_IV_LEN);
OPENSSL_cleanse(local_salt, KDF_SRTP_MAX_SALT_LEN);
OPENSSL_cleanse(master_salt, KDF_SRTP_IV_LEN);
BN_clear_free(bn_index);
BN_clear_free(bn_salt);
return rv;
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2026 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
{-
use OpenSSL::paramnames qw(produce_param_decoder);
-}
{- produce_param_decoder('srtp_set_ctx_params',
(['OSSL_KDF_PARAM_PROPERTIES', 'propq', 'utf8_string'],
['OSSL_KDF_PARAM_CIPHER', 'cipher', 'utf8_string'],
['OSSL_KDF_PARAM_KEY', 'key', 'octet_string'],
['OSSL_KDF_PARAM_SALT', 'salt', 'octet_string'],
['OSSL_KDF_PARAM_SRTPKDF_INDEX', 'index', 'octet_string'],
['OSSL_KDF_PARAM_SRTPKDF_KDR', 'kdr', 'uint32'],
['OSSL_KDF_PARAM_LABEL', 'label', 'uint32'],
)); -}
{- produce_param_decoder('srtp_get_ctx_params',
(['OSSL_KDF_PARAM_SIZE', 'size', 'size_t'],
)); -}

View file

@ -42,6 +42,7 @@ my $no_determinstic_nonce = disabled("hmac-drbg-kdf");
my $no_kbkdf = disabled("kbkdf");
my $no_krb5kdf = disabled("krb5kdf");
my $no_snmpkdf = disabled("snmpkdf");
my $no_srtpkdf = disabled("srtpkdf");
my $no_sshkdf = disabled("sshkdf");
# Default config depends on if the legacy module is built or not
@ -76,6 +77,7 @@ my @files = qw(
);
push @files, qw(evpkdf_ssh.txt) unless $no_sshkdf;
push @files, qw(evpkdf_snmp.txt) unless $no_snmpkdf;
push @files, qw(evpkdf_srtp.txt) unless $no_srtpkdf;
push @files, qw(
evpkdf_kbkdf_counter.txt
evpkdf_kbkdf_kmac.txt

View file

@ -0,0 +1,396 @@
#
# Copyright 2026 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
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# Tests start with one of these keywords
# Cipher Decrypt Derive Digest Encoding KDF MAC PBE
# PrivPubKeyPair Sign Verify VerifyRecover
# and continue until a blank line. Lines starting with a pound sign are ignored.
Title = SRTPKDF tests (from RFC 3711 test vectors and additional cases)
# Test Case 1: RFC 3711 test vectors B.3, encryption key
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
# Test Case 1.1, variation, missing kdr (default as zero)
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
# Test Case 1.2, variation, missing index (default as zero)
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
# Test Case 1.3, variation, default kdr and index
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
# Test Case 1.4, variation, missing label (default as zero)
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Output = C61E7A93744F39EE10734AFE3FF7A087
# Test Case 2: RFC 3711 test vectors B.3, salt key
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:2
Output = 30CBBC08863D8C85D49DB34A9AE1
# Test Case 3: RFC 3711 test vectors B.3, authentication key
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:1
Output = CEBE321F6FF7716B6FD4AB49AF256A156D38BAA4
# Negative Test case 1, missing cipher
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_CTRL_ERROR
# Negative Test case 2, invalid cipher
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CBC
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_CTRL_ERROR
# Negative Test case 3, missing key
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_DERIVE_ERROR
# Negative Test case 4, missing salt
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_DERIVE_ERROR
# Negative Test case 5, invalid label
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0
Ctrl.index = hexindex:000000000000
Ctrl.label = label:8
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_DERIVE_ERROR
# Negative Test case 6, invalid kdr (not power of 2)
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:5
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_DERIVE_ERROR
# Negative Test case 7, invalid kdr (kdr out of range)
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:E1F97A0D3E018BE0D64FA32C06DE4139
Ctrl.hexsalt = hexsalt:0EC675AD498AFEEBB6960B3AABE6
Ctrl.kdr = kdr:0x10000000
Ctrl.index = hexindex:000000000000
Ctrl.label = label:0
Output = C61E7A93744F39EE10734AFE3FF7A087
Result = KDF_DERIVE_ERROR
# Additional tests from
# https://github.com/usnistgov/ACVP-Server/tree/master/gen-val/json-files/kdf-components-srtp-1.0
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtpKe
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:08284B49F520
Ctrl.label = label:0
Output = A920DF50EAA111D03FBE9B203121C07D
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtpKa
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:08284B49F520
Ctrl.label = label:1
Output = A337DC070C0DAFA942F1E3A27ACD3C9917CE4B4D
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtpKs
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:08284B49F520
Ctrl.label = label:2
Output = 9E2BC99C86037F2AD98D72927428
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtcpKe
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:69B62109
Ctrl.label = label:3
Output = 94D76CA7ADB05b8631CF62538D97BE74
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtcpKa
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:69B62109
Ctrl.label = label:4
Output = FA02251D693645BC1001f83C5A13CB3E3D77F7EA
# prompt.json tgId:3, tcid:21, expectedResults.json tcId:21 srtcpKs
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:69B62109
Ctrl.label = label:5
Output = 70C0481A04E3610EC8AF8623FA9B
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtpKe
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:3D6FECDCE1BE
Ctrl.label = label:0
Output = A2F4D858CCDF585D9C5CA787C5A3031F
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtpKa
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:3D6FECDCE1BE
Ctrl.label = label:1
Output = C140C97CAC05B2ED338AD353014A90012F37B45C
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtpKs
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:3D6FECDCE1BE
Ctrl.label = label:2
Output = AA6DE94B3BCB5108EFD350AD6936
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtcpKe
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:1C7B571C
Ctrl.label = label:3
Output = 2844C8F56E2AF865E4EBBD0D083A4FAE
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtcpKa
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:1C7B571C
Ctrl.label = label:4
Output = 50135309CF64D5162723749CCF085708F8E81636
# prompt.json tgId:4, tcid:31, expectedResults.json tcId:31 srtcpKs
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:127A535F66D5D43135E5DB87F04AF2DB
Ctrl.hexsalt = hexsalt:82D0D04DC693E29E0FE7FECBF041
Ctrl.kdr = kdr:2
Ctrl.index = hexindex:1C7B571C
Ctrl.label = label:5
Output = 47CB081EC69F7E74FEB3FCD1BD20
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtpKe
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:F4EE616415B9
Ctrl.label = label:0
Output = B46322B06F6E4B189F27744EAD8C5173
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtpKa
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:F4EE616415B9
Ctrl.label = label:1
Output = F9F246054B3D4AA2520CE2612192749AA6970BB0
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtpKs
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:F4EE616415B9
Ctrl.label = label:2
Output = 18EA8EA36A90617224FBFBCB849A
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtcpKe
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:13DE080C
Ctrl.label = label:3
Output = F4140d2419f7A75CEE91FC942CD94514
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtcpKa
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:13DE080C
Ctrl.label = label:4
Output = 6E65548ABFE131FF91E7AE75409F96AD9D9FE345
# prompt.json tgId:6, tcid:51, expectedResults.json tcId:51 srtcpKs
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:CF08F8159FCF18DA8108A3FE3B707C2B
Ctrl.hexsalt = hexsalt:4AF8352708E0A164C6645A63E5BB
Ctrl.kdr = kdr:8
Ctrl.index = hexindex:13DE080C
Ctrl.label = label:5
Output = 2C195A5AA9F539BD7CC7D6E23483
# internalProjection.json, tgId: 1
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:A48A570A43E12372BF58495FDFD88D78
Ctrl.hexsalt = hexsalt:E1D109B42D6C16A8830F9E7DDF4B
Ctrl.index = hexindex:8E5BDF08FA78
Ctrl.label = label:0
Output = 30371635BF658204857EC5BFE13AFFE3
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:A48A570A43E12372BF58495FDFD88D78
Ctrl.hexsalt = hexsalt:E1D109B42D6C16A8830F9E7DDF4B
Ctrl.index = hexindex:8E5BDF08FA78
Ctrl.label = label:1
Output = 83E0821E1DDBD044C2DD3A980BB445875F97B4D5
FIPSversion = >=4.0.0
KDF = SRTPKDF
Ctrl.cipher = cipher:AES-128-CTR
Ctrl.hexkey = hexkey:A48A570A43E12372BF58495FDFD88D78
Ctrl.hexsalt = hexsalt:E1D109B42D6C16A8830F9E7DDF4B
Ctrl.index = hexindex:8E5BDF08FA78
Ctrl.label = label:2
Output = B27816A7A139D73E71A55FCD7006

View file

@ -228,6 +228,9 @@ my %params = (
'OSSL_KDF_PARAM_INFO' => "info", # octet string
'OSSL_KDF_PARAM_SEED' => "seed", # octet string
'OSSL_KDF_PARAM_SNMPKDF_EID' => "eid", # octet string
'OSSL_KDF_PARAM_SRTPKDF_INDEX' => "index", # octet string
'OSSL_KDF_PARAM_SRTPKDF_KDR' => "kdr", # uint32_t
'OSSL_KDF_PARAM_SRTPKDF_LABEL' => "label", # uint32_t
'OSSL_KDF_PARAM_SSHKDF_XCGHASH' => "xcghash", # octet string
'OSSL_KDF_PARAM_SSHKDF_SESSION_ID' => "session_id", # octet string
'OSSL_KDF_PARAM_SSHKDF_TYPE' => "type", # int