LCOV - code coverage report
Current view: top level - src/crypto - scrypt.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 127 130 97.7 %
Date: 2025-02-23 09:33:43 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler
       3             :  * All rights reserved.
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions
       7             :  * are met:
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  * 2. Redistributions in binary form must reproduce the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer in the
      12             :  *    documentation and/or other materials provided with the distribution.
      13             :  *
      14             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      15             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      16             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      17             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      18             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      19             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      20             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      21             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      22             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      23             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      24             :  * SUCH DAMAGE.
      25             :  *
      26             :  * This file was originally written by Colin Percival as part of the Tarsnap
      27             :  * online backup system.
      28             :  */
      29             : 
      30             : #include "crypto/scrypt.h"
      31             : 
      32             : #include "crypto/hmac_sha256.h"
      33             : #include "crypto/sha256.h"
      34             : #include "uint256.h"
      35             : #include "utilstrencodings.h"
      36             : 
      37             : #include <string>
      38             : 
      39             : #include <string.h>
      40             : #include <stdint.h>
      41             : 
      42             : #ifndef __FreeBSD__
      43         516 : static inline void be32enc(void *pp, uint32_t x)
      44             : {
      45         516 :     uint8_t *p = (uint8_t *)pp;
      46         516 :     p[3] = x & 0xff;
      47         516 :     p[2] = (x >> 8) & 0xff;
      48         516 :     p[1] = (x >> 16) & 0xff;
      49         516 :     p[0] = (x >> 24) & 0xff;
      50             : }
      51             : #endif
      52             : 
      53             : 
      54             : /**
      55             :  * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
      56             :  * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
      57             :  * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1).
      58             :  */
      59             : void
      60           4 : PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt,
      61             :               size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen)
      62             : {
      63           4 :     size_t i;
      64           4 :     uint8_t ivec[4];
      65           4 :     uint8_t U[32];
      66           4 :     uint8_t T[32];
      67           4 :     uint64_t j;
      68           4 :     int k;
      69           4 :     size_t clen;
      70             : 
      71             :     /* Compute HMAC state after processing P and S. */
      72           4 :     CHMAC_SHA256 PShctx = CHMAC_SHA256(passwd, passwdlen).Write(salt, saltlen);
      73             : 
      74             :     /* Iterate through the blocks. */
      75         520 :     for (i = 0; i * 32 < dkLen; i++) {
      76             :         /* Generate INT(i + 1). */
      77         516 :         be32enc(ivec, (uint32_t)(i + 1));
      78             : 
      79             :         /* Compute U_1 = PRF(P, S || INT(i)). */
      80         516 :         CHMAC_SHA256(PShctx).Write(ivec, 4).Finalize(U);
      81             : 
      82             :         /* T_i = U_1 ... */
      83         516 :         memcpy(T, U, 32);
      84             : 
      85         516 :         for (j = 2; j <= c; j++) {
      86             :             /* Compute U_j. */
      87           0 :             CHMAC_SHA256(passwd, passwdlen).Write(U, 32).Finalize(U);
      88             : 
      89             :             /* ... xor U_j ... */
      90           0 :             for (k = 0; k < 32; k++)
      91           0 :                 T[k] ^= U[k];
      92             :         }
      93             : 
      94             :         /* Copy as many bytes as necessary into buf. */
      95         516 :         clen = dkLen - i * 32;
      96         516 :         if (clen > 32)
      97         512 :             clen = 32;
      98         516 :         memcpy(&buf[i * 32], T, clen);
      99             :     }
     100             : 
     101           4 : }
     102             : 
     103             : static inline uint32_t
     104        4096 : le32dec_2(const void * pp)
     105             : {
     106        4096 :     const uint8_t * p = (uint8_t const *)pp;
     107             : 
     108        4096 :     return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
     109        4096 :             ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
     110             : }
     111             : 
     112             : static inline void
     113        4096 : le32enc_2(void * pp, uint32_t x)
     114             : {
     115        4096 :     uint8_t * p = (uint8_t *)pp;
     116             : 
     117        4096 :     p[0] = x & 0xff;
     118        4096 :     p[1] = (x >> 8) & 0xff;
     119        4096 :     p[2] = (x >> 16) & 0xff;
     120        4096 :     p[3] = (x >> 24) & 0xff;
     121             : }
     122             : 
     123             : static void
     124    17563600 : blkcpy(void * dest, const void * src, size_t len)
     125             : {
     126    17563600 :     size_t * D = (size_t*)dest;
     127    17563600 :     const size_t * S = (size_t*)src;
     128    17563600 :     size_t L = len / sizeof(size_t);
     129    17563600 :     size_t i;
     130             : 
     131   189530000 :     for (i = 0; i < L; i++)
     132   171966000 :         D[i] = S[i];
     133    17563600 : }
     134             : 
     135             : static void
     136     8650750 : blkxor(void * dest, const void * src, size_t len)
     137             : {
     138     8650750 :     size_t * D = (size_t*)dest;
     139     8650750 :     const size_t* S = (size_t*)src;
     140     8650750 :     size_t L = len / sizeof(size_t);
     141     8650750 :     size_t i;
     142             : 
     143   109314000 :     for (i = 0; i < L; i++)
     144   100663000 :         D[i] ^= S[i];
     145     8650750 : }
     146             : 
     147             : /**
     148             :  * salsa20_8(B):
     149             :  * Apply the salsa20/8 core to the provided block.
     150             :  */
     151             : static void
     152     8388610 : salsa20_8(uint32_t B[16])
     153             : {
     154     8388610 :     uint32_t x[16];
     155     8388610 :     size_t i;
     156             : 
     157     8388610 :     blkcpy(x, B, 64);
     158    41943000 :     for (i = 0; i < 8; i += 2) {
     159             : #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
     160             :         /* Operate on columns. */
     161    33554400 :         x[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9);
     162    33554400 :         x[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18);
     163             : 
     164    33554400 :         x[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9);
     165    33554400 :         x[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18);
     166             : 
     167    33554400 :         x[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9);
     168    33554400 :         x[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18);
     169             : 
     170    33554400 :         x[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9);
     171    33554400 :         x[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18);
     172             : 
     173             :         /* Operate on rows. */
     174    33554400 :         x[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9);
     175    33554400 :         x[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18);
     176             : 
     177    33554400 :         x[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9);
     178    33554400 :         x[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18);
     179             : 
     180    33554400 :         x[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9);
     181    33554400 :         x[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18);
     182             : 
     183    33554400 :         x[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9);
     184    33554400 :         x[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18);
     185             : #undef R
     186             :     }
     187   142606000 :     for (i = 0; i < 16; i++)
     188   134218000 :         B[i] += x[i];
     189     8388610 : }
     190             : 
     191             : /**
     192             :  * blockmix_salsa8(Bin, Bout, X, r):
     193             :  * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r
     194             :  * bytes in length; the output Bout must also be the same size.  The
     195             :  * temporary space X must be 64 bytes.
     196             :  */
     197             : static void
     198      524288 : blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
     199             : {
     200      524288 :     size_t i;
     201             : 
     202             :     /* 1: X <-- B_{2r - 1} */
     203      524288 :     blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
     204             : 
     205             :     /* 2: for i = 0 to 2r - 1 do */
     206     4718590 :     for (i = 0; i < 2 * r; i += 2) {
     207             :         /* 3: X <-- H(X \xor B_i) */
     208     4194300 :         blkxor(X, &Bin[i * 16], 64);
     209     4194300 :         salsa20_8(X);
     210             : 
     211             :         /* 4: Y_i <-- X */
     212             :         /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
     213     4194300 :         blkcpy(&Bout[i * 8], X, 64);
     214             : 
     215             :         /* 3: X <-- H(X \xor B_i) */
     216     4194300 :         blkxor(X, &Bin[i * 16 + 16], 64);
     217     4194300 :         salsa20_8(X);
     218             : 
     219             :         /* 4: Y_i <-- X */
     220             :         /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
     221     4194300 :         blkcpy(&Bout[i * 8 + r * 16], X, 64);
     222             :     }
     223      524288 : }
     224             : 
     225             : /**
     226             :  * integerify(B, r):
     227             :  * Return the result of parsing B_{2r-1} as a little-endian integer.
     228             :  */
     229             : static uint64_t
     230      262144 : integerify(const void * B, size_t r)
     231             : {
     232      262144 :     const uint32_t * X = (const uint32_t*)((uintptr_t)(B) + (2 * r - 1) * 64);
     233             : 
     234      262144 :     return (((uint64_t)(X[1]) << 32) + X[0]);
     235             : }
     236             : 
     237          16 : void SMix(uint8_t *B, unsigned int r, unsigned int N, void* _V, void* XY)
     238             : {
     239             :     //new
     240          16 :     uint32_t* X = (uint32_t*)XY;
     241          16 :     uint32_t* Y = (uint32_t*)((uint8_t*)(XY) + 128 * r);
     242          16 :     uint32_t* Z = (uint32_t*)((uint8_t *)(XY) + 256 * r);
     243          16 :     uint32_t * V = (uint32_t*)_V;
     244             : 
     245          16 :     uint32_t j, k;
     246             : 
     247             :     /* 1: X <-- B */
     248        4112 :     for (k = 0; k < 32 * r; k++)
     249        4096 :         X[k] = le32dec_2(&B[4 * k]);
     250             : 
     251             :     /* 2: for i = 0 to N - 1 do */
     252      131088 :     for (unsigned int i = 0; i < N; i += 2)
     253             :     {
     254             :         /* 3: V_i <-- X */
     255      131072 :         blkcpy(&V[i * (32 * r)], X, 128 * r);
     256             : 
     257             :         /* 4: X <-- H(X) */
     258      131072 :         blockmix_salsa8(X, Y, Z, r);
     259             : 
     260             :         /* 3: V_i <-- X */
     261      131072 :         blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
     262             : 
     263             :         /* 4: X <-- H(X) */
     264      131072 :         blockmix_salsa8(Y, X, Z, r);
     265             :     }
     266             : 
     267             :     /* 6: for i = 0 to N - 1 do */
     268      131088 :     for (unsigned int i = 0; i < N; i += 2)
     269             :     {
     270             :         /* 7: j <-- Integerify(X) mod N */
     271      131072 :         j = integerify(X, r) & (N - 1);
     272             : 
     273             :         /* 8: X <-- H(X \xor V_j) */
     274      131072 :         blkxor(X, &V[j * (32 * r)], 128 * r);
     275      131072 :         blockmix_salsa8(X, Y, Z, r);
     276             : 
     277             :         /* 7: j <-- Integerify(X) mod N */
     278      131072 :         j = integerify(Y, r) & (N - 1);
     279             : 
     280             :         /* 8: X <-- H(X \xor V_j) */
     281      131072 :         blkxor(Y, &V[j * (32 * r)], 128 * r);
     282      131072 :         blockmix_salsa8(Y, X, Z, r);
     283             :     }
     284             : 
     285             :     /* 10: B' <-- X */
     286        4112 :     for (k = 0; k < 32 * r; k++)
     287        4096 :         le32enc_2(&B[4 * k], X[k]);
     288          16 : }
     289             : 
     290           2 : void scrypt(const char* pass, unsigned int pLen, const char* salt, unsigned int sLen, char *output, unsigned int N, unsigned int r, unsigned int p, unsigned int dkLen)
     291             : {
     292             :     //containers
     293           2 :     void* V0 = malloc(128 * r * N + 63);
     294           2 :     void* XY0 = malloc(256 * r + 64 + 63);
     295           2 :     void* B1 = malloc(128 * r * p + 63);
     296           2 :     uint8_t* B = (uint8_t *)(((uintptr_t)(B1) + 63) & ~ (uintptr_t)(63));
     297           2 :     uint32_t* V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
     298           2 :     uint32_t* XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
     299             : 
     300           2 :     PBKDF2_SHA256((const uint8_t *)pass, pLen, (const uint8_t *)salt, sLen, 1, B, p * 128 * r);
     301             : 
     302          18 :     for(unsigned int i = 0; i < p; i++)
     303             :     {
     304          16 :         SMix(&B[i * 128 * r], r, N, V, XY);
     305             :     }
     306             : 
     307           2 :     PBKDF2_SHA256((const uint8_t *)pass, pLen, B, p * 128 * r, 1, (uint8_t *)output, dkLen);
     308             : 
     309           2 :     free(V0);
     310           2 :     free(XY0);
     311           2 :     free(B1);
     312           2 : }

Generated by: LCOV version 1.14