/*
 * Argon2 reference source code package - reference C implementations
 *
 * Copyright 2015
 * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
 *
 * You may use this work under the terms of a Creative Commons CC0 1.0
 * License/Waiver or the Apache Public License 2.0, at your option. The terms of
 * these licenses can be found at:
 *
 * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
 * - Apache 2.0        : https://www.apache.org/licenses/LICENSE-2.0
 *
 * You should have received a copy of both of these licenses along with this
 * software. If not, they may be obtained at the above URLs.
 */


/*================================================================================*/
/*  MODIFICATIONS by Alfred J. Baier (2018-2024)                                  */
/*                                                                                */
/*  Selftests for Argon2d/2i/2id (Version 1.3) using test vectors from            */
/*  http://tools.ietf.org/id/draft-irtf-cfrg-argon2-03.html#section-6             */
/*  Now: https://datatracker.ietf.org/doc/rfc9106/ Section 5.                     */
/*  See also:                                                                     */
/*  https://github.com/RustCrypto/password-hashes/blob/master/argon2/tests/kat.rs */
/*                                                                                */
/*  Return values:  0    =  Selftest OK / no error.                               */
/*                  >=1  =  Selftest failed / number of failed test cases.        */
/*                                                                                */
/*  Note: The selftest functions verify the correctness of Argon2 hashing on      */
/*  the current host processor (using the selected CPU extended features and      */
/*  optimizations) for various parameters and input values.                       */
/*  They do, however, not provide a comprehensive test for all Argon2 functions,  */
/*  programme paths, and error cases.                                             */
/*================================================================================*/

/* Modified for VeraCrypt integration - June 2025 by Mounir IDRASSI */

#include "argon2.h"

#undef   TEST_LARGE_RAM      /* Additional Argon2i test with 1 GiB */


/*==============================================================================
 * Basic selftest for Argon2d/2i/2id (Version 1.3) using test vectors from
 * http://tools.ietf.org/id/draft-irtf-cfrg-argon2-03.html#section-6
 * Now: https://datatracker.ietf.org/doc/rfc9106/ Sections 5.1 - 5.3.
 *
 * Uses argon2_ctx() with memory cost of 32 Bytes.
 * Runs 3 test cases.
 * Returns number of failed test cases.
 */
static int argon2_selftest_ctx (void)
{
   int i, err = 0;
   argon2_context context;
   uint8_t hash[32], pwd[32], salt[16], sec[8], ad[12];

   for (i=0; i<32; i++) pwd[i]  = 0x01;     /* Fill test vectors */
   for (i=0; i<16; i++) salt[i] = 0x02;
   for (i=0; i< 8; i++) sec[i]  = 0x03;
   for (i=0; i<12; i++) ad[i]   = 0x04;

   static const uint8_t ref0d[32] =          /* Reference hash results */
   {0x51,0x2b,0x39,0x1b,0x6f,0x11,0x62,0x97,0x53,0x71,0xd3,0x09,0x19,0x73,0x42,0x94,
    0xf8,0x68,0xe3,0xbe,0x39,0x84,0xf3,0xc1,0xa1,0x3a,0x4d,0xb9,0xfa,0xbe,0x4a,0xcb};

   static const uint8_t ref0i[32] =
   {0xc8,0x14,0xd9,0xd1,0xdc,0x7f,0x37,0xaa,0x13,0xf0,0xd7,0x7f,0x24,0x94,0xbd,0xa1,
    0xc8,0xde,0x6b,0x01,0x6d,0xd3,0x88,0xd2,0x99,0x52,0xa4,0xc4,0x67,0x2b,0x6c,0xe8};

   static const uint8_t ref0id[32] =
   {0x0d,0x64,0x0d,0xf5,0x8d,0x78,0x76,0x6c,0x08,0xc0,0x37,0xa3,0x4a,0x8b,0x53,0xc9,
    0xd0,0x1e,0xf0,0x45,0x2d,0x75,0xb6,0x5e,0xb5,0x25,0x20,0xe9,0x6b,0x01,0xe6,0x59};

   context.out = (uint8_t*) hash;           /* Init Argon2 context */
   context.outlen = 32;
   context.pwd = (uint8_t*) pwd;
   context.pwdlen = 32;
   context.salt = (uint8_t*) salt;
   context.saltlen = 16;
   context.secret = (uint8_t*) sec;
   context.secretlen = 8;
   context.ad = (uint8_t*) ad;
   context.adlen = 12;
   context.t_cost = 3;
   context.m_cost = 32;
   context.lanes = 4;
   context.threads = 4;
   context.allocate_cbk = NULL;
   context.free_cbk = NULL;
   context.flags = ARGON2_DEFAULT_FLAGS;
   context.version = ARGON2_VERSION_13;
   context.pAbortKeyDerivation = NULL; /* No abort function */

   /* Test execution for Argon2d, Argon2i, Argon2id */

   if (argon2_ctx (&context, Argon2_d) == ARGON2_OK &&
       memcmp (hash, ref0d, 32) != 0) err++;

   if (argon2_ctx (&context, Argon2_i) == ARGON2_OK &&
       memcmp (hash, ref0i, 32) != 0) err++;

   if (argon2_ctx (&context, Argon2_id) == ARGON2_OK &&
       memcmp (hash, ref0id, 32) != 0) err++;

   return err;
}


