ReactOS 0.4.17-dev-1005-g171e1de
srtp_kdf.c
Go to the documentation of this file.
1//
2// srtp_kdf.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7//
8// This module implements SRTP-KDF specified in RFC 3711 Section 4.3.1.
9//
10
11#include "precomp.h"
12
13
14#define SYMCRYPT_SRTP_KDF_SALT_SIZE (112 / 8)
15
16
17
24{
26}
27
28
33 _In_reads_(cbSalt) PCBYTE pbSalt,
34 SIZE_T cbSalt,
35 UINT32 uKeyDerivationRate,
36 UINT64 uIndex,
37 UINT32 uIndexWidth,
38 BYTE label,
39 _Out_writes_(cbOutput) PBYTE pbOutput,
40 SIZE_T cbOutput)
41{
42 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
43 BYTE X[16] = { 0 };
44
45 //
46 // uIndexWidth must be one of 0, 32 or 48. RFC 3711 defines SRTP indices to be
47 // 48-bits. SRTCP indices were first specified as 32-bit values and then updated to
48 // 48-bits by Errata ID 3712. uIndexWidth parameter allows specifying the width of
49 // the uIndex parameter for both SRTP and SRTCP indices. The test vectors use
50 // 32-bit SRTCP index values.
51 //
52 // The default value of 0 is equivalent to setting uIndexWidth to 48.
53 if (uIndexWidth == 0)
54 {
55 uIndexWidth = 48;
56 }
57 else if (uIndexWidth != 32 && uIndexWidth != 48)
58 {
59 scError = SYMCRYPT_INVALID_ARGUMENT;
60 goto cleanup;
61 }
62
63 if (cbSalt != SYMCRYPT_SRTP_KDF_SALT_SIZE)
64 {
65 scError = SYMCRYPT_INVALID_ARGUMENT;
66 goto cleanup;
67 }
68
69 // uKeyDerivationRate must be zero or 2^i for 0 <= i <= 24.
70 // This is verified by checking both it is not greater than 2^24 and it is either zero or a power of two.
71 if( (uKeyDerivationRate > (1 << 24)) || ((uKeyDerivationRate & (uKeyDerivationRate - 1)) != 0) )
72 {
73 scError = SYMCRYPT_INVALID_ARGUMENT;
74 goto cleanup;
75 }
76
77 // Initialize X to Salt || 0
78 memcpy(X, pbSalt, cbSalt);
79
80 // (uIndex DIV uKeyDerivationRate) operation can be performed with a right shift as
81 // uKeyDerivationRate is either zero or a power of 2. When uKeyDerivationRate is zero,
82 // DIV operation should evaluate to zero, which can be performed by shifting uIndex by 48 bits,
83 // i.e., maximum value it may have.
84 UINT32 kdrShift = 48;
85 if (uKeyDerivationRate)
86 {
87 for (UINT32 i = 0; i <= 24; i++)
88 {
89 if (uKeyDerivationRate == (1UL << i))
90 {
91 kdrShift = i;
92 break;
93 }
94 }
95 }
96
97 UINT64 r = uIndex >> kdrShift;
98
99 UINT64 key_id = ((UINT64)label << uIndexWidth) | r;
100
101 // XOR key_id into salt
102 //
103 // X = S0 ... |S6 ... S13| 0 0
104 // | key_id |
105 //
106 PBYTE pbXorPos = &X[SYMCRYPT_SRTP_KDF_SALT_SIZE - sizeof(key_id)];
107 UINT64 uSaltLsb = SYMCRYPT_LOAD_MSBFIRST64(pbXorPos);
108 SYMCRYPT_STORE_MSBFIRST64(pbXorPos, uSaltLsb ^ key_id);
109
110 //
111 // We break the read-once/write once rule here by writing to the pbOutput buffer twice.
112 // The first write wipes the buffer so that we get the raw keystream bytes from AES-CTR encryption.
113 // The second write to pbOutput occurs with the SymCryptAesCtrMsb64() call that produces the keystream bytes.
114 //
115 // Modification of pbOutput between the two calls does not leak any information, it just results in flipping of the
116 // corresponding bits of the correct output.
117 SymCryptWipe(pbOutput, cbOutput);
118 SymCryptAesCtrMsb64(&pExpandedKey->aesExpandedKey, X, pbOutput, pbOutput, cbOutput & ~0xf);
119
120 // SymCryptAesCtrMsb64 only processes full blocks. If cbOutput is not a multiple of 16 we generate the last block of
121 // keystream to local buffer and copy the necessary number of bytes to output.
122 if (cbOutput & 0xf)
123 {
124 BYTE lastBlockBytes[16] = { 0 };
125
126 SymCryptAesCtrMsb64(&pExpandedKey->aesExpandedKey, X, lastBlockBytes, lastBlockBytes, 16);
127
128 memcpy(pbOutput + 16 * (cbOutput / 16), lastBlockBytes, cbOutput & 0xf);
129
130 SymCryptWipeKnownSize(lastBlockBytes, sizeof(lastBlockBytes));
131 }
132
133cleanup:
134
135 return scError;
136}
137
138
144 _In_reads_(cbSalt) PCBYTE pbSalt,
145 SIZE_T cbSalt,
146 UINT32 uKeyDerivationRate,
147 UINT64 uIndex,
148 UINT32 uIndexWidth,
149 BYTE label,
150 _Out_writes_(cbOutput) PBYTE pbOutput,
151 SIZE_T cbOutput)
152{
153 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
155
156 scError = SymCryptSrtpKdfExpandKey(&expandedKey, pbKey, cbKey);
157
158 if (scError != SYMCRYPT_NO_ERROR)
159 {
160 goto cleanup;
161 }
162
163 scError = SymCryptSrtpKdfDerive(&expandedKey,
164 pbSalt, cbSalt,
165 uKeyDerivationRate,
166 uIndex, uIndexWidth,
167 label,
168 pbOutput, cbOutput);
169
170cleanup:
171
172 SymCryptWipeKnownSize(&expandedKey, sizeof(expandedKey));
173
174 return scError;
175}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static void cleanup(void)
Definition: main.c:1335
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const WCHAR label[]
Definition: itemdlg.c:1608
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_SRTP_KDF_SALT_SIZE
Definition: srtp_kdf.c:14
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptSrtpKdf(_In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _In_reads_(cbSalt) PCBYTE pbSalt, SIZE_T cbSalt, UINT32 uKeyDerivationRate, UINT64 uIndex, UINT32 uIndexWidth, BYTE label, _Out_writes_(cbOutput) PBYTE pbOutput, SIZE_T cbOutput)
Definition: srtp_kdf.c:141
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptSrtpKdfExpandKey(_Out_ PSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey)
Definition: srtp_kdf.c:20
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptSrtpKdfDerive(_In_ PCSYMCRYPT_SRTPKDF_EXPANDED_KEY pExpandedKey, _In_reads_(cbSalt) PCBYTE pbSalt, SIZE_T cbSalt, UINT32 uKeyDerivationRate, UINT64 uIndex, UINT32 uIndexWidth, BYTE label, _Out_writes_(cbOutput) PBYTE pbOutput, SIZE_T cbOutput)
Definition: srtp_kdf.c:31
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptAesExpandKeyEncryptOnly(_Out_ PSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey)
Definition: aes-key.c:230
#define SYMCRYPT_LOAD_MSBFIRST64(p)
Definition: symcrypt.h:304
VOID SYMCRYPT_CALL SymCryptAesCtrMsb64(_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, _Inout_updates_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: aes-default.c:404
#define SYMCRYPT_STORE_MSBFIRST64(p, v)
Definition: symcrypt.h:312
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_CALL
PCBYTE pbKey
PCBYTE SIZE_T cbKey
const BYTE * PCBYTE
PCVOID pExpandedKey
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193