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