/*==============================================================================
 * Hash test helper function for Argon2 (Version 1.3).
 * Calls argon2_hash().
 */
static int hashtest (uint32_t t, uint32_t m, uint32_t p, const char *pwd,
                     const char *salt, argon2_type type, const uint8_t *ref)
{
   uint8_t out[32];

   return (argon2_hash(t, 1 << m, p, pwd, strlen (pwd), salt, strlen (salt),
           out, 32, type, ARGON2_VERSION_NUMBER, NULL) == ARGON2_OK &&
           memcmp (out, ref, 32) == 0) ? 0 : 1;
}


/*==============================================================================
 * Selftest function for Argon2i (Version 1.3). Includes 1 Argon2d test case.
 * Using test vectors from Argon2 reference source code package ("test.c")
 * and from https://tools.ietf.org/id/draft-irtf-cfrg-argon2-03.html#section-5.6
 * See also:
 * https://github.com/RustCrypto/password-hashes/blob/master/argon2/tests/kat.rs
 *
 * Uses memory costs of 32 Bytes, 256 KiB, 4 MiB, 64 MiB, 256 MiB.
 * Runs 13 test cases in total + 1 optional large memory test (1 GiB).
 * Returns number of failed test cases.
 */
int argon2i_selftest (void)
{
   int err = argon2_selftest_ctx ();        /* Basic test using argon2_ctx() */

   static const uint8_t ref1i[32] =
   {0x89,0xe9,0x02,0x9f,0x46,0x37,0xb2,0x95,0xbe,0xb0,0x27,0x05,0x6a,0x73,0x36,0xc4,
    0x14,0xfa,0xdd,0x43,0xf6,0xb2,0x08,0x64,0x52,0x81,0xcb,0x21,0x4a,0x56,0x45,0x2f};
   err += hashtest(2, 8, 1, "password", "somesalt", Argon2_i, ref1i);

   static const uint8_t ref2i[32] =
   {0x4f,0xf5,0xce,0x27,0x69,0xa1,0xd7,0xf4,0xc8,0xa4,0x91,0xdf,0x09,0xd4,0x1a,0x9f,
    0xbe,0x90,0xe5,0xeb,0x02,0x15,0x5a,0x13,0xe4,0xc0,0x1e,0x20,0xcd,0x4e,0xab,0x61};
   err += hashtest(2, 8, 2, "password", "somesalt", Argon2_i, ref2i);

   static const uint8_t ref3i[32] =
   {0x95,0x7f,0xc0,0x72,0x7d,0x83,0xf4,0x06,0x0b,0xb0,0xf1,0x07,0x1e,0xb5,0x90,0xa1,
    0x9a,0x8c,0x44,0x8f,0xc0,0x20,0x94,0x97,0xee,0x4f,0x54,0xca,0x24,0x1f,0x3c,0x90};
   err += hashtest (3, 12, 1, "pasword", "somesalt", Argon2_i, ref3i);

   static const uint8_t ref4d[32] =
   {0x0b,0x3f,0x09,0xe7,0xb8,0xd0,0x36,0xe5,0x8c,0xcd,0x08,0xf0,0x8c,0xb6,0xba,0xbf,
    0x7e,0x5e,0x24,0x63,0xc2,0x6b,0xcf,0x2a,0x9e,0x4e,0xa7,0x0d,0x74,0x7c,0x40,0x98};
   err += hashtest (3, 12, 1, "pasword", "somesalt", Argon2_d, ref4d);

   static const uint8_t ref5i[32] =
   {0xd1,0x68,0x07,0x5c,0x4d,0x98,0x5e,0x13,0xeb,0xea,0xe5,0x60,0xcf,0x8b,0x94,0xc3,
    0xb5,0xd8,0xa1,0x6c,0x51,0x91,0x6b,0x6f,0x4a,0xc2,0xda,0x3a,0xc1,0x1b,0xbe,0xcf};
   err += hashtest (1, 16, 1, "password", "somesalt", Argon2_i, ref5i);

   static const uint8_t ref6i[32] =
   {0xc1,0x62,0x88,0x32,0x14,0x7d,0x97,0x20,0xc5,0xbd,0x1c,0xfd,0x61,0x36,0x70,0x78,
    0x72,0x9f,0x6d,0xfb,0x6f,0x8f,0xea,0x9f,0xf9,0x81,0x58,0xe0,0xd7,0x81,0x6e,0xd0};
   err += hashtest (2, 16, 1, "password", "somesalt", Argon2_i, ref6i);

   static const uint8_t ref7i[32] =
   {0x14,0xae,0x8d,0xa0,0x1a,0xfe,0xa8,0x70,0x0c,0x23,0x58,0xdc,0xef,0x7c,0x53,0x58,
    0xd9,0x02,0x12,0x82,0xbd,0x88,0x66,0x3a,0x45,0x62,0xf5,0x9f,0xb7,0x4d,0x22,0xee};
   err += hashtest (2, 16, 1, "differentpassword", "somesalt", Argon2_i, ref7i);

   static const uint8_t ref8i[32] =
   {0xb0,0x35,0x7c,0xcc,0xfb,0xef,0x91,0xf3,0x86,0x0b,0x0d,0xba,0x44,0x7b,0x23,0x48,
    0xcb,0xef,0xec,0xad,0xaf,0x99,0x0a,0xbf,0xe9,0xcc,0x40,0x72,0x6c,0x52,0x12,0x71};
   err += hashtest (2, 16, 1, "password", "diffsalt", Argon2_i, ref8i);

   static const uint8_t ref9i[32] =
   {0xaa,0xa9,0x53,0xd5,0x8a,0xf3,0x70,0x6c,0xe3,0xdf,0x1a,0xef,0xd4,0xa6,0x4a,0x84,
    0xe3,0x1d,0x7f,0x54,0x17,0x52,0x31,0xf1,0x28,0x52,0x59,0xf8,0x81,0x74,0xce,0x5b};
   err += hashtest (4, 16, 1, "password", "somesalt", Argon2_i, ref9i);

   static const uint8_t ref10i[32] =
   {0x29,0x6d,0xba,0xe8,0x0b,0x80,0x7c,0xdc,0xea,0xad,0x44,0xae,0x74,0x1b,0x50,0x6f,
    0x14,0xdb,0x09,0x59,0x26,0x7b,0x18,0x3b,0x11,0x8f,0x9b,0x24,0x22,0x9b,0xc7,0xcb};
   err += hashtest (2, 18, 1, "password", "somesalt", Argon2_i, ref10i);

#ifdef TEST_LARGE_RAM                       /* Argon2i: 1 GiB Test */
   static const uint8_t ref11i[32] =
   {0xd1,0x58,0x7a,0xca,0x09,0x22,0xc3,0xb5,0xd6,0xa8,0x3e,0xda,0xb3,0x1b,0xee,0x3c,
    0x4e,0xba,0xef,0x34,0x2e,0xd6,0x12,0x7a,0x55,0xd1,0x9b,0x23,0x51,0xad,0x1f,0x41};
   err += hashtest (2, 20, 1, "password", "somesalt", Argon2_i, ref11i);
#endif

   return err;
}


