1 //========= Copyright Valve LLC, All rights reserved. =========================
2 
3 #ifndef CRYPTO_25519_H
4 #define CRYPTO_25519_H
5 
6 #include <tier0/dbg.h>
7 #include "crypto_constants.h"
8 #include "keypair.h"
9 
10 class CEC25519KeyBase : public CCryptoKeyBase_RawBuffer
11 {
12 public:
13 	virtual ~CEC25519KeyBase();
14 	virtual bool IsValid() const override;
15 	virtual uint32 GetRawData( void *pData ) const override;
16 	virtual void Wipe() override;
17 
evp_pkey()18 	void *evp_pkey() const { return m_evp_pkey; }
19 protected:
20 	virtual bool SetRawData( const void *pData, size_t cbData ) override;
CEC25519KeyBase(ECryptoKeyType keyType)21 	inline CEC25519KeyBase( ECryptoKeyType keyType ) : CCryptoKeyBase_RawBuffer( keyType ), m_evp_pkey(nullptr) {}
22 
23 	// Actually EVP_PKEY*, but we don't want to include OpenSSL headers here,
24 	// especially since we might not actually be using OpenSSL for this at all!
25 	void *m_evp_pkey;
26 };
27 
28 //-----------------------------------------------------------------------------
29 // Purpose: Common base for x25519 and ed25519 public keys on the 25519 curve
30 //			The raw data is 32 bytes
31 //-----------------------------------------------------------------------------
32 class CEC25519PublicKeyBase : public CEC25519KeyBase
33 {
34 public:
35 	virtual ~CEC25519PublicKeyBase();
36 protected:
CEC25519PublicKeyBase(ECryptoKeyType eType)37 	CEC25519PublicKeyBase( ECryptoKeyType eType ) : CEC25519KeyBase( eType ) { }
38 };
39 
40 //-----------------------------------------------------------------------------
41 // Purpose: Common base for x25519 and ed25519 private keys on the 25519 curve
42 //			The raw data is 32 bytes.
43 //          NOTE: An old version also stored the public key in the raw data.
44 //                We don't do that anymore.)  If you want that, get the public
45 //                key data specifically
46 //-----------------------------------------------------------------------------
47 class CEC25519PrivateKeyBase : public CEC25519KeyBase
48 {
49 public:
50 	virtual ~CEC25519PrivateKeyBase();
51 	virtual void Wipe() override;
52 	bool GetPublicKey( CEC25519PublicKeyBase *pPublicKey ) const;
53 	bool MatchesPublicKey( const CEC25519PublicKeyBase &pPublicKey ) const;
54 
GetPublicKeyRawData()55 	const uint8 *GetPublicKeyRawData() const { return m_publicKey; }
56 
57 protected:
CEC25519PrivateKeyBase(ECryptoKeyType eType)58 	CEC25519PrivateKeyBase( ECryptoKeyType eType ) : CEC25519KeyBase( eType ) { }
59 
60 	// We keep a copy of the public key cached.
61 	// It is not considered part of the raw key data,
62 	// as was previously the case.)
63 	uint8 m_publicKey[32];
64 
65 	bool CachePublicKey();
66 	virtual bool SetRawData( const void *pData, size_t cbData ) override;
67 };
68 
69 
70 //-----------------------------------------------------------------------------
71 // Purpose: Encapsulates an elliptic-curve signature private key (x25519)
72 //-----------------------------------------------------------------------------
73 class CECKeyExchangePrivateKey : public CEC25519PrivateKeyBase
74 {
75 public:
CECKeyExchangePrivateKey()76 	CECKeyExchangePrivateKey() : CEC25519PrivateKeyBase( k_ECryptoKeyTypeKeyExchangePrivate ) { }
77 	virtual ~CECKeyExchangePrivateKey();
78 };
79 
80 
81 //-----------------------------------------------------------------------------
82 // Purpose: Encapsulates an elliptic-curve key-exchange public key (curve25519)
83 //			Internally, this is stored as a 32-byte binary data blob
84 //-----------------------------------------------------------------------------
85 class CECKeyExchangePublicKey : public CEC25519PublicKeyBase
86 {
87 public:
CECKeyExchangePublicKey()88 	CECKeyExchangePublicKey() : CEC25519PublicKeyBase( k_ECryptoKeyTypeKeyExchangePublic ) { }
89 
90 	// Allow copying of public keys without a bunch of paranoia.
CECKeyExchangePublicKey(const CECKeyExchangePublicKey & x)91 	CECKeyExchangePublicKey( const CECKeyExchangePublicKey &x ) : CEC25519PublicKeyBase( k_ECryptoKeyTypeKeyExchangePublic ) { CopyFrom( x ); }
92 	CECKeyExchangePublicKey & operator=(const CECKeyExchangePublicKey &x) { if ( this != &x ) { CopyFrom( x ); } return *this; }
93 
94 	virtual ~CECKeyExchangePublicKey();
95 };
96 
97 
98 //-----------------------------------------------------------------------------
99 // Purpose: Encapsulates an elliptic-curve signature private key (ed25519)
100 //			Internally, this is stored as a 64-byte (public, private) pair
101 //-----------------------------------------------------------------------------
102 class CECSigningPrivateKey : public CEC25519PrivateKeyBase
103 {
104 public:
CECSigningPrivateKey()105 	CECSigningPrivateKey() : CEC25519PrivateKeyBase( k_ECryptoKeyTypeSigningPrivate ) { }
106 
107 	// Load from PEM
108 	virtual bool LoadFromAndWipeBuffer( void *pBuffer, size_t cBytes ) override;
109 
110 	// Purpose: Get key in PEM text format
111 	// Input:	pchPEMData -		Pointer to string buffer to store output in (or NULL to just calculate required size)
112 	//			cubPEMData -		Size of pchPEMData buffer
113 	//			pcubPEMData -		Pointer to number of bytes written to pchPEMData (including terminating nul), or
114 	//								required size of pchPEMData if it is NULL or not big enough.
115 	bool GetAsPEM( char *pchPEMData, uint32 cubPEMData, uint32 *pcubPEMData ) const;
116 
117 	// Parses OpenSSH PEM block.
118 	// WARNING: DOES NOT WIPE INPUT.
119 	bool ParsePEM( const char *pBuffer, size_t cBytes );
120 
121 	// Generate an ed25519 public-key signature
122 	void GenerateSignature( const void *pData, size_t cbData, CryptoSignature_t *pSignatureOut ) const;
123 };
124 
125 //-----------------------------------------------------------------------------
126 // Purpose: Encapsulates an elliptic-curve signature public key (x25519)
127 //			Internally, this is stored as a 32-byte binary data blob
128 //-----------------------------------------------------------------------------
129 class CECSigningPublicKey : public CEC25519PublicKeyBase
130 {
131 public:
CECSigningPublicKey()132 	CECSigningPublicKey() : CEC25519PublicKeyBase( k_ECryptoKeyTypeSigningPublic ) { }
133 
134 	// Allow copying of public keys without a bunch of paranoia.
CECSigningPublicKey(const CECSigningPublicKey & x)135 	CECSigningPublicKey( const CECSigningPublicKey &x ) : CEC25519PublicKeyBase( k_ECryptoKeyTypeSigningPublic ) { CopyFrom( x ); }
136 	CECSigningPublicKey& operator=(const CECSigningPublicKey &x) { if ( this != &x ) { CopyFrom( x ); } return *this; }
137 
138 	virtual bool LoadFromAndWipeBuffer( void *pBuffer, size_t cBytes ) override;
139 
140 	bool GetAsOpenSSHAuthorizedKeys( char *pchData, uint32 cubData, uint32 *pcubData, const char *pszComment = "" ) const;
141 	bool SetFromOpenSSHAuthorizedKeys( const char *pchData, size_t cbData );
142 
143 	bool VerifySignature( const void *pData, size_t cbData, const CryptoSignature_t &signature ) const;
144 };
145 
146 #ifdef VALVE_CRYPTO_ENABLE_25519
147 
148 namespace CCrypto
149 {
150 
151 	//
152 	// Secure key exchange (curve25519 elliptic-curve Diffie-Hellman key exchange)
153 	//
154 
155 	// Generate a X25519 key pair for Diffie-Hellman secure key exchange.
156 	// pPublicKey can be null.  (Since the private key also has a copy of the public key.)
157 	void GenerateKeyExchangeKeyPair( CECKeyExchangePublicKey *pPublicKey, CECKeyExchangePrivateKey *pPrivateKey );
158 
159 	// Do Diffie-Hellman secure key exchange.
160 	// NOTE: this actually returns the SHA256 of the raw DH result.  I don't know why.
161 	bool PerformKeyExchange( const CECKeyExchangePrivateKey &localPrivateKey, const CECKeyExchangePublicKey &remotePublicKey, SHA256Digest_t *pSharedSecretOut );
162 
163 	//
164 	// Signing and verification (ed25519 elliptic-curve signature scheme)
165 	//
166 
167 	// Generate an ed25519 key pair for public-key signature generation
168 	void GenerateSigningKeyPair( CECSigningPublicKey *pPublicKey, CECSigningPrivateKey *pPrivateKey );
169 
170 	// Legacy compatibility - use the key methods
GenerateSignature(const void * pData,size_t cbData,const CECSigningPrivateKey & privateKey,CryptoSignature_t * pSignatureOut)171 	inline void GenerateSignature( const void *pData, size_t cbData, const CECSigningPrivateKey &privateKey, CryptoSignature_t *pSignatureOut ) { privateKey.GenerateSignature( pData, cbData, pSignatureOut ); }
VerifySignature(const void * pData,size_t cbData,const CECSigningPublicKey & publicKey,const CryptoSignature_t & signature)172 	inline bool VerifySignature( const void *pData, size_t cbData, const CECSigningPublicKey &publicKey, const CryptoSignature_t &signature ) { return publicKey.VerifySignature( pData, cbData, signature ); }
173 };
174 
175 #endif // #ifdef VALVE_CRYPTO_ENABLE_25519
176 
177 #endif // CRYPTO_H
178