lime
Lime is a C++ library implementing Open Whisper System Signal protocol
lime_crypto_primitives.hpp
Go to the documentation of this file.
1 /*
2  lime_crypto_primitives.hpp
3  @author Johan Pascal
4  @copyright Copyright (C) 2017 Belledonne Communications SARL
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef lime_crypto_primitives_hpp
21 #define lime_crypto_primitives_hpp
22 
23 #include <memory>
24 #include <vector>
25 
26 #include "lime_keys.hpp"
27 #include "lime_defines.hpp"
28 
29 namespace lime {
30 /*************************************************************************************************/
31 /********************** Data Structures **********************************************************/
32 /*************************************************************************************************/
33 
34  void cleanBuffer(uint8_t *buffer, size_t size);
35 
41  template <size_t T>
42  struct sBuffer : public std::array<uint8_t, T> {
44  ~sBuffer() {cleanBuffer(this->data(), T);};
45  };
46 
47  /****************************************************************/
48  /* Key Exchange Data structures */
49  /****************************************************************/
55  template <typename Curve, lime::Xtype dataType>
56  class X : public sBuffer<static_cast<size_t>(Curve::Xsize(dataType))>{
57  public :
59  constexpr static size_t ssize(void) {return Curve::Xsize(dataType);};
61  X(std::vector<uint8_t>::const_iterator buffer) {std::copy_n(buffer, Curve::Xsize(dataType), this->begin());}
62  X() {};
64  void assign(std::vector<uint8_t>::const_iterator buffer) {std::copy_n(buffer, Curve::Xsize(dataType), this->begin());}
65  };
66 
70  template <typename Curve>
71  class Xpair {
72  private:
75  public:
77  X<Curve, lime::Xtype::privateKey> &privateKey(void) {return m_privKey;};
79  X<Curve, lime::Xtype::publicKey> &publicKey(void) {return m_pubKey;};
81  Xpair(X<Curve, lime::Xtype::publicKey> &pub, X<Curve, lime::Xtype::privateKey> &priv):m_pubKey(pub),m_privKey(priv) {};
82  Xpair() :m_pubKey{},m_privKey{}{};
84  bool operator==(Xpair<Curve> b) const {return (m_privKey==b.privateKey() && m_pubKey==b.publicKey());};
85 
86  };
87 
88  /****************************************************************/
89  /* Digital Signature Algorithm data structures */
90  /****************************************************************/
96  template <typename Curve, lime::DSAtype dataType>
97  class DSA : public sBuffer<static_cast<size_t>(Curve::DSAsize(dataType))>{
98  public :
100  constexpr static size_t ssize(void) {return Curve::DSAsize(dataType);};
102  DSA(std::vector<uint8_t>::const_iterator buffer) {std::copy_n(buffer, Curve::DSAsize(dataType), this->begin());}
103  DSA() {};
105  void assign(std::vector<uint8_t>::const_iterator buffer) {std::copy_n(buffer, Curve::DSAsize(dataType), this->begin());}
106  };
107 
111  template <typename Curve>
112  class DSApair {
113  private:
116  public:
123  DSApair() :m_pubKey{},m_privKey{}{};
125  bool operator==(DSApair<Curve> b) const {return (m_privKey==b.privateKey() && m_pubKey==b.publicKey());};
126  };
127 
128 
129 /*************************************************************************************************/
130 /********************** Crypto Algo interface ****************************************************/
131 /*************************************************************************************************/
132 
142 class RNG {
143  public:
149  virtual void randomize(sBuffer<lime::settings::DRrandomSeedSize> &buffer) = 0;
150 
158  virtual uint32_t randomize() = 0;
159 
165  virtual void randomize(uint8_t *buffer, const size_t size) = 0;
166 
167  virtual ~RNG() = default;
168 }; //class RNG
169 
176 template <typename Curve>
177 class keyExchange {
178  public:
179  /* accessors */
181  virtual const X<Curve, lime::Xtype::privateKey> get_secret(void) = 0;
183  virtual const X<Curve, lime::Xtype::publicKey> get_selfPublic(void) = 0;
185  virtual const X<Curve, lime::Xtype::publicKey> get_peerPublic(void) = 0;
187  virtual const X<Curve, lime::Xtype::sharedSecret> get_sharedSecret(void) = 0;
188 
189  /* set keys in context, publics and private keys directly accept Signature formatted keys which are converted to keyExchange format */
191  virtual void set_secret(const X<Curve, lime::Xtype::privateKey> &secret) = 0;
196  virtual void set_secret(const DSA<Curve, lime::DSAtype::privateKey> &secret) = 0;
198  virtual void set_selfPublic(const X<Curve, lime::Xtype::publicKey> &selfPublic) = 0;
203  virtual void set_selfPublic(const DSA<Curve, lime::DSAtype::publicKey> &selfPublic) = 0;
205  virtual void set_peerPublic(const X<Curve, lime::Xtype::publicKey> &peerPublic) = 0;
210  virtual void set_peerPublic(const DSA<Curve, lime::DSAtype::publicKey> &peerPublic) = 0;
211 
217  virtual void createKeyPair(std::shared_ptr<lime::RNG> rng) = 0;
218 
222  virtual void deriveSelfPublic(void) = 0;
223 
227  virtual void computeSharedSecret(void) = 0;
228  virtual ~keyExchange() = default;
229 }; //class keyExchange
230 
236 template <typename Curve>
237 class Signature {
238  public:
239  /* accessors */
241  virtual const DSA<Curve, lime::DSAtype::privateKey> get_secret(void) = 0;
243  virtual const DSA<Curve, lime::DSAtype::publicKey> get_public(void) = 0;
244 
246  virtual void set_secret(const DSA<Curve, lime::DSAtype::privateKey> &secretKey) = 0;
248  virtual void set_public(const DSA<Curve, lime::DSAtype::publicKey> &publicKey) = 0;
249 
255  virtual void createKeyPair(std::shared_ptr<lime::RNG> rng) = 0;
256 
260  virtual void derivePublic(void) = 0;
261 
268  virtual void sign(const std::vector<uint8_t> &message, DSA<Curve, lime::DSAtype::signature> &signature) = 0;
273  virtual void sign(const X<Curve, lime::Xtype::publicKey> &message, DSA<Curve, lime::DSAtype::signature> &signature) = 0;
274 
283  virtual bool verify(const std::vector<uint8_t> &message, const DSA<Curve, lime::DSAtype::signature> &signature) = 0;
288  virtual bool verify(const X<Curve, lime::Xtype::publicKey> &message, const DSA<Curve, lime::DSAtype::signature> &signature) = 0;
289 
290  virtual ~Signature() = default;
291 }; //class EdDSA
292 
306 template <typename hashAlgo>
307 void HMAC(const uint8_t *const key, const size_t keySize, const uint8_t *const input, const size_t inputSize, uint8_t *hash, size_t hashSize);
308 /* declare template specialisations */
309 template <> void HMAC<SHA512>(const uint8_t *const key, const size_t keySize, const uint8_t *const input, const size_t inputSize, uint8_t *hash, size_t hashSize);
310 
339 template <typename hashAlgo, typename infoType>
340 void HMAC_KDF(const std::vector<uint8_t> &salt, const std::vector<uint8_t> &ikm, const infoType &info, uint8_t *okm, size_t okmSize);
345 template <typename hashAlgo, typename infoType>
346 void HMAC_KDF(const uint8_t *const salt, const size_t saltSize, const uint8_t *const ikm, const size_t ikmSize, const infoType &info, uint8_t *output, size_t outputSize);
347 
348 
349 /************************ AEAD interface *************************************/
350 
366 template <typename AEADAlgo>
367 void AEAD_encrypt(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize,
368  const uint8_t *const plain, const size_t plainSize, const uint8_t *const AD, const size_t ADSize,
369  uint8_t *tag, const size_t tagSize, uint8_t *cipher);
370 
388 template <typename AEADAlgo>
389 bool AEAD_decrypt(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize,
390  const uint8_t *const cipher, const size_t cipherSize, const uint8_t *const AD, const size_t ADSize,
391  const uint8_t *const tag, const size_t tagSize, uint8_t *plain);
392 
393 /* declare AEAD template specialisations */
394 template <> void AEAD_encrypt<AES256GCM>(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize,
395  const uint8_t *const plain, const size_t plainSize, const uint8_t *const AD, const size_t ADSize,
396  uint8_t *tag, const size_t tagSize, uint8_t *cipher);
397 
398 template <> bool AEAD_decrypt<AES256GCM>(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize,
399  const uint8_t *const cipher, const size_t cipherSize, const uint8_t *const AD, const size_t ADSize,
400  const uint8_t *const tag, const size_t tagSize, uint8_t *plain);
401 
402 
403 /*************************************************************************************************/
404 /********************** Factory Functions ********************************************************/
405 /*************************************************************************************************/
406 /* Use these to instantiate an object as they will pick the correct undurlying implemenation of virtual classes */
407 std::shared_ptr<RNG> make_RNG();
408 
409 template <typename Curve>
410 std::shared_ptr<keyExchange<Curve>> make_keyExchange();
411 
412 template <typename Curve>
413 std::shared_ptr<Signature<Curve>> make_Signature();
414 
415 /*************************************************************************************************/
416 /********************** Template Instanciation ***************************************************/
417 /*************************************************************************************************/
418 /* this templates are instanciated once in the lime_crypto_primitives.cpp file, explicitly tell anyone including this header that there is no need to re-instanciate them */
419 extern template void HMAC_KDF<SHA512, std::vector<uint8_t>>(const std::vector<uint8_t> &salt, const std::vector<uint8_t> &ikm, const std::vector<uint8_t> &info, uint8_t *output, size_t outputSize);
420 extern template void HMAC_KDF<SHA512, std::string>(const std::vector<uint8_t> &salt, const std::vector<uint8_t> &ikm, const std::string &info, uint8_t *output, size_t outputSize);
421 extern template void HMAC_KDF<SHA512, std::vector<uint8_t>>(const uint8_t *const salt, const size_t saltSize, const uint8_t *const ikm, const size_t ikmSize, const std::vector<uint8_t> &info, uint8_t *output, size_t outputSize);
422 extern template void HMAC_KDF<SHA512, std::string>(const uint8_t *const salt, const size_t saltSize, const uint8_t *const ikm, const size_t ikmSize, const std::string &info, uint8_t *output, size_t outputSize);
423 
424 #ifdef EC25519_ENABLED
425  extern template std::shared_ptr<keyExchange<C255>> make_keyExchange();
426  extern template std::shared_ptr<Signature<C255>> make_Signature();
427  extern template class X<C255, lime::Xtype::publicKey>;
428  extern template class X<C255, lime::Xtype::privateKey>;
429  extern template class X<C255, lime::Xtype::sharedSecret>;
430  extern template class Xpair<C255>;
431  extern template class DSA<C255, lime::DSAtype::publicKey>;
432  extern template class DSA<C255, lime::DSAtype::privateKey>;
433  extern template class DSA<C255, lime::DSAtype::signature>;
434  extern template class DSApair<C255>;
435 #endif // EC25519_ENABLED
436 
437 #ifdef EC448_ENABLED
438  extern template std::shared_ptr<keyExchange<C448>> make_keyExchange();
439  extern template std::shared_ptr<Signature<C448>> make_Signature();
440  extern template class X<C448, lime::Xtype::publicKey>;
441  extern template class X<C448, lime::Xtype::privateKey>;
442  extern template class X<C448, lime::Xtype::sharedSecret>;
443  extern template class Xpair<C448>;
444  extern template class DSA<C448, lime::DSAtype::publicKey>;
445  extern template class DSA<C448, lime::DSAtype::privateKey>;
446  extern template class DSA<C448, lime::DSAtype::signature>;
447  extern template class DSApair<C448>;
448 #endif // EC448_ENABLED
449 
450 } // namespace lime
451 
452 #endif //lime_crypto_primitives_hpp
453 
454 
static constexpr size_t ssize(void)
provide a static size function to be able to call the function not on an object
Definition: lime_crypto_primitives.hpp:59
X()
Definition: lime_crypto_primitives.hpp:62
DSApair(DSA< Curve, lime::DSAtype::publicKey > &pub, DSA< Curve, lime::DSAtype::privateKey > &priv)
copy construct a key pair from public and private keys (no verification on validity of keys is perfor...
Definition: lime_crypto_primitives.hpp:122
X< Curve, lime::Xtype::privateKey > & privateKey(void)
access the private key
Definition: lime_crypto_primitives.hpp:77
DSA(std::vector< uint8_t >::const_iterator buffer)
contruct from a std::vector<uint8_t>
Definition: lime_crypto_primitives.hpp:102
DSA()
Definition: lime_crypto_primitives.hpp:103
Digital Signature interface.
Definition: lime_crypto_primitives.hpp:237
bool AEAD_decrypt(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize, const uint8_t *const cipher, const size_t cipherSize, const uint8_t *const AD, const size_t ADSize, const uint8_t *const tag, const size_t tagSize, uint8_t *plain)
Authenticate and Decrypt using scheme given as template parameter.
Definition: lime_crypto_primitives.cpp:415
std::shared_ptr< RNG > make_RNG()
Definition: lime_crypto_primitives.cpp:76
bool operator==(Xpair< Curve > b) const
== operator assert that public and private keys are the same
Definition: lime_crypto_primitives.hpp:84
Base buffer definition for DSA data structure.
Definition: lime_crypto_primitives.hpp:97
Key pair structure for DSA algorithm.
Definition: lime_crypto_primitives.hpp:112
Key pair structure for key exchange algorithm.
Definition: lime_crypto_primitives.hpp:71
void cleanBuffer(uint8_t *buffer, size_t size)
force a buffer values to zero in a way that shall prevent the compiler from optimizing it out ...
Definition: lime_crypto_primitives.cpp:479
void AEAD_encrypt(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize, const uint8_t *const plain, const size_t plainSize, const uint8_t *const AD, const size_t ADSize, uint8_t *tag, const size_t tagSize, uint8_t *cipher)
Encrypt and tag using scheme given as template parameter.
Definition: lime_crypto_primitives.cpp:407
bool operator==(DSApair< Curve > b) const
== operator assert that public and private keys are the same
Definition: lime_crypto_primitives.hpp:125
void HMAC_KDF(const uint8_t *const salt, const size_t saltSize, const uint8_t *const ikm, const size_t ikmSize, const infoType &info, uint8_t *output, size_t outputSize)
Definition: lime_crypto_primitives.cpp:372
std::shared_ptr< keyExchange< Curve > > make_keyExchange()
Definition: lime_crypto_primitives.cpp:348
X(std::vector< uint8_t >::const_iterator buffer)
construct from a std::vector<uint8_t>
Definition: lime_crypto_primitives.hpp:61
void assign(std::vector< uint8_t >::const_iterator buffer)
copy from a std::vector<uint8_t>
Definition: lime_crypto_primitives.hpp:105
void AEAD_encrypt< AES256GCM >(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize, const uint8_t *const plain, const size_t plainSize, const uint8_t *const AD, const size_t ADSize, uint8_t *tag, const size_t tagSize, uint8_t *cipher)
Definition: lime_crypto_primitives.cpp:424
std::shared_ptr< Signature< Curve > > make_Signature()
Definition: lime_crypto_primitives.cpp:353
DSA< Curve, lime::DSAtype::publicKey > & publicKey(void)
access the public key
Definition: lime_crypto_primitives.hpp:120
static constexpr size_t ssize(void)
provide a static size function to be able to call the function not on an object
Definition: lime_crypto_primitives.hpp:100
void HMAC< SHA512 >(const uint8_t *const key, const size_t keySize, const uint8_t *const input, const size_t inputSize, uint8_t *hash, size_t hashSize)
Definition: lime_crypto_primitives.cpp:366
void HMAC(const uint8_t *const key, const size_t keySize, const uint8_t *const input, const size_t inputSize, uint8_t *hash, size_t hashSize)
templated HMAC
Definition: lime_crypto_primitives.cpp:360
Definition: lime.cpp:30
DSApair()
Definition: lime_crypto_primitives.hpp:123
X< Curve, lime::Xtype::publicKey > & publicKey(void)
access the public key
Definition: lime_crypto_primitives.hpp:79
void assign(std::vector< uint8_t >::const_iterator buffer)
copy from a std::vector<uint8_t>
Definition: lime_crypto_primitives.hpp:64
DSA< Curve, lime::DSAtype::privateKey > & privateKey(void)
access the private key
Definition: lime_crypto_primitives.hpp:118
Xpair()
Definition: lime_crypto_primitives.hpp:82
auto clean fixed size buffer(std::array based)
Definition: lime_crypto_primitives.hpp:42
bool AEAD_decrypt< AES256GCM >(const uint8_t *const key, const size_t keySize, const uint8_t *const IV, const size_t IVSize, const uint8_t *const cipher, const size_t cipherSize, const uint8_t *const AD, const size_t ADSize, const uint8_t *const tag, const size_t tagSize, uint8_t *plain)
Definition: lime_crypto_primitives.cpp:437
Base buffer definition for Key Exchange data structure.
Definition: lime_crypto_primitives.hpp:56
~sBuffer()
zeroise all buffer when done
Definition: lime_crypto_primitives.hpp:44
Xpair(X< Curve, lime::Xtype::publicKey > &pub, X< Curve, lime::Xtype::privateKey > &priv)
copy construct a key pair from public and private keys (no verification on validity of keys is perfor...
Definition: lime_crypto_primitives.hpp:81
Random number generator interface.
Definition: lime_crypto_primitives.hpp:142
Key exchange interface.
Definition: lime_crypto_primitives.hpp:177