"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Pkcs5.c" (10 Oct 2018, 33324 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 "Pkcs5.c" 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  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is 
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is 
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses' 
    8  Modifications and additions to the original source code (contained in this file) 
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include "Tcdefs.h"
   15 #if !defined(_UEFI)
   16 #include <memory.h>
   17 #include <stdlib.h>
   18 #endif
   19 #include "Rmd160.h"
   20 #ifndef TC_WINDOWS_BOOT
   21 #include "Sha2.h"
   22 #include "Whirlpool.h"
   23 #include "cpu.h"
   24 #include "misc.h"
   25 #else
   26 #pragma optimize ("t", on)
   27 #include <string.h>
   28 #if defined( _MSC_VER )
   29 #  ifndef DEBUG
   30 #    pragma intrinsic( memcpy )
   31 #    pragma intrinsic( memset )
   32 #  endif
   33 #endif
   34 #include "Sha2Small.h"
   35 #endif
   36 #include "Pkcs5.h"
   37 #include "Crypto.h"
   38 
   39 #if !defined(TC_WINDOWS_BOOT) || defined(TC_WINDOWS_BOOT_SHA2)
   40 
   41 typedef struct hmac_sha256_ctx_struct
   42 {
   43     sha256_ctx ctx;
   44     sha256_ctx inner_digest_ctx; /*pre-computed inner digest context */
   45     sha256_ctx outer_digest_ctx; /*pre-computed outer digest context */
   46     char k[PKCS5_SALT_SIZE + 4]; /* enough to hold (salt_len + 4) and also the SHA256 hash */
   47     char u[SHA256_DIGESTSIZE];
   48 } hmac_sha256_ctx;
   49 
   50 void hmac_sha256_internal
   51 (
   52       char *d,      /* input data. d pointer is guaranteed to be at least 32-bytes long */
   53       int ld,       /* length of input data in bytes */
   54       hmac_sha256_ctx* hmac /* HMAC-SHA256 context which holds temporary variables */
   55 )
   56 {
   57     sha256_ctx* ctx = &(hmac->ctx);
   58 
   59     /**** Restore Precomputed Inner Digest Context ****/
   60 
   61     memcpy (ctx, &(hmac->inner_digest_ctx), sizeof (sha256_ctx));
   62 
   63     sha256_hash ((unsigned char *) d, ld, ctx);
   64 
   65     sha256_end ((unsigned char *) d, ctx); /* d = inner digest */
   66 
   67     /**** Restore Precomputed Outer Digest Context ****/
   68 
   69     memcpy (ctx, &(hmac->outer_digest_ctx), sizeof (sha256_ctx));
   70 
   71     sha256_hash ((unsigned char *) d, SHA256_DIGESTSIZE, ctx);
   72 
   73     sha256_end ((unsigned char *) d, ctx); /* d = outer digest */
   74 }
   75 
   76 #ifndef TC_WINDOWS_BOOT
   77 void hmac_sha256
   78 (
   79     char *k,    /* secret key */
   80     int lk,    /* length of the key in bytes */
   81     char *d,    /* data */
   82     int ld    /* length of data in bytes */
   83 )
   84 {
   85     hmac_sha256_ctx hmac;
   86     sha256_ctx* ctx;
   87     char* buf = hmac.k;
   88     int b;
   89     char key[SHA256_DIGESTSIZE];
   90 #if defined (DEVICE_DRIVER)
   91     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
   92 #ifdef _WIN64
   93     XSTATE_SAVE SaveState;
   94     if (g_isIntel && HasSAVX())
   95         saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
   96 #else
   97     KFLOATING_SAVE floatingPointState;  
   98     if (HasSSE2())
   99         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  100 #endif
  101 #endif
  102     /* If the key is longer than the hash algorithm block size,
  103        let key = sha256(key), as per HMAC specifications. */
  104     if (lk > SHA256_BLOCKSIZE)
  105     {
  106         sha256_ctx tctx;
  107 
  108         sha256_begin (&tctx);
  109         sha256_hash ((unsigned char *) k, lk, &tctx);
  110         sha256_end ((unsigned char *) key, &tctx);
  111 
  112         k = key;
  113         lk = SHA256_DIGESTSIZE;
  114 
  115         burn (&tctx, sizeof(tctx));     // Prevent leaks
  116     }
  117 
  118     /**** Precompute HMAC Inner Digest ****/
  119 
  120     ctx = &(hmac.inner_digest_ctx);
  121     sha256_begin (ctx);
  122 
  123     /* Pad the key for inner digest */
  124     for (b = 0; b < lk; ++b)
  125         buf[b] = (char) (k[b] ^ 0x36);
  126     memset (&buf[lk], 0x36, SHA256_BLOCKSIZE - lk);
  127 
  128     sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
  129 
  130     /**** Precompute HMAC Outer Digest ****/
  131 
  132     ctx = &(hmac.outer_digest_ctx);
  133     sha256_begin (ctx);
  134 
  135     for (b = 0; b < lk; ++b)
  136         buf[b] = (char) (k[b] ^ 0x5C);
  137     memset (&buf[lk], 0x5C, SHA256_BLOCKSIZE - lk);
  138 
  139     sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
  140 
  141     hmac_sha256_internal(d, ld, &hmac);
  142 
  143 #if defined (DEVICE_DRIVER)
  144     if (NT_SUCCESS (saveStatus))
  145 #ifdef _WIN64
  146         KeRestoreExtendedProcessorState(&SaveState);
  147 #else
  148         KeRestoreFloatingPointState (&floatingPointState);
  149 #endif
  150 #endif
  151 
  152     /* Prevent leaks */
  153     burn(&hmac, sizeof(hmac));
  154     burn(key, sizeof(key));
  155 }
  156 #endif
  157 
  158 static void derive_u_sha256 (char *salt, int salt_len, uint32 iterations, int b, hmac_sha256_ctx* hmac)
  159 {
  160     char* k = hmac->k;
  161     char* u = hmac->u;
  162     uint32 c;
  163     int i;  
  164 
  165 #ifdef TC_WINDOWS_BOOT
  166     /* In bootloader mode, least significant bit of iterations is a boolean (TRUE for boot derivation mode, FALSE otherwise)
  167      * and the most significant 16 bits hold the pim value
  168      * This enables us to save code space needed for implementing other features.
  169      */
  170     c = iterations >> 16;
  171     i = ((int) iterations) & 0x01;
  172     if (i)
  173         c = (c == 0)? 200000 : c << 11;
  174     else
  175         c = (c == 0)? 500000 : 15000 + c * 1000;
  176 #else
  177     c = iterations;
  178 #endif
  179 
  180     /* iteration 1 */
  181     memcpy (k, salt, salt_len); /* salt */
  182     
  183     /* big-endian block number */
  184 #ifdef TC_WINDOWS_BOOT
  185     /* specific case of 16-bit bootloader: b is a 16-bit integer that is always < 256 */
  186     memset (&k[salt_len], 0, 3);
  187     k[salt_len + 3] = (char) b;
  188 #else
  189     b = bswap_32 (b);
  190     memcpy (&k[salt_len], &b, 4);
  191 #endif  
  192 
  193     hmac_sha256_internal (k, salt_len + 4, hmac);
  194     memcpy (u, k, SHA256_DIGESTSIZE);
  195 
  196     /* remaining iterations */
  197     while (c > 1)
  198     {
  199         hmac_sha256_internal (k, SHA256_DIGESTSIZE, hmac);
  200         for (i = 0; i < SHA256_DIGESTSIZE; i++)
  201         {
  202             u[i] ^= k[i];
  203         }
  204         c--;
  205     }
  206 }
  207 
  208 
  209 void derive_key_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
  210 {   
  211     hmac_sha256_ctx hmac;
  212     sha256_ctx* ctx;
  213     char* buf = hmac.k;
  214     int b, l, r;
  215 #ifndef TC_WINDOWS_BOOT
  216     char key[SHA256_DIGESTSIZE];
  217 #if defined (DEVICE_DRIVER)
  218     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  219 #ifdef _WIN64
  220     XSTATE_SAVE SaveState;
  221     if (g_isIntel && HasSAVX())
  222         saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
  223 #else
  224     KFLOATING_SAVE floatingPointState;  
  225     if (HasSSE2())
  226         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  227 #endif
  228 #endif
  229     /* If the password is longer than the hash algorithm block size,
  230        let pwd = sha256(pwd), as per HMAC specifications. */
  231     if (pwd_len > SHA256_BLOCKSIZE)
  232     {
  233         sha256_ctx tctx;
  234 
  235         sha256_begin (&tctx);
  236         sha256_hash ((unsigned char *) pwd, pwd_len, &tctx);
  237         sha256_end ((unsigned char *) key, &tctx);
  238 
  239         pwd = key;
  240         pwd_len = SHA256_DIGESTSIZE;
  241 
  242         burn (&tctx, sizeof(tctx));     // Prevent leaks
  243     }
  244 #endif
  245 
  246     if (dklen % SHA256_DIGESTSIZE)
  247     {
  248         l = 1 + dklen / SHA256_DIGESTSIZE;
  249     }
  250     else
  251     {
  252         l = dklen / SHA256_DIGESTSIZE;
  253     }
  254 
  255     r = dklen - (l - 1) * SHA256_DIGESTSIZE;
  256 
  257     /**** Precompute HMAC Inner Digest ****/
  258 
  259     ctx = &(hmac.inner_digest_ctx);
  260     sha256_begin (ctx);
  261 
  262     /* Pad the key for inner digest */
  263     for (b = 0; b < pwd_len; ++b)
  264         buf[b] = (char) (pwd[b] ^ 0x36);
  265     memset (&buf[pwd_len], 0x36, SHA256_BLOCKSIZE - pwd_len);
  266 
  267     sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
  268 
  269     /**** Precompute HMAC Outer Digest ****/
  270 
  271     ctx = &(hmac.outer_digest_ctx);
  272     sha256_begin (ctx);
  273 
  274     for (b = 0; b < pwd_len; ++b)
  275         buf[b] = (char) (pwd[b] ^ 0x5C);
  276     memset (&buf[pwd_len], 0x5C, SHA256_BLOCKSIZE - pwd_len);
  277 
  278     sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
  279 
  280     /* first l - 1 blocks */
  281     for (b = 1; b < l; b++)
  282     {
  283         derive_u_sha256 (salt, salt_len, iterations, b, &hmac);
  284         memcpy (dk, hmac.u, SHA256_DIGESTSIZE);
  285         dk += SHA256_DIGESTSIZE;
  286     }
  287 
  288     /* last block */
  289     derive_u_sha256 (salt, salt_len, iterations, b, &hmac);
  290     memcpy (dk, hmac.u, r);
  291 
  292 #if defined (DEVICE_DRIVER)
  293     if (NT_SUCCESS (saveStatus))
  294 #ifdef _WIN64
  295         KeRestoreExtendedProcessorState(&SaveState);
  296 #else
  297         KeRestoreFloatingPointState (&floatingPointState);
  298 #endif
  299 #endif
  300 
  301     /* Prevent possible leaks. */
  302     burn (&hmac, sizeof(hmac));
  303 #ifndef TC_WINDOWS_BOOT
  304     burn (key, sizeof(key));
  305 #endif
  306 }
  307 
  308 #endif
  309 
  310 #ifndef TC_WINDOWS_BOOT
  311 
  312 typedef struct hmac_sha512_ctx_struct
  313 {
  314     sha512_ctx ctx;
  315     sha512_ctx inner_digest_ctx; /*pre-computed inner digest context */
  316     sha512_ctx outer_digest_ctx; /*pre-computed outer digest context */
  317     char k[SHA512_BLOCKSIZE]; /* enough to hold (salt_len + 4) and also the SHA512 hash */
  318     char u[SHA512_DIGESTSIZE];
  319 } hmac_sha512_ctx;
  320 
  321 void hmac_sha512_internal
  322 (
  323       char *d,      /* data and also output buffer of at least 64 bytes */
  324       int ld,           /* length of data in bytes */
  325       hmac_sha512_ctx* hmac
  326 )
  327 {
  328     sha512_ctx* ctx = &(hmac->ctx);
  329 
  330     /**** Restore Precomputed Inner Digest Context ****/
  331 
  332     memcpy (ctx, &(hmac->inner_digest_ctx), sizeof (sha512_ctx));
  333 
  334     sha512_hash ((unsigned char *) d, ld, ctx);
  335 
  336     sha512_end ((unsigned char *) d, ctx);
  337 
  338     /**** Restore Precomputed Outer Digest Context ****/
  339 
  340     memcpy (ctx, &(hmac->outer_digest_ctx), sizeof (sha512_ctx));
  341 
  342     sha512_hash ((unsigned char *) d, SHA512_DIGESTSIZE, ctx);
  343 
  344     sha512_end ((unsigned char *) d, ctx);
  345 }
  346 
  347 void hmac_sha512
  348 (
  349       char *k,      /* secret key */
  350       int lk,       /* length of the key in bytes */
  351       char *d,      /* data and also output buffer of at least 64 bytes */
  352       int ld            /* length of data in bytes */     
  353 )
  354 {
  355     hmac_sha512_ctx hmac;
  356     sha512_ctx* ctx;
  357     char* buf = hmac.k;
  358     int b;
  359     char key[SHA512_DIGESTSIZE];
  360 #if defined (DEVICE_DRIVER)
  361     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  362 #ifdef _WIN64
  363     XSTATE_SAVE SaveState;
  364     if (g_isIntel && HasSAVX())
  365         saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
  366 #else
  367     KFLOATING_SAVE floatingPointState;  
  368     if (HasSSSE3() && HasMMX())
  369         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  370 #endif
  371 #endif
  372 
  373     /* If the key is longer than the hash algorithm block size,
  374        let key = sha512(key), as per HMAC specifications. */
  375     if (lk > SHA512_BLOCKSIZE)
  376     {
  377         sha512_ctx tctx;
  378 
  379         sha512_begin (&tctx);
  380         sha512_hash ((unsigned char *) k, lk, &tctx);
  381         sha512_end ((unsigned char *) key, &tctx);
  382 
  383         k = key;
  384         lk = SHA512_DIGESTSIZE;
  385 
  386         burn (&tctx, sizeof(tctx));     // Prevent leaks
  387     }
  388 
  389     /**** Precompute HMAC Inner Digest ****/
  390 
  391     ctx = &(hmac.inner_digest_ctx);
  392     sha512_begin (ctx);
  393 
  394     /* Pad the key for inner digest */
  395     for (b = 0; b < lk; ++b)
  396         buf[b] = (char) (k[b] ^ 0x36);
  397     memset (&buf[lk], 0x36, SHA512_BLOCKSIZE - lk);
  398 
  399     sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, ctx);
  400 
  401     /**** Precompute HMAC Outer Digest ****/
  402 
  403     ctx = &(hmac.outer_digest_ctx);
  404     sha512_begin (ctx);
  405 
  406     for (b = 0; b < lk; ++b)
  407         buf[b] = (char) (k[b] ^ 0x5C);
  408     memset (&buf[lk], 0x5C, SHA512_BLOCKSIZE - lk);
  409 
  410     sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, ctx);
  411 
  412     hmac_sha512_internal (d, ld, &hmac);
  413 
  414 #if defined (DEVICE_DRIVER)
  415     if (NT_SUCCESS (saveStatus))
  416 #ifdef _WIN64
  417         KeRestoreExtendedProcessorState(&SaveState);
  418 #else
  419         KeRestoreFloatingPointState (&floatingPointState);
  420 #endif
  421 #endif
  422 
  423     /* Prevent leaks */
  424     burn (&hmac, sizeof(hmac));
  425     burn (key, sizeof(key));
  426 }
  427 
  428 static void derive_u_sha512 (char *salt, int salt_len, uint32 iterations, int b, hmac_sha512_ctx* hmac)
  429 {
  430     char* k = hmac->k;
  431     char* u = hmac->u;
  432     uint32 c, i;
  433 
  434     /* iteration 1 */
  435     memcpy (k, salt, salt_len); /* salt */
  436     /* big-endian block number */
  437     b = bswap_32 (b);
  438     memcpy (&k[salt_len], &b, 4);
  439 
  440     hmac_sha512_internal (k, salt_len + 4, hmac);
  441     memcpy (u, k, SHA512_DIGESTSIZE);
  442 
  443     /* remaining iterations */
  444     for (c = 1; c < iterations; c++)
  445     {
  446         hmac_sha512_internal (k, SHA512_DIGESTSIZE, hmac);
  447         for (i = 0; i < SHA512_DIGESTSIZE; i++)
  448         {
  449             u[i] ^= k[i];
  450         }
  451     }
  452 }
  453 
  454 
  455 void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
  456 {
  457     hmac_sha512_ctx hmac;
  458     sha512_ctx* ctx;
  459     char* buf = hmac.k;
  460     int b, l, r;
  461     char key[SHA512_DIGESTSIZE];
  462 #if defined (DEVICE_DRIVER)
  463     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  464 #ifdef _WIN64
  465     XSTATE_SAVE SaveState;
  466     if (g_isIntel && HasSAVX())
  467         saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
  468 #else
  469     KFLOATING_SAVE floatingPointState;  
  470     if (HasSSSE3() && HasMMX())
  471         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  472 #endif
  473 #endif
  474 
  475     /* If the password is longer than the hash algorithm block size,
  476        let pwd = sha512(pwd), as per HMAC specifications. */
  477     if (pwd_len > SHA512_BLOCKSIZE)
  478     {
  479         sha512_ctx tctx;
  480 
  481         sha512_begin (&tctx);
  482         sha512_hash ((unsigned char *) pwd, pwd_len, &tctx);
  483         sha512_end ((unsigned char *) key, &tctx);
  484 
  485         pwd = key;
  486         pwd_len = SHA512_DIGESTSIZE;
  487 
  488         burn (&tctx, sizeof(tctx));     // Prevent leaks
  489     }
  490 
  491     if (dklen % SHA512_DIGESTSIZE)
  492     {
  493         l = 1 + dklen / SHA512_DIGESTSIZE;
  494     }
  495     else
  496     {
  497         l = dklen / SHA512_DIGESTSIZE;
  498     }
  499 
  500     r = dklen - (l - 1) * SHA512_DIGESTSIZE;
  501 
  502     /**** Precompute HMAC Inner Digest ****/
  503 
  504     ctx = &(hmac.inner_digest_ctx);
  505     sha512_begin (ctx);
  506 
  507     /* Pad the key for inner digest */
  508     for (b = 0; b < pwd_len; ++b)
  509         buf[b] = (char) (pwd[b] ^ 0x36);
  510     memset (&buf[pwd_len], 0x36, SHA512_BLOCKSIZE - pwd_len);
  511 
  512     sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, ctx);
  513 
  514     /**** Precompute HMAC Outer Digest ****/
  515 
  516     ctx = &(hmac.outer_digest_ctx);
  517     sha512_begin (ctx);
  518 
  519     for (b = 0; b < pwd_len; ++b)
  520         buf[b] = (char) (pwd[b] ^ 0x5C);
  521     memset (&buf[pwd_len], 0x5C, SHA512_BLOCKSIZE - pwd_len);
  522 
  523     sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, ctx);
  524 
  525     /* first l - 1 blocks */
  526     for (b = 1; b < l; b++)
  527     {
  528         derive_u_sha512 (salt, salt_len, iterations, b, &hmac);
  529         memcpy (dk, hmac.u, SHA512_DIGESTSIZE);
  530         dk += SHA512_DIGESTSIZE;
  531     }
  532 
  533     /* last block */
  534     derive_u_sha512 (salt, salt_len, iterations, b, &hmac);
  535     memcpy (dk, hmac.u, r);
  536 
  537 #if defined (DEVICE_DRIVER)
  538     if (NT_SUCCESS (saveStatus))
  539 #ifdef _WIN64
  540         KeRestoreExtendedProcessorState(&SaveState);
  541 #else
  542         KeRestoreFloatingPointState (&floatingPointState);
  543 #endif
  544 #endif
  545 
  546     /* Prevent possible leaks. */
  547     burn (&hmac, sizeof(hmac));
  548     burn (key, sizeof(key));
  549 }
  550 
  551 #endif // TC_WINDOWS_BOOT
  552 
  553 #if !defined(TC_WINDOWS_BOOT) || defined(TC_WINDOWS_BOOT_RIPEMD160)
  554 
  555 typedef struct hmac_ripemd160_ctx_struct
  556 {
  557     RMD160_CTX context;
  558     RMD160_CTX inner_digest_ctx; /*pre-computed inner digest context */
  559     RMD160_CTX outer_digest_ctx; /*pre-computed outer digest context */
  560     char k[PKCS5_SALT_SIZE + 4]; /* enough to hold (salt_len + 4) and also the RIPEMD-160 hash */
  561     char u[RIPEMD160_DIGESTSIZE];
  562 } hmac_ripemd160_ctx;
  563 
  564 void hmac_ripemd160_internal (char *input_digest, int len, hmac_ripemd160_ctx* hmac)
  565 {
  566     RMD160_CTX* context = &(hmac->context);
  567 
  568     /**** Restore Precomputed Inner Digest Context ****/
  569 
  570     memcpy (context, &(hmac->inner_digest_ctx), sizeof (RMD160_CTX));
  571 
  572     RMD160Update(context, (const unsigned char *) input_digest, len); /* then text of datagram */
  573     RMD160Final((unsigned char *) input_digest, context);         /* finish up 1st pass */
  574 
  575     /**** Restore Precomputed Outer Digest Context ****/
  576 
  577     memcpy (context, &(hmac->outer_digest_ctx), sizeof (RMD160_CTX));
  578 
  579     /* results of 1st hash */
  580     RMD160Update(context, (const unsigned char *) input_digest, RIPEMD160_DIGESTSIZE);
  581     RMD160Final((unsigned char *) input_digest, context);         /* finish up 2nd pass */
  582 }
  583 
  584 #ifndef TC_WINDOWS_BOOT
  585 void hmac_ripemd160 (char *key, int keylen, char *input_digest, int len)
  586 {
  587     hmac_ripemd160_ctx hmac;
  588     RMD160_CTX* ctx;
  589     unsigned char* k_pad = (unsigned char*) hmac.k;  /* inner/outer padding - key XORd with ipad */
  590     unsigned char tk[RIPEMD160_DIGESTSIZE];
  591     int i;
  592 
  593     /* If the key is longer than the hash algorithm block size,
  594     let key = ripemd160(key), as per HMAC specifications. */
  595     if (keylen > RIPEMD160_BLOCKSIZE) 
  596     {
  597         RMD160_CTX      tctx;
  598 
  599         RMD160Init(&tctx);
  600         RMD160Update(&tctx, (const unsigned char *) key, keylen);
  601         RMD160Final(tk, &tctx);
  602 
  603         key = (char *) tk;
  604         keylen = RIPEMD160_DIGESTSIZE;
  605 
  606         burn (&tctx, sizeof(tctx)); // Prevent leaks
  607     }   
  608 
  609     /* perform inner RIPEMD-160 */
  610     ctx = &(hmac.inner_digest_ctx);
  611     /* start out by storing key in pads */
  612     memset(k_pad, 0x36, 64);
  613     /* XOR key with ipad and opad values */
  614     for (i=0; i<keylen; i++) 
  615     {
  616         k_pad[i] ^= key[i];
  617     }
  618 
  619     RMD160Init(ctx);           /* init context for 1st pass */
  620     RMD160Update(ctx, k_pad, RIPEMD160_BLOCKSIZE);  /* start with inner pad */
  621 
  622     /* perform outer RIPEMD-160 */
  623     ctx = &(hmac.outer_digest_ctx);
  624     memset(k_pad, 0x5c, 64);
  625     for (i=0; i<keylen; i++) 
  626     {
  627         k_pad[i] ^= key[i];
  628     }
  629 
  630     RMD160Init(ctx);           /* init context for 2nd pass */
  631     RMD160Update(ctx, k_pad, RIPEMD160_BLOCKSIZE);  /* start with outer pad */
  632 
  633     hmac_ripemd160_internal (input_digest, len, &hmac);
  634 
  635     burn (&hmac, sizeof(hmac));
  636     burn (tk, sizeof(tk));
  637 }
  638 #endif
  639 
  640 
  641 static void derive_u_ripemd160 (char *salt, int salt_len, uint32 iterations, int b, hmac_ripemd160_ctx* hmac)
  642 {
  643     char* k = hmac->k;
  644     char* u = hmac->u;
  645     uint32 c;
  646     int i;
  647 
  648 #ifdef TC_WINDOWS_BOOT
  649     /* In bootloader mode, least significant bit of iterations is a boolean (TRUE for boot derivation mode, FALSE otherwise)
  650      * and the most significant 16 bits hold the pim value
  651      * This enables us to save code space needed for implementing other features.
  652      */
  653     c = iterations >> 16;
  654     i = ((int) iterations) & 0x01;
  655     if (i)
  656         c = (c == 0)? 327661 : c << 11;
  657     else
  658         c = (c == 0)? 655331 : 15000 + c * 1000;
  659 #else
  660     c  = iterations;
  661 #endif
  662 
  663     /* iteration 1 */
  664     memcpy (k, salt, salt_len); /* salt */
  665     
  666     /* big-endian block number */
  667 #ifdef TC_WINDOWS_BOOT
  668     /* specific case of 16-bit bootloader: b is a 16-bit integer that is always < 256*/
  669     memset (&k[salt_len], 0, 3);
  670     k[salt_len + 3] = (char) b;
  671 #else
  672     b = bswap_32 (b);
  673     memcpy (&k[salt_len], &b, 4);
  674 #endif  
  675 
  676     hmac_ripemd160_internal (k, salt_len + 4, hmac);
  677     memcpy (u, k, RIPEMD160_DIGESTSIZE);
  678 
  679     /* remaining iterations */
  680     while ( c > 1)
  681     {
  682         hmac_ripemd160_internal (k, RIPEMD160_DIGESTSIZE, hmac);
  683         for (i = 0; i < RIPEMD160_DIGESTSIZE; i++)
  684         {
  685             u[i] ^= k[i];
  686         }
  687         c--;
  688     }
  689 }
  690 
  691 void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
  692 {   
  693     int b, l, r;
  694     hmac_ripemd160_ctx hmac;
  695     RMD160_CTX* ctx;
  696     unsigned char* k_pad = (unsigned char*) hmac.k;
  697 #ifndef TC_WINDOWS_BOOT
  698     unsigned char tk[RIPEMD160_DIGESTSIZE];
  699     /* If the password is longer than the hash algorithm block size,
  700        let password = ripemd160(password), as per HMAC specifications. */
  701     if (pwd_len > RIPEMD160_BLOCKSIZE) 
  702     {
  703         RMD160_CTX      tctx;
  704 
  705         RMD160Init(&tctx);
  706         RMD160Update(&tctx, (const unsigned char *) pwd, pwd_len);
  707         RMD160Final(tk, &tctx);
  708 
  709         pwd = (char *) tk;
  710         pwd_len = RIPEMD160_DIGESTSIZE;
  711 
  712         burn (&tctx, sizeof(tctx)); // Prevent leaks
  713     }
  714 #endif
  715 
  716     if (dklen % RIPEMD160_DIGESTSIZE)
  717     {
  718         l = 1 + dklen / RIPEMD160_DIGESTSIZE;
  719     }
  720     else
  721     {
  722         l = dklen / RIPEMD160_DIGESTSIZE;
  723     }
  724 
  725     r = dklen - (l - 1) * RIPEMD160_DIGESTSIZE;
  726 
  727     /* perform inner RIPEMD-160 */
  728     ctx = &(hmac.inner_digest_ctx);
  729     /* start out by storing key in pads */
  730     memset(k_pad, 0x36, 64);
  731     /* XOR key with ipad and opad values */
  732     for (b=0; b<pwd_len; b++) 
  733     {
  734         k_pad[b] ^= pwd[b];
  735     }
  736 
  737     RMD160Init(ctx);           /* init context for 1st pass */
  738     RMD160Update(ctx, k_pad, RIPEMD160_BLOCKSIZE);  /* start with inner pad */
  739 
  740     /* perform outer RIPEMD-160 */
  741     ctx = &(hmac.outer_digest_ctx);
  742     memset(k_pad, 0x5c, 64);
  743     for (b=0; b<pwd_len; b++) 
  744     {
  745         k_pad[b] ^= pwd[b];
  746     }
  747 
  748     RMD160Init(ctx);           /* init context for 2nd pass */
  749     RMD160Update(ctx, k_pad, RIPEMD160_BLOCKSIZE);  /* start with outer pad */
  750 
  751     /* first l - 1 blocks */
  752     for (b = 1; b < l; b++)
  753     {
  754         derive_u_ripemd160 (salt, salt_len, iterations, b, &hmac);
  755         memcpy (dk, hmac.u, RIPEMD160_DIGESTSIZE);
  756         dk += RIPEMD160_DIGESTSIZE;
  757     }
  758 
  759     /* last block */
  760     derive_u_ripemd160 (salt, salt_len, iterations, b, &hmac);
  761     memcpy (dk, hmac.u, r);
  762 
  763 
  764     /* Prevent possible leaks. */
  765     burn (&hmac, sizeof(hmac));
  766 #ifndef TC_WINDOWS_BOOT
  767     burn (tk, sizeof(tk));
  768 #endif
  769 }
  770 #endif // TC_WINDOWS_BOOT
  771 
  772 #ifndef TC_WINDOWS_BOOT
  773 
  774 typedef struct hmac_whirlpool_ctx_struct
  775 {
  776     WHIRLPOOL_CTX ctx;
  777     WHIRLPOOL_CTX inner_digest_ctx; /*pre-computed inner digest context */
  778     WHIRLPOOL_CTX outer_digest_ctx; /*pre-computed outer digest context */
  779     CRYPTOPP_ALIGN_DATA(16) char k[PKCS5_SALT_SIZE + 4]; /* enough to hold (salt_len + 4) and also the Whirlpool hash */
  780     char u[WHIRLPOOL_DIGESTSIZE];
  781 } hmac_whirlpool_ctx;
  782 
  783 void hmac_whirlpool_internal
  784 (
  785       char *d,      /* input/output data. d pointer is guaranteed to be at least 64-bytes long */
  786       int ld,       /* length of input data in bytes */
  787       hmac_whirlpool_ctx* hmac /* HMAC-Whirlpool context which holds temporary variables */
  788 )
  789 {
  790     WHIRLPOOL_CTX* ctx = &(hmac->ctx);
  791 
  792     /**** Restore Precomputed Inner Digest Context ****/
  793 
  794     memcpy (ctx, &(hmac->inner_digest_ctx), sizeof (WHIRLPOOL_CTX));
  795 
  796     WHIRLPOOL_add ((unsigned char *) d, ld, ctx);
  797 
  798     WHIRLPOOL_finalize (ctx, (unsigned char *) d);
  799 
  800     /**** Restore Precomputed Outer Digest Context ****/
  801 
  802     memcpy (ctx, &(hmac->outer_digest_ctx), sizeof (WHIRLPOOL_CTX));
  803 
  804     WHIRLPOOL_add ((unsigned char *) d, WHIRLPOOL_DIGESTSIZE, ctx);
  805 
  806     WHIRLPOOL_finalize (ctx, (unsigned char *) d);
  807 }
  808 
  809 void hmac_whirlpool
  810 (
  811       char *k,      /* secret key */
  812       int lk,       /* length of the key in bytes */
  813       char *d,      /* input data. d pointer is guaranteed to be at least 32-bytes long */
  814       int ld        /* length of data in bytes */
  815 )
  816 {
  817     hmac_whirlpool_ctx hmac;
  818     WHIRLPOOL_CTX* ctx;
  819     char* buf = hmac.k;
  820     int b;
  821     char key[WHIRLPOOL_DIGESTSIZE];
  822 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
  823     KFLOATING_SAVE floatingPointState;
  824     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  825     if (HasISSE())
  826         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  827 #endif
  828     /* If the key is longer than the hash algorithm block size,
  829        let key = whirlpool(key), as per HMAC specifications. */
  830     if (lk > WHIRLPOOL_BLOCKSIZE)
  831     {
  832         WHIRLPOOL_CTX tctx;
  833 
  834         WHIRLPOOL_init (&tctx);
  835         WHIRLPOOL_add ((unsigned char *) k, lk, &tctx);
  836         WHIRLPOOL_finalize (&tctx, (unsigned char *) key);
  837 
  838         k = key;
  839         lk = WHIRLPOOL_DIGESTSIZE;
  840 
  841         burn (&tctx, sizeof(tctx));     // Prevent leaks
  842     }
  843 
  844     /**** Precompute HMAC Inner Digest ****/
  845 
  846     ctx = &(hmac.inner_digest_ctx);
  847     WHIRLPOOL_init (ctx);
  848 
  849     /* Pad the key for inner digest */
  850     for (b = 0; b < lk; ++b)
  851         buf[b] = (char) (k[b] ^ 0x36);
  852     memset (&buf[lk], 0x36, WHIRLPOOL_BLOCKSIZE - lk);
  853 
  854     WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE, ctx);
  855 
  856     /**** Precompute HMAC Outer Digest ****/
  857 
  858     ctx = &(hmac.outer_digest_ctx);
  859     WHIRLPOOL_init (ctx);
  860 
  861     for (b = 0; b < lk; ++b)
  862         buf[b] = (char) (k[b] ^ 0x5C);
  863     memset (&buf[lk], 0x5C, WHIRLPOOL_BLOCKSIZE - lk);
  864 
  865     WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE, ctx);
  866 
  867     hmac_whirlpool_internal(d, ld, &hmac);
  868 
  869 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
  870     if (NT_SUCCESS (saveStatus))
  871         KeRestoreFloatingPointState (&floatingPointState);
  872 #endif
  873     /* Prevent leaks */
  874     burn(&hmac, sizeof(hmac));
  875 }
  876 
  877 static void derive_u_whirlpool (char *salt, int salt_len, uint32 iterations, int b, hmac_whirlpool_ctx* hmac)
  878 {
  879     char* u = hmac->u;
  880     char* k = hmac->k;
  881     uint32 c, i;
  882 
  883     /* iteration 1 */
  884     memcpy (k, salt, salt_len); /* salt */
  885     /* big-endian block number */
  886     b = bswap_32 (b);
  887     memcpy (&k[salt_len], &b, 4);
  888 
  889     hmac_whirlpool_internal (k, salt_len + 4, hmac);
  890     memcpy (u, k, WHIRLPOOL_DIGESTSIZE);
  891 
  892     /* remaining iterations */
  893     for (c = 1; c < iterations; c++)
  894     {
  895         hmac_whirlpool_internal (k, WHIRLPOOL_DIGESTSIZE, hmac);
  896         for (i = 0; i < WHIRLPOOL_DIGESTSIZE; i++)
  897         {
  898             u[i] ^= k[i];
  899         }
  900     }
  901 }
  902 
  903 void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
  904 {
  905     hmac_whirlpool_ctx hmac;
  906     WHIRLPOOL_CTX* ctx;
  907     char* buf = hmac.k;
  908     char key[WHIRLPOOL_DIGESTSIZE];
  909     int b, l, r;
  910 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
  911     KFLOATING_SAVE floatingPointState;
  912     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  913     if (HasISSE())
  914         saveStatus = KeSaveFloatingPointState (&floatingPointState);
  915 #endif
  916     /* If the password is longer than the hash algorithm block size,
  917        let pwd = whirlpool(pwd), as per HMAC specifications. */
  918     if (pwd_len > WHIRLPOOL_BLOCKSIZE)
  919     {
  920         WHIRLPOOL_CTX tctx;
  921 
  922         WHIRLPOOL_init (&tctx);
  923         WHIRLPOOL_add ((unsigned char *) pwd, pwd_len, &tctx);
  924         WHIRLPOOL_finalize (&tctx, (unsigned char *) key);
  925 
  926         pwd = key;
  927         pwd_len = WHIRLPOOL_DIGESTSIZE;
  928 
  929         burn (&tctx, sizeof(tctx));     // Prevent leaks
  930     }
  931 
  932     if (dklen % WHIRLPOOL_DIGESTSIZE)
  933     {
  934         l = 1 + dklen / WHIRLPOOL_DIGESTSIZE;
  935     }
  936     else
  937     {
  938         l = dklen / WHIRLPOOL_DIGESTSIZE;
  939     }
  940 
  941     r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE;
  942 
  943     /**** Precompute HMAC Inner Digest ****/
  944 
  945     ctx = &(hmac.inner_digest_ctx);
  946     WHIRLPOOL_init (ctx);
  947 
  948     /* Pad the key for inner digest */
  949     for (b = 0; b < pwd_len; ++b)
  950         buf[b] = (char) (pwd[b] ^ 0x36);
  951     memset (&buf[pwd_len], 0x36, WHIRLPOOL_BLOCKSIZE - pwd_len);
  952 
  953     WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE, ctx);
  954 
  955     /**** Precompute HMAC Outer Digest ****/
  956 
  957     ctx = &(hmac.outer_digest_ctx);
  958     WHIRLPOOL_init (ctx);
  959 
  960     for (b = 0; b < pwd_len; ++b)
  961         buf[b] = (char) (pwd[b] ^ 0x5C);
  962     memset (&buf[pwd_len], 0x5C, WHIRLPOOL_BLOCKSIZE - pwd_len);
  963 
  964     WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE, ctx);
  965 
  966     /* first l - 1 blocks */
  967     for (b = 1; b < l; b++)
  968     {
  969         derive_u_whirlpool (salt, salt_len, iterations, b, &hmac);
  970         memcpy (dk, hmac.u, WHIRLPOOL_DIGESTSIZE);
  971         dk += WHIRLPOOL_DIGESTSIZE;
  972     }
  973 
  974     /* last block */
  975     derive_u_whirlpool (salt, salt_len, iterations, b, &hmac);
  976     memcpy (dk, hmac.u, r);
  977 
  978 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
  979     if (NT_SUCCESS (saveStatus))
  980         KeRestoreFloatingPointState (&floatingPointState);
  981 #endif
  982 
  983     /* Prevent possible leaks. */
  984     burn (&hmac, sizeof(hmac));
  985     burn (key, sizeof(key));
  986 }
  987 
  988 
  989 typedef struct hmac_streebog_ctx_struct
  990 {
  991     STREEBOG_CTX ctx;
  992     STREEBOG_CTX inner_digest_ctx; /*pre-computed inner digest context */
  993     STREEBOG_CTX outer_digest_ctx; /*pre-computed outer digest context */
  994     CRYPTOPP_ALIGN_DATA(16) char k[PKCS5_SALT_SIZE + 4]; /* enough to hold (salt_len + 4) and also the Streebog hash */
  995     char u[STREEBOG_DIGESTSIZE];
  996 } hmac_streebog_ctx;
  997 
  998 void hmac_streebog_internal
  999 (
 1000       char *d,      /* input/output data. d pointer is guaranteed to be at least 64-bytes long */
 1001       int ld,       /* length of input data in bytes */
 1002       hmac_streebog_ctx* hmac /* HMAC-Whirlpool context which holds temporary variables */
 1003 )
 1004 {
 1005     STREEBOG_CTX* ctx = &(hmac->ctx);
 1006 
 1007     /**** Restore Precomputed Inner Digest Context ****/
 1008 
 1009     memcpy (ctx, &(hmac->inner_digest_ctx), sizeof (STREEBOG_CTX));
 1010 
 1011     STREEBOG_add (ctx, (unsigned char *) d, ld);
 1012 
 1013     STREEBOG_finalize (ctx, (unsigned char *) d);
 1014 
 1015     /**** Restore Precomputed Outer Digest Context ****/
 1016 
 1017     memcpy (ctx, &(hmac->outer_digest_ctx), sizeof (STREEBOG_CTX));
 1018 
 1019     STREEBOG_add (ctx, (unsigned char *) d, STREEBOG_DIGESTSIZE);
 1020 
 1021     STREEBOG_finalize (ctx, (unsigned char *) d);
 1022 }
 1023 
 1024 void hmac_streebog
 1025 (
 1026       char *k,      /* secret key */
 1027       int lk,       /* length of the key in bytes */
 1028       char *d,      /* input data. d pointer is guaranteed to be at least 32-bytes long */
 1029       int ld        /* length of data in bytes */
 1030 )
 1031 {
 1032     hmac_streebog_ctx hmac;
 1033     STREEBOG_CTX* ctx;
 1034     char* buf = hmac.k;
 1035     int b;
 1036     CRYPTOPP_ALIGN_DATA(16) char key[STREEBOG_DIGESTSIZE];
 1037 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
 1038     KFLOATING_SAVE floatingPointState;
 1039     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
 1040     if (HasSSE2() || HasSSE41())
 1041         saveStatus = KeSaveFloatingPointState (&floatingPointState);
 1042 #endif
 1043     /* If the key is longer than the hash algorithm block size,
 1044        let key = streebog(key), as per HMAC specifications. */
 1045     if (lk > STREEBOG_BLOCKSIZE)
 1046     {
 1047         STREEBOG_CTX tctx;
 1048 
 1049         STREEBOG_init (&tctx);
 1050         STREEBOG_add (&tctx, (unsigned char *) k, lk);
 1051         STREEBOG_finalize (&tctx, (unsigned char *) key);
 1052 
 1053         k = key;
 1054         lk = STREEBOG_DIGESTSIZE;
 1055 
 1056         burn (&tctx, sizeof(tctx));     // Prevent leaks
 1057     }
 1058 
 1059     /**** Precompute HMAC Inner Digest ****/
 1060 
 1061     ctx = &(hmac.inner_digest_ctx);
 1062     STREEBOG_init (ctx);
 1063 
 1064     /* Pad the key for inner digest */
 1065     for (b = 0; b < lk; ++b)
 1066         buf[b] = (char) (k[b] ^ 0x36);
 1067     memset (&buf[lk], 0x36, STREEBOG_BLOCKSIZE - lk);
 1068 
 1069     STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
 1070 
 1071     /**** Precompute HMAC Outer Digest ****/
 1072 
 1073     ctx = &(hmac.outer_digest_ctx);
 1074     STREEBOG_init (ctx);
 1075 
 1076     for (b = 0; b < lk; ++b)
 1077         buf[b] = (char) (k[b] ^ 0x5C);
 1078     memset (&buf[lk], 0x5C, STREEBOG_BLOCKSIZE - lk);
 1079 
 1080     STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
 1081 
 1082     hmac_streebog_internal(d, ld, &hmac);
 1083 
 1084 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
 1085     if (NT_SUCCESS (saveStatus))
 1086         KeRestoreFloatingPointState (&floatingPointState);
 1087 #endif
 1088     /* Prevent leaks */
 1089     burn(&hmac, sizeof(hmac));
 1090 }
 1091 
 1092 static void derive_u_streebog (char *salt, int salt_len, uint32 iterations, int b, hmac_streebog_ctx* hmac)
 1093 {
 1094     char* u = hmac->u;
 1095     char* k = hmac->k;
 1096     uint32 c, i;
 1097 
 1098     /* iteration 1 */
 1099     memcpy (k, salt, salt_len); /* salt */
 1100     /* big-endian block number */
 1101     b = bswap_32 (b);
 1102     memcpy (&k[salt_len], &b, 4);
 1103 
 1104     hmac_streebog_internal (k, salt_len + 4, hmac);
 1105     memcpy (u, k, STREEBOG_DIGESTSIZE);
 1106 
 1107     /* remaining iterations */
 1108     for (c = 1; c < iterations; c++)
 1109     {
 1110         hmac_streebog_internal (k, STREEBOG_DIGESTSIZE, hmac);
 1111         for (i = 0; i < STREEBOG_DIGESTSIZE; i++)
 1112         {
 1113             u[i] ^= k[i];
 1114         }
 1115     }
 1116 }
 1117 
 1118 void derive_key_streebog (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
 1119 {
 1120     hmac_streebog_ctx hmac;
 1121     STREEBOG_CTX* ctx;
 1122     char* buf = hmac.k;
 1123     char key[STREEBOG_DIGESTSIZE];
 1124     int b, l, r;
 1125 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
 1126     KFLOATING_SAVE floatingPointState;
 1127     NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
 1128     if (HasSSE2() || HasSSE41())
 1129         saveStatus = KeSaveFloatingPointState (&floatingPointState);
 1130 #endif
 1131     /* If the password is longer than the hash algorithm block size,
 1132        let pwd = streebog(pwd), as per HMAC specifications. */
 1133     if (pwd_len > STREEBOG_BLOCKSIZE)
 1134     {
 1135         STREEBOG_CTX tctx;
 1136 
 1137         STREEBOG_init (&tctx);
 1138         STREEBOG_add (&tctx, (unsigned char *) pwd, pwd_len);
 1139         STREEBOG_finalize (&tctx, (unsigned char *) key);
 1140 
 1141         pwd = key;
 1142         pwd_len = STREEBOG_DIGESTSIZE;
 1143 
 1144         burn (&tctx, sizeof(tctx));     // Prevent leaks
 1145     }
 1146 
 1147     if (dklen % STREEBOG_DIGESTSIZE)
 1148     {
 1149         l = 1 + dklen / STREEBOG_DIGESTSIZE;
 1150     }
 1151     else
 1152     {
 1153         l = dklen / STREEBOG_DIGESTSIZE;
 1154     }
 1155 
 1156     r = dklen - (l - 1) * STREEBOG_DIGESTSIZE;
 1157 
 1158     /**** Precompute HMAC Inner Digest ****/
 1159 
 1160     ctx = &(hmac.inner_digest_ctx);
 1161     STREEBOG_init (ctx);
 1162 
 1163     /* Pad the key for inner digest */
 1164     for (b = 0; b < pwd_len; ++b)
 1165         buf[b] = (char) (pwd[b] ^ 0x36);
 1166     memset (&buf[pwd_len], 0x36, STREEBOG_BLOCKSIZE - pwd_len);
 1167 
 1168     STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
 1169 
 1170     /**** Precompute HMAC Outer Digest ****/
 1171 
 1172     ctx = &(hmac.outer_digest_ctx);
 1173     STREEBOG_init (ctx);
 1174 
 1175     for (b = 0; b < pwd_len; ++b)
 1176         buf[b] = (char) (pwd[b] ^ 0x5C);
 1177     memset (&buf[pwd_len], 0x5C, STREEBOG_BLOCKSIZE - pwd_len);
 1178 
 1179     STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
 1180 
 1181     /* first l - 1 blocks */
 1182     for (b = 1; b < l; b++)
 1183     {
 1184         derive_u_streebog (salt, salt_len, iterations, b, &hmac);
 1185         memcpy (dk, hmac.u, STREEBOG_DIGESTSIZE);
 1186         dk += STREEBOG_DIGESTSIZE;
 1187     }
 1188 
 1189     /* last block */
 1190     derive_u_streebog (salt, salt_len, iterations, b, &hmac);
 1191     memcpy (dk, hmac.u, r);
 1192 
 1193 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
 1194     if (NT_SUCCESS (saveStatus))
 1195         KeRestoreFloatingPointState (&floatingPointState);
 1196 #endif
 1197 
 1198     /* Prevent possible leaks. */
 1199     burn (&hmac, sizeof(hmac));
 1200     burn (key, sizeof(key));
 1201 }
 1202 
 1203 wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id)
 1204 {
 1205     switch (pkcs5_prf_id)
 1206     {
 1207     case SHA512:    
 1208         return L"HMAC-SHA-512";
 1209 
 1210     case SHA256:    
 1211         return L"HMAC-SHA-256";
 1212 
 1213     case RIPEMD160: 
 1214         return L"HMAC-RIPEMD-160";
 1215 
 1216     case WHIRLPOOL: 
 1217         return L"HMAC-Whirlpool";
 1218 
 1219     case STREEBOG:
 1220         return L"HMAC-STREEBOG";
 1221 
 1222     default:        
 1223         return L"(Unknown)";
 1224     }
 1225 }
 1226 
 1227 
 1228 
 1229 int get_pkcs5_iteration_count (int pkcs5_prf_id, int pim, BOOL truecryptMode, BOOL bBoot)
 1230 {
 1231     if (    (pim < 0)
 1232         || (truecryptMode && pim > 0) /* No PIM for TrueCrypt mode */
 1233         )
 1234     {
 1235         return 0;
 1236     }
 1237 
 1238     switch (pkcs5_prf_id)
 1239     {
 1240 
 1241     case RIPEMD160: 
 1242         if (truecryptMode)
 1243             return bBoot ? 1000 : 2000;
 1244         else if (pim == 0)
 1245             return bBoot? 327661 : 655331;
 1246         else
 1247         {
 1248             return bBoot? pim * 2048 : 15000 + pim * 1000;
 1249         }
 1250 
 1251     case SHA512:    
 1252         return truecryptMode? 1000 : ((pim == 0)? 500000 : 15000 + pim * 1000);
 1253 
 1254     case WHIRLPOOL: 
 1255         return truecryptMode? 1000 : ((pim == 0)? 500000 : 15000 + pim * 1000);
 1256 
 1257     case SHA256:
 1258         if (truecryptMode)
 1259             return 0; // SHA-256 not supported by TrueCrypt
 1260         else if (pim == 0)
 1261             return bBoot? 200000 : 500000;
 1262         else
 1263         {
 1264             return bBoot? pim * 2048 : 15000 + pim * 1000;
 1265         }
 1266 
 1267     case STREEBOG:  
 1268         if (truecryptMode)
 1269             return 1000;
 1270         else if (pim == 0)
 1271             return bBoot? 200000 : 500000;
 1272         else
 1273         {
 1274             return bBoot? pim * 2048 : 15000 + pim * 1000;
 1275         }
 1276 
 1277     default:        
 1278         TC_THROW_FATAL_EXCEPTION;   // Unknown/wrong ID
 1279     }
 1280     return 0;
 1281 }
 1282 
 1283 int is_pkcs5_prf_supported (int pkcs5_prf_id, BOOL truecryptMode, PRF_BOOT_TYPE bootType)
 1284 {
 1285    if (pkcs5_prf_id == 0) // auto-detection always supported
 1286       return 1;
 1287 
 1288    if (truecryptMode)
 1289    {
 1290       if (  (bootType == PRF_BOOT_GPT) 
 1291          || (bootType == PRF_BOOT_MBR && pkcs5_prf_id != RIPEMD160) 
 1292          || (bootType == PRF_BOOT_NO && pkcs5_prf_id != SHA512 && pkcs5_prf_id != WHIRLPOOL && pkcs5_prf_id != RIPEMD160)
 1293          )
 1294          return 0;
 1295    }
 1296    else
 1297    {
 1298       if (  (bootType == PRF_BOOT_MBR && pkcs5_prf_id != RIPEMD160 && pkcs5_prf_id != SHA256)
 1299          || (bootType != PRF_BOOT_MBR && (pkcs5_prf_id < FIRST_PRF_ID || pkcs5_prf_id > LAST_PRF_ID))
 1300          )
 1301          return 0;
 1302    }
 1303 
 1304    return 1;
 1305 
 1306 }
 1307 
 1308 #endif //!TC_WINDOWS_BOOT