/*==============================================================================
 * Selftest function for Argon2id (Version 1.3).
 * Using test vectors from Argon2 reference source code package ("test.c")
 * and from https://tools.ietf.org/id/draft-irtf-cfrg-argon2-03.html#section-5.6
 * See also:
 * https://github.com/RustCrypto/password-hashes/blob/master/argon2/tests/kat.rs
 * 
 * Uses memory costs of 32 Bytes, 256 KiB, 4 MiB, 64 MiB, 256 MiB.
 * Runs 12 test cases in total.
 * Returns number of failed test cases.
 */
int argon2id_selftest (void)
{
   int err = argon2_selftest_ctx ();        /* Basic test using argon2_ctx() */

   static const uint8_t ref1id[32] =
   {0x9d,0xfe,0xb9,0x10,0xe8,0x0b,0xad,0x03,0x11,0xfe,0xe2,0x0f,0x9c,0x0e,0x2b,0x12,
    0xc1,0x79,0x87,0xb4,0xca,0xc9,0x0c,0x2e,0xf5,0x4d,0x5b,0x30,0x21,0xc6,0x8b,0xfe};
   err += hashtest (2, 8, 1, "password", "somesalt", Argon2_id, ref1id);

   static const uint8_t ref2id[32] =
   {0x6d,0x09,0x3c,0x50,0x1f,0xd5,0x99,0x96,0x45,0xe0,0xea,0x3b,0xf6,0x20,0xd7,0xb8,
    0xbe,0x7f,0xd2,0xdb,0x59,0xc2,0x0d,0x9f,0xff,0x95,0x39,0xda,0x2b,0xf5,0x70,0x37};
   err += hashtest (2, 8, 2, "password", "somesalt", Argon2_id, ref2id);

   static const uint8_t ref3id[32] =
   {0xf5,0x55,0x35,0xbf,0xe9,0x48,0x71,0x00,0x51,0x42,0x4c,0x74,0x24,0xb1,0x1b,0xa9,
    0xa1,0x3a,0x50,0x23,0x9b,0x04,0x59,0xf5,0x6c,0xa6,0x95,0xea,0x14,0xbc,0x19,0x5e};
   err += hashtest (3, 12, 1, "pasword", "somesalt", Argon2_id, ref3id);

   static const uint8_t ref4id[32] =
   {0xf6,0xa5,0xad,0xc1,0xba,0x72,0x3d,0xdd,0xef,0x9b,0x5a,0xc1,0xd4,0x64,0xe1,0x80,
    0xfc,0xd9,0xdf,0xfc,0x9d,0x1c,0xbf,0x76,0xcc,0xa2,0xfe,0xd7,0x95,0xd9,0xca,0x98};
   err += hashtest (1, 16, 1, "password", "somesalt", Argon2_id, ref4id);
/*
   static const uint8_t ref5id[32] =
   {0x09,0x31,0x61,0x15,0xd5,0xcf,0x24,0xed,0x5a,0x15,0xa3,0x1a,0x3b,0xa3,0x26,0xe5,
    0xcf,0x32,0xed,0xc2,0x47,0x02,0x98,0x7c,0x02,0xb6,0x56,0x6f,0x61,0x91,0x3c,0xf7};
   err += hashtest (2, 16, 1, "password", "somesalt", Argon2_id, ref5id);

   static const uint8_t ref6id[32] =
   {0x0b,0x84,0xd6,0x52,0xcf,0x6b,0x0c,0x4b,0xea,0xef,0x0d,0xfe,0x27,0x8b,0xa6,0xa8,
    0x0d,0xf6,0x69,0x62,0x81,0xd7,0xe0,0xd2,0x89,0x1b,0x81,0x7d,0x8c,0x45,0x8f,0xde};
   err += hashtest (2, 16, 1, "differentpassword", "somesalt", Argon2_id, ref6id);

   static const uint8_t ref7id[32] =
   {0xbd,0xf3,0x2b,0x05,0xcc,0xc4,0x2e,0xb1,0x5d,0x58,0xfd,0x19,0xb1,0xf8,0x56,0xb1,
    0x13,0xda,0x1e,0x9a,0x58,0x74,0xfd,0xcc,0x54,0x43,0x08,0x56,0x5a,0xa8,0x14,0x1c};
   err += hashtest (2, 16, 1, "password", "diffsalt", Argon2_id, ref7id);

   static const uint8_t ref8id[32] =
   {0x90,0x25,0xd4,0x8e,0x68,0xef,0x73,0x95,0xcc,0xa9,0x07,0x9d,0xa4,0xc4,0xec,0x3a,
    0xff,0xb3,0xc8,0x91,0x1f,0xe4,0xf8,0x6d,0x1a,0x25,0x20,0x85,0x6f,0x63,0x17,0x2c};
   err += hashtest (4, 16, 1, "password", "somesalt", Argon2_id, ref8id);

   static const uint8_t ref9id[32] =
   {0x78,0xfe,0x1e,0xc9,0x1f,0xb3,0xaa,0x56,0x57,0xd7,0x2e,0x71,0x08,0x54,0xe4,0xc3,
    0xd9,0xb9,0x19,0x8c,0x74,0x2f,0x96,0x16,0xc2,0xf0,0x85,0xbe,0xd9,0x5b,0x2e,0x8c};
   err += hashtest (2, 18, 1, "password", "somesalt", Argon2_id, ref9id);
   */
   return err;
}
