Generate a key-encryption key (KEK) for ECDH key exchange in a CMS EnvelopedData object.
Public Declare Function KDF_ForCms Lib "diCrPKI.dll" (ByRef lpOutput As Byte, ByVal nOutBytes As Long, ByRef lpZZ As Byte, ByVal nZzLen As Long, ByRef lpUkm As Byte, ByVal nUkmLen As Long, ByVal szParams As String, ByVal nOptions As Long) As Long
nRet = KDF_ForCms(lpOutput(0), nOutBytes, lpZZ(0), nZzLen, lpUkm(0), nUkmLen, szParams, nOptions) ' Note the "(0)" after the byte array parameters
long __stdcall KDF_ForCms(unsigned char *lpOutput, long nOutBytes, const void *lpZZ, long nZzLen, const void *lpUkm, long nUkmLen, const char *szParams, long nOptions);
cms3DESwrap
aes128-wrap
aes192-wrap
aes256-wrap
If successful, the return value is the number of bytes in or required for the output key material; otherwise it returns a negative error code.
Public Function kdfForCms
(lpZZ() As Byte, lpUkm() As Byte, Optional nOptions As Long = 0) As Byte()
static bvec_t dipki::Kdf::ForCms (const bvec_t &zz, KeyWrapAlg keyWrapAlg, KdfAlg kdfAlg=KdfAlg::X963, HashAlg hashAlg=HashAlg::Sha1, const bvec_t &ukm={})
static Kdf.for_cms(zz, keywrapalg, kdfalg=KdfAlg.X963, hashalg=HashAlg.SHA1, ukm=None)
This is a specialist function using the key definition algorithms described in [RFC5753] and [RFC8418] when used for key agreement with ECDH in a CMS EnvelopedData object using the ECC-CMS-SharedInfo structure.
Note the behaviour of this function is different from KDF_KeyBytes
as the length of the output is fixed by the key wrap algorithm and is not an arbitrary number.
The function returns the number of bytes in the output key material, not zero on success.
Specify a zero nOutChars or NULL
for szOutput to find the required number of bytes for the given key wrap algorithm.
The output buffer for the output key material lpOutput must have been dimensioned to at least the required length in nOutBytes.
When using ECDH with EnvelopedData, the key-encryption keys are derived using the ECC-CMS-SharedInfo type, described in section 7.2 of [RFC5753] (the SharedInfo input to the KDF is the DER-encoded ECC-CMS-SharedInfo structure). The processing of the ukm with the HKDF key derivation function is described in section 2.2 of [RFC8418] (TL;DR if provided, the ukm is included in the entityUInfo field of the ECC-CMS-SharedInfo structure and is used as the salt, otherwise no salt is provided).
Dim nBytes As Long Dim lpOutput() As Byte Dim lpZZ() As Byte Dim lpUkm() As Byte lpZZ = cnvFromHex("160E3F5588C6FB4E9CEE8BC3C1C5000AB86396468C3D1CAEC0CB6E21536B5513") ' How many bytes for specified key wrap algorithm? nBytes = KDF_ForCms(ByVal 0&, 0, lpZZ(0), cnvBytesLen(lpZZ), ByVal 0&, 0, "", PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1) Debug.Print "KDF_ForCms returns " & nBytes Debug.Assert (nBytes > 0) ReDim lpOutput(nBytes - 1) nBytes = KDF_ForCms(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), ByVal 0&, 0, "", PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1) Debug.Print "KEK=" & cnvToHex(lpOutput) Debug.Print "OK =" & "04D616C654CDF62BB186A5A088B60FB5" lpUkm = cnvFromHex("616263") ' "abc" nBytes = KDF_ForCms(ByVal 0&, 0, lpZZ(0), cnvBytesLen(lpZZ), lpUkm(0), cnvBytesLen(lpUkm), "", PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256) Debug.Print "KDF_ForCms returns " & nBytes Debug.Assert (nBytes > 0) ReDim lpOutput(nBytes - 1) nBytes = KDF_ForCms(lpOutput(0), nBytes, lpZZ(0), cnvBytesLen(lpZZ), lpUkm(0), cnvBytesLen(lpUkm), "", PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256) Debug.Print "KEK=" & cnvToHex(lpOutput) Debug.Print "OK =" & "1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5"
KDF_ForCms returns 16 KEK=04D616C654CDF62BB186A5A088B60FB5 OK =04D616C654CDF62BB186A5A088B60FB5 KDF_ForCms returns 32 KEK=1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5 OK =1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5
Dim lpKEK() As Byte Dim lpZZ() As Byte Dim lpUkm() As Byte lpZZ = cnvFromHex("160E3F5588C6FB4E9CEE8BC3C1C5000AB86396468C3D1CAEC0CB6E21536B5513") lpKEK = kdfForCms(lpZZ, lpUkm, PKI_KWRAP_AES128 Or PKI_KDF_X963 Or PKI_HASH_SHA1) Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK) Debug.Print "OK = 04D616C654CDF62BB186A5A088B60FB5" lpUkm = cnvFromHex("616263") ' "abc" lpKEK = kdfForCms(lpZZ, lpUkm, PKI_KWRAP_AES256 Or PKI_KDF_HKDF Or PKI_HASH_SHA256) Debug.Print "KEK = " & cnvHexStrFromBytes(lpKEK) Debug.Print "OK = 1D06D6FD5C1EBFB33CAD875E6B99781D3D750875F573C9093CECBFBA6937ACC5"