"Fossies" - the Fresh Open Source Software Archive

Member "src/Volume/Cipher.cpp" (10 Oct 2018, 11411 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Cipher.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.21_Source_vs_1.22_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "Platform/Platform.h"
   14 #include "Cipher.h"
   15 #include "Crypto/Aes.h"
   16 #include "Crypto/SerpentFast.h"
   17 #include "Crypto/Twofish.h"
   18 #include "Crypto/Camellia.h"
   19 #include "Crypto/GostCipher.h"
   20 #include "Crypto/kuznyechik.h"
   21 
   22 #ifdef TC_AES_HW_CPU
   23 #   include "Crypto/Aes_hw_cpu.h"
   24 #endif
   25 #include "Crypto/cpu.h"
   26 
   27 extern "C" int IsAesHwCpuSupported ()
   28 {
   29 #ifdef TC_AES_HW_CPU
   30     static bool state = false;
   31     static bool stateValid = false;
   32 
   33     if (!stateValid)
   34     {
   35         state = g_hasAESNI ? true : false;
   36         stateValid = true;
   37     }
   38     return state && VeraCrypt::Cipher::IsHwSupportEnabled();
   39 #else
   40     return false;
   41 #endif
   42 }
   43 
   44 namespace VeraCrypt
   45 {
   46     Cipher::Cipher () : Initialized (false)
   47     {
   48     }
   49 
   50     Cipher::~Cipher ()
   51     {
   52     }
   53 
   54     void Cipher::DecryptBlock (byte *data) const
   55     {
   56         if (!Initialized)
   57             throw NotInitialized (SRC_POS);
   58 
   59         Decrypt (data);
   60     }
   61 
   62     void Cipher::DecryptBlocks (byte *data, size_t blockCount) const
   63     {
   64         if (!Initialized)
   65             throw NotInitialized (SRC_POS);
   66 
   67         while (blockCount-- > 0)
   68         {
   69             Decrypt (data);
   70             data += GetBlockSize();
   71         }
   72     }
   73 
   74     void Cipher::EncryptBlock (byte *data) const
   75     {
   76         if (!Initialized)
   77             throw NotInitialized (SRC_POS);
   78 
   79         Encrypt (data);
   80     }
   81 
   82     void Cipher::EncryptBlocks (byte *data, size_t blockCount) const
   83     {
   84         if (!Initialized)
   85             throw NotInitialized (SRC_POS);
   86 
   87         while (blockCount-- > 0)
   88         {
   89             Encrypt (data);
   90             data += GetBlockSize();
   91         }
   92     }
   93 
   94     CipherList Cipher::GetAvailableCiphers ()
   95     {
   96         CipherList l;
   97 
   98         l.push_back (shared_ptr <Cipher> (new CipherAES ()));
   99         l.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
  100         l.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
  101         l.push_back (shared_ptr <Cipher> (new CipherCamellia ()));
  102         l.push_back (shared_ptr <Cipher> (new CipherGost89 ()));
  103         l.push_back (shared_ptr <Cipher> (new CipherKuznyechik ()));
  104 
  105         return l;
  106     }
  107 
  108     void Cipher::SetKey (const ConstBufferPtr &key)
  109     {
  110         if (key.Size() != GetKeySize ())
  111             throw ParameterIncorrect (SRC_POS);
  112 
  113         if (!Initialized)
  114             ScheduledKey.Allocate (GetScheduledKeySize ());
  115 
  116         SetCipherKey (key);
  117         Key.CopyFrom (key);
  118         Initialized = true;
  119     }
  120 
  121 #define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
  122 #undef TC_EXCEPTION_NODECL
  123 #define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
  124 
  125     TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CipherException);
  126 
  127 
  128     // AES
  129     void CipherAES::Decrypt (byte *data) const
  130     {
  131 #ifdef TC_AES_HW_CPU
  132         if (IsHwSupportAvailable())
  133             aes_hw_cpu_decrypt (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx), data);
  134         else
  135 #endif
  136             aes_decrypt (data, data, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx)));
  137     }
  138 
  139     void CipherAES::DecryptBlocks (byte *data, size_t blockCount) const
  140     {
  141         if (!Initialized)
  142             throw NotInitialized (SRC_POS);
  143 
  144 #ifdef TC_AES_HW_CPU
  145         if ((blockCount & (32 - 1)) == 0
  146             && IsHwSupportAvailable())
  147         {
  148             while (blockCount > 0)
  149             {
  150                 aes_hw_cpu_decrypt_32_blocks (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx), data);
  151 
  152                 data += 32 * GetBlockSize();
  153                 blockCount -= 32;
  154             }
  155         }
  156         else
  157 #endif
  158             Cipher::DecryptBlocks (data, blockCount);
  159     }
  160 
  161     void CipherAES::Encrypt (byte *data) const
  162     {
  163 #ifdef TC_AES_HW_CPU
  164         if (IsHwSupportAvailable())
  165             aes_hw_cpu_encrypt (ScheduledKey.Ptr(), data);
  166         else
  167 #endif
  168             aes_encrypt (data, data, (aes_encrypt_ctx *) ScheduledKey.Ptr());
  169     }
  170 
  171     void CipherAES::EncryptBlocks (byte *data, size_t blockCount) const
  172     {
  173         if (!Initialized)
  174             throw NotInitialized (SRC_POS);
  175 
  176 #ifdef TC_AES_HW_CPU
  177         if ((blockCount & (32 - 1)) == 0
  178             && IsHwSupportAvailable())
  179         {
  180             while (blockCount > 0)
  181             {
  182                 aes_hw_cpu_encrypt_32_blocks (ScheduledKey.Ptr(), data);
  183 
  184                 data += 32 * GetBlockSize();
  185                 blockCount -= 32;
  186             }
  187         }
  188         else
  189 #endif
  190             Cipher::EncryptBlocks (data, blockCount);
  191     }
  192 
  193     size_t CipherAES::GetScheduledKeySize () const
  194     {
  195         return sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx);
  196     }
  197 
  198     bool CipherAES::IsHwSupportAvailable () const
  199     {
  200 #ifdef TC_AES_HW_CPU
  201         static bool state = false;
  202         static bool stateValid = false;
  203 
  204         if (!stateValid)
  205         {
  206             state = g_hasAESNI ? true : false;
  207             stateValid = true;
  208         }
  209         return state && HwSupportEnabled;
  210 #else
  211         return false;
  212 #endif
  213     }
  214 
  215     void CipherAES::SetCipherKey (const byte *key)
  216     {
  217         if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ScheduledKey.Ptr()) != EXIT_SUCCESS)
  218             throw CipherInitError (SRC_POS);
  219 
  220         if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ScheduledKey.Ptr() + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS)
  221             throw CipherInitError (SRC_POS);
  222     }
  223 
  224     // Serpent
  225     void CipherSerpent::Decrypt (byte *data) const
  226     {
  227         serpent_decrypt (data, data, ScheduledKey);
  228     }
  229 
  230     void CipherSerpent::Encrypt (byte *data) const
  231     {
  232         serpent_encrypt (data, data, ScheduledKey);
  233     }
  234 
  235     size_t CipherSerpent::GetScheduledKeySize () const
  236     {
  237         return 140*4;
  238     }
  239 
  240     void CipherSerpent::SetCipherKey (const byte *key)
  241     {
  242         serpent_set_key (key, ScheduledKey);
  243     }
  244     
  245     void CipherSerpent::EncryptBlocks (byte *data, size_t blockCount) const
  246     {
  247         if (!Initialized)
  248             throw NotInitialized (SRC_POS);
  249 
  250 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  251         if ((blockCount >= 4)
  252             && IsHwSupportAvailable())
  253         {
  254             serpent_encrypt_blocks (data, data, blockCount, ScheduledKey.Ptr());
  255         }
  256         else
  257 #endif
  258             Cipher::EncryptBlocks (data, blockCount);
  259     }
  260     
  261     void CipherSerpent::DecryptBlocks (byte *data, size_t blockCount) const
  262     {
  263         if (!Initialized)
  264             throw NotInitialized (SRC_POS);
  265 
  266 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  267         if ((blockCount >= 4)
  268             && IsHwSupportAvailable())
  269         {
  270             serpent_decrypt_blocks (data, data, blockCount, ScheduledKey.Ptr());
  271         }
  272         else
  273 #endif
  274             Cipher::DecryptBlocks (data, blockCount);
  275     }
  276     
  277     bool CipherSerpent::IsHwSupportAvailable () const
  278     {
  279 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  280         static bool state = false;
  281         static bool stateValid = false;
  282 
  283         if (!stateValid)
  284         {
  285             state = HasSSE2() ? true : false;
  286             stateValid = true;
  287         }
  288         return state;
  289 #else
  290         return false;
  291 #endif
  292     }
  293 
  294 
  295     // Twofish
  296     void CipherTwofish::Decrypt (byte *data) const
  297     {
  298         twofish_decrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data);
  299     }
  300 
  301     void CipherTwofish::Encrypt (byte *data) const
  302     {
  303         twofish_encrypt ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *)data, (unsigned int *)data);
  304     }
  305 
  306     size_t CipherTwofish::GetScheduledKeySize () const
  307     {
  308         return TWOFISH_KS;
  309     }
  310 
  311     void CipherTwofish::SetCipherKey (const byte *key)
  312     {
  313         twofish_set_key ((TwofishInstance *) ScheduledKey.Ptr(), (unsigned int *) key);
  314     }
  315     
  316     void CipherTwofish::EncryptBlocks (byte *data, size_t blockCount) const
  317     {
  318         if (!Initialized)
  319             throw NotInitialized (SRC_POS);
  320 
  321 #if CRYPTOPP_BOOL_X64
  322         twofish_encrypt_blocks ( (TwofishInstance *) ScheduledKey.Ptr(), data, data, blockCount);
  323 #else
  324         Cipher::EncryptBlocks (data, blockCount);
  325 #endif
  326     }
  327     
  328     void CipherTwofish::DecryptBlocks (byte *data, size_t blockCount) const
  329     {
  330         if (!Initialized)
  331             throw NotInitialized (SRC_POS);
  332 
  333 #if CRYPTOPP_BOOL_X64
  334         twofish_decrypt_blocks ( (TwofishInstance *) ScheduledKey.Ptr(), data, data, blockCount);
  335 #else
  336         Cipher::DecryptBlocks (data, blockCount);
  337 #endif
  338     }
  339     
  340     bool CipherTwofish::IsHwSupportAvailable () const
  341     {
  342 #if CRYPTOPP_BOOL_X64
  343         return true;
  344 #else
  345         return false;
  346 #endif
  347     }
  348     
  349     // Camellia
  350     void CipherCamellia::Decrypt (byte *data) const
  351     {
  352         camellia_decrypt (data, data, ScheduledKey.Ptr());
  353     }
  354 
  355     void CipherCamellia::Encrypt (byte *data) const
  356     {
  357         camellia_encrypt (data, data, ScheduledKey.Ptr());
  358     }
  359 
  360     size_t CipherCamellia::GetScheduledKeySize () const
  361     {
  362         return CAMELLIA_KS;
  363     }
  364 
  365     void CipherCamellia::SetCipherKey (const byte *key)
  366     {
  367         camellia_set_key (key, ScheduledKey.Ptr());
  368     }
  369     
  370     void CipherCamellia::EncryptBlocks (byte *data, size_t blockCount) const
  371     {
  372         if (!Initialized)
  373             throw NotInitialized (SRC_POS);
  374 
  375 #if CRYPTOPP_BOOL_X64
  376         camellia_encrypt_blocks ( ScheduledKey.Ptr(), data, data, blockCount);
  377 #else
  378         Cipher::EncryptBlocks (data, blockCount);
  379 #endif
  380     }
  381     
  382     void CipherCamellia::DecryptBlocks (byte *data, size_t blockCount) const
  383     {
  384         if (!Initialized)
  385             throw NotInitialized (SRC_POS);
  386 
  387 #if CRYPTOPP_BOOL_X64
  388         camellia_decrypt_blocks ( ScheduledKey.Ptr(), data, data, blockCount);
  389 #else
  390         Cipher::DecryptBlocks (data, blockCount);
  391 #endif
  392     }
  393     
  394     bool CipherCamellia::IsHwSupportAvailable () const
  395     {
  396 #if CRYPTOPP_BOOL_X64
  397         return true;
  398 #else
  399         return false;
  400 #endif
  401     }
  402 
  403     // GOST89
  404     void CipherGost89::Decrypt (byte *data) const
  405     {
  406         gost_decrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
  407     }
  408 
  409     void CipherGost89::Encrypt (byte *data) const
  410     {
  411         gost_encrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
  412     }
  413 
  414     size_t CipherGost89::GetScheduledKeySize () const
  415     {
  416         return GOST_KS;
  417     }
  418 
  419     void CipherGost89::SetCipherKey (const byte *key)
  420     {
  421         gost_set_key (key, (gost_kds *) ScheduledKey.Ptr(), 1);
  422     }
  423     
  424     // GOST89 with static SBOX
  425     void CipherGost89StaticSBOX::Decrypt (byte *data) const
  426     {
  427         gost_decrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
  428     }
  429 
  430     void CipherGost89StaticSBOX::Encrypt (byte *data) const
  431     {
  432         gost_encrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
  433     }
  434 
  435     size_t CipherGost89StaticSBOX::GetScheduledKeySize () const
  436     {
  437         return GOST_KS;
  438     }
  439 
  440     void CipherGost89StaticSBOX::SetCipherKey (const byte *key)
  441     {
  442         gost_set_key (key, (gost_kds *) ScheduledKey.Ptr(), 0);
  443     }
  444 
  445     // Kuznyechik
  446     void CipherKuznyechik::Decrypt (byte *data) const
  447     {
  448         kuznyechik_decrypt_block (data, data, (kuznyechik_kds *) ScheduledKey.Ptr());
  449     }
  450 
  451     void CipherKuznyechik::Encrypt (byte *data) const
  452     {
  453         kuznyechik_encrypt_block (data, data, (kuznyechik_kds *) ScheduledKey.Ptr());
  454     }
  455 
  456     size_t CipherKuznyechik::GetScheduledKeySize () const
  457     {
  458         return KUZNYECHIK_KS;
  459     }
  460 
  461     void CipherKuznyechik::SetCipherKey (const byte *key)
  462     {
  463         kuznyechik_set_key (key, (kuznyechik_kds *) ScheduledKey.Ptr());
  464     }
  465     void CipherKuznyechik::EncryptBlocks (byte *data, size_t blockCount) const
  466     {
  467         if (!Initialized)
  468             throw NotInitialized (SRC_POS);
  469 
  470 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  471         if ((blockCount >= 4)
  472             && IsHwSupportAvailable())
  473         {
  474             kuznyechik_encrypt_blocks (data, data, blockCount, (kuznyechik_kds *) ScheduledKey.Ptr());
  475         }
  476         else
  477 #endif
  478             Cipher::EncryptBlocks (data, blockCount);
  479     }
  480     
  481     void CipherKuznyechik::DecryptBlocks (byte *data, size_t blockCount) const
  482     {
  483         if (!Initialized)
  484             throw NotInitialized (SRC_POS);
  485 
  486 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  487         if ((blockCount >= 4)
  488             && IsHwSupportAvailable())
  489         {
  490             kuznyechik_decrypt_blocks (data, data, blockCount, (kuznyechik_kds *) ScheduledKey.Ptr());
  491         }
  492         else
  493 #endif
  494             Cipher::DecryptBlocks (data, blockCount);
  495     }
  496     
  497     bool CipherKuznyechik::IsHwSupportAvailable () const
  498     {
  499 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  500         static bool state = false;
  501         static bool stateValid = false;
  502 
  503         if (!stateValid)
  504         {
  505             state = HasSSE2() ? true : false;
  506             stateValid = true;
  507         }
  508         return state;
  509 #else
  510         return false;
  511 #endif
  512     }
  513     bool Cipher::HwSupportEnabled = true;
  514 }