LCOV - code coverage report
Current view: top level - source/third_party/encryption - pkcs5_pbkdf2.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 43 50 86.0 %
Date: 2023-01-19 00:18:29 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
       3             :  *
       4             :  * Permission to use, copy, modify, and distribute this software for any
       5             :  * purpose with or without fee is hereby granted, provided that the above
       6             :  * copyright notice and this permission notice appear in all copies.
       7             :  *
       8             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       9             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      10             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      11             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      12             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      13             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      14             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      15             :  */
      16             : // This file is based loosly off libutil/pkcs5_pbkdf2.c in OpenBSD.
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "pkcs5_pbkdf2.h"
      21             : 
      22             : #include <cstring>
      23             : 
      24             : // This does not match libsodium crypto_auth_hmacsha256, which has a constant key_len.
      25         400 : static void hmac_sha256(unsigned char (&digest)[crypto_hash_sha256_BYTES],
      26             :                         const unsigned char* text, size_t text_len,
      27             :                         const unsigned char* key, size_t key_len)
      28             : {
      29             :     crypto_hash_sha256_state state;
      30         400 :     crypto_hash_sha256_init(&state);
      31             : 
      32             :     unsigned char tk[crypto_hash_sha256_BYTES]; // temporary key in case we need to pad the key with zero unsigned chars
      33         400 :     if (key_len > crypto_hash_sha256_BYTES)
      34             :     {
      35           0 :         crypto_hash_sha256_update(&state, key, key_len);
      36           0 :         crypto_hash_sha256_final(&state, tk);
      37           0 :         key = tk;
      38           0 :         key_len = crypto_hash_sha256_BYTES;
      39             :     }
      40             : 
      41             :     unsigned char k_pad[crypto_hash_sha256_BYTES];
      42             : 
      43         400 :     memset(k_pad, 0, sizeof k_pad);
      44         400 :     memcpy(k_pad, key, key_len);
      45       13200 :     for (unsigned int i = 0; i < crypto_hash_sha256_BYTES; ++i)
      46       12800 :         k_pad[i] ^= 0x36;
      47         400 :     crypto_hash_sha256_init(&state);
      48         400 :     crypto_hash_sha256_update(&state, k_pad, crypto_hash_sha256_BYTES);
      49         400 :     crypto_hash_sha256_update(&state, text, text_len);
      50         400 :     crypto_hash_sha256_final(&state, digest);
      51             : 
      52             : 
      53         400 :     memset(k_pad, 0, sizeof k_pad);
      54         400 :     memcpy(k_pad, key, key_len);
      55       13200 :     for (unsigned int i = 0; i < crypto_hash_sha256_BYTES; ++i)
      56       12800 :         k_pad[i] ^= 0x5c;
      57             : 
      58         400 :     crypto_hash_sha256_init(&state);
      59         400 :     crypto_hash_sha256_update(&state, k_pad, crypto_hash_sha256_BYTES);
      60         400 :     crypto_hash_sha256_update(&state, digest, crypto_hash_sha256_BYTES);
      61         400 :     crypto_hash_sha256_final(&state, digest);
      62         400 : }
      63             : 
      64             : 
      65           6 : int pbkdf2(unsigned char (&output)[crypto_hash_sha256_BYTES],
      66             :             const unsigned char* key, size_t key_len,
      67             :             const unsigned char* salt, size_t salt_len,
      68             :             unsigned rounds)
      69             : {
      70             :     unsigned char asalt[crypto_hash_sha256_BYTES + 4], obuf[crypto_hash_sha256_BYTES], d1[crypto_hash_sha256_BYTES], d2[crypto_hash_sha256_BYTES];
      71             : 
      72           6 :     if (rounds < 1 || key_len == 0 || salt_len == 0)
      73           0 :         return -1;
      74             : 
      75           6 :     if (salt_len > crypto_hash_sha256_BYTES) salt_len = crypto_hash_sha256_BYTES; // length cap for the salt
      76           6 :     memset(asalt, 0, salt_len);
      77           6 :     memcpy(asalt, salt, salt_len);
      78             : 
      79           6 :     for (unsigned count = 1; ; ++count)
      80             :     {
      81           6 :         asalt[salt_len + 0] = (count >> 24) & 0xff;
      82           6 :         asalt[salt_len + 1] = (count >> 16) & 0xff;
      83           6 :         asalt[salt_len + 2] = (count >> 8) & 0xff;
      84           6 :         asalt[salt_len + 3] = count & 0xff;
      85           6 :         hmac_sha256(d1, asalt, salt_len + 4, key, key_len);
      86           6 :         memcpy(obuf, d1, crypto_hash_sha256_BYTES);
      87             : 
      88         400 :         for (unsigned i = 1; i < rounds; i++)
      89             :         {
      90         394 :             hmac_sha256(d2, d1, crypto_hash_sha256_BYTES, key, key_len);
      91         394 :             memcpy(d1, d2, crypto_hash_sha256_BYTES);
      92       13002 :             for (unsigned j = 0; j < crypto_hash_sha256_BYTES; j++)
      93       12608 :                 obuf[j] ^= d1[j];
      94             :         }
      95             : 
      96           6 :         memcpy(output, obuf, crypto_hash_sha256_BYTES);
      97           6 :         key += crypto_hash_sha256_BYTES;
      98           6 :         if (key_len < crypto_hash_sha256_BYTES)
      99           6 :             break;
     100           0 :         key_len -= crypto_hash_sha256_BYTES;
     101           0 :     };
     102           6 :     return 0;
     103           3 : }
     104             : 

Generated by: LCOV version 1.13