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