]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add SRTPKDF implementation
authorHelen Zhang <helzhang@cisco.com>
Wed, 17 Dec 2025 21:45:26 +0000 (21:45 +0000)
committerNorbert Pocs <norbertp@openssl.org>
Fri, 23 Jan 2026 10:19:31 +0000 (11:19 +0100)
      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)

28 files changed:
.github/workflows/run-checker-daily.yml
.gitignore
CHANGES.md
Configure
INSTALL.md
build.info
crypto/err/openssl.txt
doc/build.info
doc/man1/openssl-kdf.pod.in
doc/man7/EVP_KDF-SRTPKDF.pod [new file with mode: 0644]
doc/man7/OSSL_PROVIDER-FIPS.pod
doc/man7/OSSL_PROVIDER-default.pod
include/openssl/core_names.h.in
include/openssl/proverr.h
include/openssl/self_test.h
providers/common/provider_err.c
providers/defltprov.c
providers/fips/fipsprov.c
providers/fips/self_test_data.inc
providers/implementations/include/prov/implementations.h
providers/implementations/include/prov/names.h
providers/implementations/kdfs/build.info
providers/implementations/kdfs/snmpkdf.c
providers/implementations/kdfs/srtpkdf.c [new file with mode: 0644]
providers/implementations/kdfs/srtpkdf.inc.in [new file with mode: 0644]
test/recipes/30-test_evp.t
test/recipes/30-test_evp_data/evpkdf_srtp.txt [new file with mode: 0644]
util/perl/OpenSSL/paramnames.pm

index 113e65e9f8305f7ae96df8698be5b572c35c1988..49c21ca17bdb1d4d9d7f04626147311d48be13dc 100644 (file)
@@ -105,6 +105,7 @@ jobs:
           no-sm4,
           no-snmpkdf,
           no-sock,
+          no-srtpkdf,
           no-sse2,
           no-sshkdf,
           no-sskdf,
index f5b55b927b389d7e5d16da761600e47c87a06853..ba7f69828b0e29d5b54e2cc43d05109c8a1e0516 100644 (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
index 757cea73ecde660de74fe632a2d1b56512251d6a..9901b34609c66ec3a4d2bc035945f1947a60d64e 100644 (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
 -----------
 
index efded13f3e71ff07df9f6c885a69d58ce01a9204..a8bf855a1af986b44089ee4ebc031cbe8b2b8ecd 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -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",
index 9a21f72db8a543a15d4d70879aae3d1dc62c3009..8350567e9efb1d4bafc89b7c18bb17d183b32d93 100644 (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.
index 5607fbdad468cf0c61404839658ec1a7092f2bc7..d6c4c2ba3edef1eaa039f36dfb4799218a5fccea 100644 (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]=\
index 3302b94a1e3c2719242c8413259d0ca1a6ac9ac2..da6a2e70ecf28245b0802c261df927d9b0c918d9 100644 (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
index 589516632aeb41dd491b6d9e95a9d43b443c66da..07b77e4ef0e98e17dec05fffa5929d2dd7771782 100644 (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 \
index ae153b4b817ec586fdf2f144da7b4b0144b9a21a..90a95a27ebf6b01b092640595ea8caf90a288cb7 100644 (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)>,
diff --git a/doc/man7/EVP_KDF-SRTPKDF.pod b/doc/man7/EVP_KDF-SRTPKDF.pod
new file mode 100644 (file)
index 0000000..c18853c
--- /dev/null
@@ -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
index 29ffe1592bcdb7ed43062643eb4da329d8792b4d..70fc2c597ee873b0d3eca511c07769d03bca2c14 100644 (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>)
index 5cc5f490ec28c5c686b37b00a4c699660aa0c949..207a46ce1e8156f5b1bf99ab80281d2792ee18c8 100644 (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)>
index e0a4c5e63259faad46034ea46eacd2db622cf0a8..1c4396e69b15f89e1e643fa42d211ab9f8093753 100644 (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"
index fdfa8916a28bedd1394547594a715a4a890b1c98..e27048faed25dbb0c3b4f9a3d2391e6a7f35e07d 100644 (file)
 #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
index 8dab9b6f99859484211dd93766ae0c8f8a62fd50..c5e4be955e79cca900aef5a5890729327cc9cad4 100644 (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"
index 6cdb7283331ec0b67dbf229e2d979663a3f29e34..f8fb4c16792dd21265b72a207c64309055e51f9a 100644 (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" },
index cddec70369855385ca544ef85cd562f82a44a2e4..87c53ca761ff7ab276b84b30d494c5b363c7e457 100644 (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
index ce2645ce073fdebdf4cd68653bfff675d0daffcb..f321990b6225dfa6c604dbc99f81acc6f6884e66 100644 (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
index 4d41126bc752595105cc9edc1d40bd2d90dfff28..bc7e77bf1f9cfca814b5b1962300f7dc1886c86d 100644 (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,
index 5a7ffd276a6aadbbc65344006304c3142c9f1ba5..990dd258643189b416198d18284acf334c493e15 100644 (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[];
index 6863f647142e25deb44fe42da2cd4d08463aa1dc..04b41d53c84fb7f05991038573a5a22f4bdc40c1 100644 (file)
 #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"
index f94c78bf4d4eb218176d9758d3468ed965b8aa2f..60146804b3ee454d42cb4ac560b65f6a397962d8 100644 (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
index f81738fee03c772d2743dc850d324e29e295eb1b..5e4831fdeb5966f59f527041509e16a343847115 100644 (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;
 
diff --git a/providers/implementations/kdfs/srtpkdf.c b/providers/implementations/kdfs/srtpkdf.c
new file mode 100644 (file)
index 0000000..46e5411
--- /dev/null
@@ -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;
+}
diff --git a/providers/implementations/kdfs/srtpkdf.inc.in b/providers/implementations/kdfs/srtpkdf.inc.in
new file mode 100644 (file)
index 0000000..0cf5ec1
--- /dev/null
@@ -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'],
+                         )); -}
index c6bb748c4f1236619d88484f7f754b79c477d75d..58221897a4fbc8115c8bd7e1480b605482803efc 100644 (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
diff --git a/test/recipes/30-test_evp_data/evpkdf_srtp.txt b/test/recipes/30-test_evp_data/evpkdf_srtp.txt
new file mode 100644 (file)
index 0000000..a810b90
--- /dev/null
@@ -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
index 8473aa2b07501165f7726a0123dcb9a8aaeff419..cea9d2d0686b894d15af8d24121b16e0576430c7 100644 (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