1 //========= Copyright Valve LLC, All rights reserved. ========================
2
3 #include "crypto.h"
4 #ifdef STEAMNETWORKINGSOCKETS_CRYPTO_VALVEOPENSSL
5
6 #if defined(_WIN32)
7 #ifdef __MINGW32__
8 // x86intrin.h gets included by MinGW's winnt.h, so defining this avoids
9 // redefinition of AES-NI intrinsics below
10 #define _X86INTRIN_H_INCLUDED
11 #endif
12 #include "winlite.h"
13 #elif defined(POSIX)
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #endif
19
20 #include <tier0/vprof.h>
21 #include <tier1/utlmemory.h>
22 #include "crypto.h"
23
24 #include "tier0/memdbgoff.h"
25 #include <openssl/evp.h>
26 #include <openssl/pem.h>
27 #include "tier0/memdbgon.h"
28
29 #include "opensslwrapper.h"
30
31 #if OPENSSL_VERSION_NUMBER < 0x10100000
EVP_MD_CTX_free(EVP_MD_CTX * ctx)32 inline void EVP_MD_CTX_free( EVP_MD_CTX *ctx )
33 {
34 EVP_MD_CTX_destroy( ctx );
35 }
36 #endif
37
OneTimeCryptoInitOpenSSL()38 void OneTimeCryptoInitOpenSSL()
39 {
40 static bool once;
41 if ( !once )
42 {
43 once = true; // Not thread-safe
44 COpenSSLWrapper::Initialize();
45 atexit( &COpenSSLWrapper::Shutdown );
46 }
47 }
48
Init()49 void CCrypto::Init()
50 {
51 OneTimeCryptoInitOpenSSL();
52 }
53
54 template < typename CTXType, void(*CleanupFunc)(CTXType)>
55 class EVPCTXPointer
56 {
57 public:
58 CTXType ctx;
59
EVPCTXPointer()60 EVPCTXPointer() { this->ctx = NULL; }
EVPCTXPointer(CTXType ctx)61 EVPCTXPointer(CTXType ctx) { this->ctx = ctx; }
~EVPCTXPointer()62 ~EVPCTXPointer() { CleanupFunc(ctx); }
63 };
64
SymmetricCryptContextBase()65 SymmetricCryptContextBase::SymmetricCryptContextBase()
66 {
67 m_ctx = nullptr;
68 m_cbIV = 0;
69 m_cbTag = 0;
70 }
71
Wipe()72 void SymmetricCryptContextBase::Wipe()
73 {
74 if ( m_ctx )
75 {
76 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)m_ctx;
77 #if OPENSSL_VERSION_NUMBER < 0x10100000
78 EVP_CIPHER_CTX_cleanup( ctx );
79 delete ctx;
80 #else
81 EVP_CIPHER_CTX_free( ctx );
82 #endif
83 m_ctx = nullptr;
84 }
85 m_cbIV = 0;
86 m_cbTag = 0;
87 }
88
InitCipher(const void * pKey,size_t cbKey,size_t cbIV,size_t cbTag,bool bEncrypt)89 bool AES_GCM_CipherContext::InitCipher( const void *pKey, size_t cbKey, size_t cbIV, size_t cbTag, bool bEncrypt )
90 {
91 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)m_ctx;
92 if ( ctx )
93 {
94 #if OPENSSL_VERSION_NUMBER < 0x10100000
95 EVP_CIPHER_CTX_cleanup( ctx );
96 EVP_CIPHER_CTX_init( ctx );
97 #else
98 EVP_CIPHER_CTX_reset( ctx );
99 #endif
100 }
101 else
102 {
103 #if OPENSSL_VERSION_NUMBER < 0x10100000
104 ctx = new EVP_CIPHER_CTX;
105 if ( !ctx )
106 return false;
107 EVP_CIPHER_CTX_init( ctx );
108 #else
109 ctx = EVP_CIPHER_CTX_new();
110 if ( !ctx )
111 return false;
112 #endif
113 m_ctx = ctx;
114 }
115
116 // Select the cipher based on the size of the key
117 const EVP_CIPHER *cipher = nullptr;
118 switch ( cbKey )
119 {
120 case 128/8: cipher = EVP_aes_128_gcm(); break;
121 case 192/8: cipher = EVP_aes_192_gcm(); break;
122 case 256/8: cipher = EVP_aes_256_gcm(); break;
123 }
124 if ( cipher == nullptr )
125 {
126 AssertMsg( false, "Invalid AES-GCM key size" );
127 Wipe();
128 return false;
129 }
130
131 // Setup for encryption setting the key
132 if ( EVP_CipherInit_ex( ctx, cipher, nullptr, (const uint8*)pKey, nullptr, bEncrypt ? 1 : 0 ) != 1 )
133 {
134 Wipe();
135 return false;
136 }
137
138 // Set IV length
139 if ( EVP_CIPHER_CTX_ctrl( ctx, EVP_CTRL_GCM_SET_IVLEN, (int)cbIV, NULL) != 1 )
140 {
141 AssertMsg( false, "Bad IV size" );
142 Wipe();
143 return false;
144 }
145
146 // Remember parameters
147 m_cbIV = (uint32)cbIV;
148 m_cbTag = (uint32)cbTag;
149 return true;
150 }
151
Encrypt(const void * pPlaintextData,size_t cbPlaintextData,const void * pIV,void * pEncryptedDataAndTag,uint32 * pcbEncryptedDataAndTag,const void * pAdditionalAuthenticationData,size_t cbAuthenticationData)152 bool AES_GCM_EncryptContext::Encrypt(
153 const void *pPlaintextData, size_t cbPlaintextData,
154 const void *pIV,
155 void *pEncryptedDataAndTag, uint32 *pcbEncryptedDataAndTag,
156 const void *pAdditionalAuthenticationData, size_t cbAuthenticationData // Optional additional authentication data. Not encrypted, but will be included in the tag, so it can be authenticated.
157 )
158 {
159 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)m_ctx;
160 if ( !ctx )
161 {
162 AssertMsg( false, "Not initialized!" );
163 *pcbEncryptedDataAndTag = 0;
164 return false;
165 }
166
167 // Calculate size of encrypted data. Note that GCM does not use padding.
168 uint32 cbEncryptedWithoutTag = (uint32)cbPlaintextData;
169 uint32 cbEncryptedTotal = cbEncryptedWithoutTag + m_cbTag;
170
171 // Make sure their buffer is big enough
172 if ( cbEncryptedTotal > *pcbEncryptedDataAndTag )
173 {
174 AssertMsg( false, "Buffer isn't big enough to hold padded+encrypted data and tag" );
175 return false;
176 }
177
178 // This function really shouldn't fail unless we have a bug,
179 // so people might not check the return value. So make sure
180 // if we do fail, they don't think anything was encrypted.
181 *pcbEncryptedDataAndTag = 0;
182
183 // Set IV
184 VerifyFatal( EVP_EncryptInit_ex( ctx, nullptr, nullptr, nullptr, (const uint8*)pIV ) == 1 );
185
186 int nBytesWritten;
187
188 // AAD, if any
189 if ( cbAuthenticationData > 0 && pAdditionalAuthenticationData )
190 {
191 VerifyFatal( EVP_EncryptUpdate( ctx, nullptr, &nBytesWritten, (const uint8*)pAdditionalAuthenticationData, (int)cbAuthenticationData ) == 1 );
192 }
193 else
194 {
195 Assert( cbAuthenticationData == 0 );
196 }
197
198 // Now the actual plaintext to be encrypted
199 uint8 *pOut = (uint8 *)pEncryptedDataAndTag;
200 VerifyFatal( EVP_EncryptUpdate( ctx, pOut, &nBytesWritten, (const uint8*)pPlaintextData, (int)cbPlaintextData ) == 1 );
201 pOut += nBytesWritten;
202
203 // Finish up
204 VerifyFatal( EVP_EncryptFinal_ex( ctx, pOut, &nBytesWritten ) == 1 );
205 pOut += nBytesWritten;
206
207 // Make sure that we have the expected number of encrypted bytes at this point
208 VerifyFatal( (uint8 *)pEncryptedDataAndTag + cbEncryptedWithoutTag == pOut );
209
210 // Append the tag
211 if ( EVP_CIPHER_CTX_ctrl( ctx, EVP_CTRL_GCM_GET_TAG, (int)m_cbTag, pOut ) != 1 )
212 {
213 AssertMsg( false, "Bad tag size" );
214 return false;
215 }
216
217 // Give the caller back the size of everything
218 *pcbEncryptedDataAndTag = cbEncryptedTotal;
219
220 // Success.
221 return true;
222 }
223
Decrypt(const void * pEncryptedDataAndTag,size_t cbEncryptedDataAndTag,const void * pIV,void * pPlaintextData,uint32 * pcbPlaintextData,const void * pAdditionalAuthenticationData,size_t cbAuthenticationData)224 bool AES_GCM_DecryptContext::Decrypt(
225 const void *pEncryptedDataAndTag, size_t cbEncryptedDataAndTag,
226 const void *pIV,
227 void *pPlaintextData, uint32 *pcbPlaintextData,
228 const void *pAdditionalAuthenticationData, size_t cbAuthenticationData
229 )
230 {
231
232 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)m_ctx;
233 if ( !ctx )
234 {
235 AssertMsg( false, "Not initialized!" );
236 *pcbPlaintextData = 0;
237 return false;
238 }
239
240 // Make sure buffer and tag sizes aren't totally bogus
241 if ( m_cbTag > cbEncryptedDataAndTag )
242 {
243 AssertMsg( false, "Encrypted size doesn't make sense for tag size" );
244 *pcbPlaintextData = 0;
245 return false;
246 }
247 uint32 cbEncryptedDataWithoutTag = uint32( cbEncryptedDataAndTag - m_cbTag );
248
249 // Make sure their buffer is big enough. Remember that in GCM mode,
250 // there is no padding, so if this fails, we indeed would have overflowed
251 if ( cbEncryptedDataWithoutTag > *pcbPlaintextData )
252 {
253 AssertMsg( false, "Buffer might not be big enough to hold decrypted data" );
254 *pcbPlaintextData = 0;
255 return false;
256 }
257
258 // People really have to check the return value, but in case they
259 // don't, make sure they don't think we decrypted any data
260 *pcbPlaintextData = 0;
261
262 // Set IV
263 VerifyFatal( EVP_DecryptInit_ex( ctx, nullptr, nullptr, nullptr, (const uint8*)pIV ) == 1 );
264
265 int nBytesWritten;
266
267 // AAD, if any
268 if ( cbAuthenticationData > 0 && pAdditionalAuthenticationData )
269 {
270 // I don't think it's actually possible to failed here, but
271 // since the caller really must be checking the return value,
272 // let's not make this fatal
273 if ( EVP_DecryptUpdate( ctx, nullptr, &nBytesWritten, (const uint8*)pAdditionalAuthenticationData, (int)cbAuthenticationData ) != 1 )
274 {
275 AssertMsg( false, "EVP_DecryptUpdate failed?" );
276 return false;
277 }
278 }
279 else
280 {
281 Assert( cbAuthenticationData == 0 );
282 }
283
284 uint8 *pOut = (uint8 *)pPlaintextData;
285 const uint8 *pIn = (const uint8 *)pEncryptedDataAndTag;
286
287 // Now the actual ciphertext to be decrypted
288 if ( EVP_DecryptUpdate( ctx, pOut, &nBytesWritten, pIn, (int)cbEncryptedDataWithoutTag ) != 1 )
289 return false;
290 pOut += nBytesWritten;
291 pIn += cbEncryptedDataWithoutTag;
292
293 // Set expected tag value
294 if( EVP_CIPHER_CTX_ctrl( ctx, EVP_CTRL_GCM_SET_TAG, (int)m_cbTag, const_cast<uint8*>( pIn ) ) != 1)
295 {
296 AssertMsg( false, "Bad tag size" );
297 return false;
298 }
299
300 // Finish up, and check tag
301 if ( EVP_DecryptFinal_ex( ctx, pOut, &nBytesWritten ) <= 0 )
302 return false; // data has been tamped with
303 pOut += nBytesWritten;
304
305 // Make sure we got back the size we expected, and return the size
306 VerifyFatal( pOut == (uint8 *)pPlaintextData + cbEncryptedDataWithoutTag );
307 *pcbPlaintextData = cbEncryptedDataWithoutTag;
308
309 // Success.
310 return true;
311 }
312
313 //-----------------------------------------------------------------------------
SymmetricAuthEncryptWithIV(const void * pPlaintextData,size_t cbPlaintextData,const void * pIV,size_t cbIV,void * pEncryptedDataAndTag,uint32 * pcbEncryptedDataAndTag,const void * pKey,size_t cbKey,const void * pAdditionalAuthenticationData,size_t cbAuthenticationData,size_t cbTag)314 bool CCrypto::SymmetricAuthEncryptWithIV(
315 const void *pPlaintextData, size_t cbPlaintextData,
316 const void *pIV, size_t cbIV,
317 void *pEncryptedDataAndTag, uint32 *pcbEncryptedDataAndTag,
318 const void *pKey, size_t cbKey,
319 const void *pAdditionalAuthenticationData, size_t cbAuthenticationData,
320 size_t cbTag
321 )
322 {
323
324 // Setup a context. If you are going to be encrypting many buffers with the same parameters,
325 // you should create a context and reuse it, to avoid this setup cost
326 AES_GCM_EncryptContext ctx;
327 if ( !ctx.Init( pKey, cbKey, cbIV, cbTag ) )
328 return false;
329
330 // Encrypt it, and cleanup
331 return ctx.Encrypt( pPlaintextData, cbPlaintextData, pIV, pEncryptedDataAndTag, pcbEncryptedDataAndTag, pAdditionalAuthenticationData, cbAuthenticationData );
332 }
333
334 //-----------------------------------------------------------------------------
SymmetricAuthDecryptWithIV(const void * pEncryptedDataAndTag,size_t cbEncryptedDataAndTag,const void * pIV,size_t cbIV,void * pPlaintextData,uint32 * pcbPlaintextData,const void * pKey,size_t cbKey,const void * pAdditionalAuthenticationData,size_t cbAuthenticationData,size_t cbTag)335 bool CCrypto::SymmetricAuthDecryptWithIV(
336 const void *pEncryptedDataAndTag, size_t cbEncryptedDataAndTag,
337 const void *pIV, size_t cbIV,
338 void *pPlaintextData, uint32 *pcbPlaintextData,
339 const void *pKey, size_t cbKey,
340 const void *pAdditionalAuthenticationData, size_t cbAuthenticationData,
341 size_t cbTag
342 )
343 {
344 // Setup a context. If you are going to be decrypting many buffers with the same parameters,
345 // you should create a context and reuse it, to avoid this setup cost
346 AES_GCM_DecryptContext ctx;
347 if ( !ctx.Init( pKey, cbKey, cbIV, cbTag ) )
348 return false;
349
350 // Decrypt it, and cleanup
351 return ctx.Decrypt( pEncryptedDataAndTag, cbEncryptedDataAndTag, pIV, pPlaintextData, pcbPlaintextData, pAdditionalAuthenticationData, cbAuthenticationData );
352 }
353
354 //-----------------------------------------------------------------------------
355 // Purpose: Generate a SHA256 hash
356 // Input: pchInput - Plaintext string of item to hash (null terminated)
357 // pOutDigest - Pointer to receive hashed digest output
358 //-----------------------------------------------------------------------------
GenerateSHA256Digest(const void * pInput,size_t cbInput,SHA256Digest_t * pOutDigest)359 void CCrypto::GenerateSHA256Digest( const void *pInput, size_t cbInput, SHA256Digest_t *pOutDigest )
360 {
361 VPROF_BUDGET( "CCrypto::GenerateSHA256Digest", VPROF_BUDGETGROUP_ENCRYPTION );
362 //Assert( pubInput );
363 Assert( pOutDigest );
364
365 EVPCTXPointer<EVP_MD_CTX *, EVP_MD_CTX_free> ctx(EVP_MD_CTX_create());
366
367 unsigned int digest_len = sizeof(SHA256Digest_t);
368 VerifyFatal(ctx.ctx != NULL);
369 VerifyFatal(EVP_DigestInit_ex(ctx.ctx, EVP_sha256(), NULL) == 1);
370 VerifyFatal(EVP_DigestUpdate(ctx.ctx, pInput, cbInput) == 1);
371 VerifyFatal(EVP_DigestFinal(ctx.ctx, *pOutDigest, &digest_len) == 1);
372 }
373
374 //-----------------------------------------------------------------------------
375 // Purpose: Generates a cryptographiacally random block of data fit for any use.
376 // NOTE: Function terminates process on failure rather than returning false!
377 //-----------------------------------------------------------------------------
GenerateRandomBlock(void * pvDest,int cubDest)378 void CCrypto::GenerateRandomBlock( void *pvDest, int cubDest )
379 {
380 VPROF_BUDGET( "CCrypto::GenerateRandomBlock", VPROF_BUDGETGROUP_ENCRYPTION );
381 AssertFatal( cubDest >= 0 );
382 uint8 *pubDest = (uint8 *)pvDest;
383
384 #if defined(_WIN32)
385
386 // NOTE: assume that this cannot fail. MS has baked this function name into
387 // static CRT runtime libraries for years; changing the export would break
388 // millions of applications. Available from Windows XP onward. -henryg
389 typedef BYTE ( NTAPI *PfnRtlGenRandom_t )( PVOID RandomBuffer, ULONG RandomBufferLength );
390 static PfnRtlGenRandom_t s_pfnRtlGenRandom;
391 if ( !s_pfnRtlGenRandom )
392 {
393 s_pfnRtlGenRandom = (PfnRtlGenRandom_t) (void*) GetProcAddress( LoadLibraryA( "advapi32.dll" ), "SystemFunction036" );
394 }
395
396 bool bRtlGenRandomOK = s_pfnRtlGenRandom && ( s_pfnRtlGenRandom( pubDest, (unsigned long)cubDest ) == TRUE );
397 AssertFatal( bRtlGenRandomOK );
398
399 #elif defined(POSIX)
400
401 // Reading from /dev/urandom is threadsafe, but possibly slow due to a kernel
402 // spinlock or mutex protecting access to the internal PRNG state. In theory,
403 // we could use bytes from /dev/urandom to initialize a user-space PRNG (like
404 // OpenSSL does), but this introduces a security risk: if our process memory
405 // is compromised and an attacker gains read access, the PRNG state could be
406 // dumped and an attacker might be able to predict future or past outputs!
407 // The risk of the kernel's internal PRNG state being exposed is much lower.
408 // (We can revisit this if performance becomes an issue. -henryg 4/26/2016)
409 static int s_dev_urandom_fd = open( "/dev/urandom", O_RDONLY | O_CLOEXEC );
410 AssertFatal( s_dev_urandom_fd >= 0 );
411 size_t remaining = (size_t)cubDest;
412 while ( remaining )
413 {
414 ssize_t urandom_result = read( s_dev_urandom_fd, pubDest + cubDest - remaining, remaining );
415 AssertFatal( urandom_result > 0 || ( urandom_result < 0 && errno == EINTR ) );
416 if ( urandom_result > 0 )
417 {
418 remaining -= urandom_result;
419 }
420 }
421
422 #else
423
424 OneTimeCryptoInitOpenSSL();
425 AssertFatal( RAND_bytes( pubDest, cubDest ) > 0 );
426
427 #endif
428 }
429
430
431 //-----------------------------------------------------------------------------
432 // Purpose: Generate a keyed-hash MAC using SHA-256
433 //-----------------------------------------------------------------------------
GenerateHMAC256(const uint8 * pubData,uint32 cubData,const uint8 * pubKey,uint32 cubKey,SHA256Digest_t * pOutputDigest)434 void CCrypto::GenerateHMAC256( const uint8 *pubData, uint32 cubData, const uint8 *pubKey, uint32 cubKey, SHA256Digest_t *pOutputDigest )
435 {
436 VPROF_BUDGET( "CCrypto::GenerateHMAC256", VPROF_BUDGETGROUP_ENCRYPTION );
437 Assert( pubData );
438 Assert( cubData > 0 );
439 Assert( pubKey );
440 Assert( cubKey > 0 );
441 Assert( pOutputDigest );
442
443 EVPCTXPointer<EVP_MD_CTX *, EVP_MD_CTX_free> mdctx(EVP_MD_CTX_create());
444 EVPCTXPointer<EVP_PKEY *, EVP_PKEY_free> pkey(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, pubKey, cubKey));
445 const EVP_MD *digest = EVP_sha256();
446
447 VerifyFatal(mdctx.ctx != NULL && pkey.ctx != NULL);
448 VerifyFatal(EVP_DigestInit_ex(mdctx.ctx, digest, NULL) == 1);
449 VerifyFatal(EVP_DigestSignInit(mdctx.ctx, NULL, digest, NULL, pkey.ctx) == 1);
450 VerifyFatal(EVP_DigestSignUpdate(mdctx.ctx, pubData, cubData) == 1);
451
452 size_t needed = sizeof(SHA256Digest_t);
453 VerifyFatal(EVP_DigestSignFinal(mdctx.ctx, *pOutputDigest, &needed) == 1);
454 }
455
456 #endif //STEAMNETWORKINGSOCKETS_CRYPTO_VALVEOPENSSL
457