Example #1
0
static int
_crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n,
                           const unsigned char *p, const int clamp)
{
    unsigned char *t = q;
    ge25519_p3     Q;
    ge25519_p3     P;
    unsigned int   i;

    if (ge25519_is_canonical(p) == 0 || ge25519_has_small_order(p) != 0 ||
        ge25519_frombytes(&P, p) != 0 || ge25519_is_on_main_subgroup(&P) == 0) {
        return -1;
    }
    for (i = 0; i < 32; ++i) {
        t[i] = n[i];
    }
    if (clamp != 0) {
        _crypto_scalarmult_ed25519_clamp(t);
    }
    ge25519_scalarmult(&Q, t, &P);
    ge25519_p3_tobytes(q, &Q);
    if (_crypto_scalarmult_ed25519_is_inf(q) != 0 || sodium_is_zero(n, 32)) {
        return -1;
    }
    return 0;
}
Example #2
0
static int
_crypto_scalarmult_ed25519_base(unsigned char *q,
                                const unsigned char *n, const int clamp)
{
    unsigned char *t = q;
    ge25519_p3     Q;
    unsigned int   i;

    for (i = 0; i < 32; ++i) {
        t[i] = n[i];
    }
    if (clamp != 0) {
        _crypto_scalarmult_ed25519_clamp(t);
    }
    ge25519_scalarmult_base(&Q, t);
    ge25519_p3_tobytes(q, &Q);
    if (_crypto_scalarmult_ed25519_is_inf(q) != 0 || sodium_is_zero(n, 32)) {
        return -1;
    }
    return 0;
}
Example #3
0
static void
tv_stream_xchacha20(void)
{
    static const XChaCha20TV tvs[] = {
        { "79c99798ac67300bbb2704c95c341e3245f3dcb21761b98e52ff45b24f304fc4", "b33ffd3096479bcfbc9aee49417688a0a2554f8d95389419", "c6e9758160083ac604ef90e712ce6e75d7797590744e0cf060f013739c" },
        { "ddf7784fee099612c40700862189d0397fcc4cc4b3cc02b5456b3a97d1186173", "a9a04491e7bf00c3ca91ac7c2d38a777d88993a7047dfcc4", "2f289d371f6f0abc3cb60d11d9b7b29adf6bc5ad843e8493e928448d" },
        { "3d12800e7b014e88d68a73f0a95b04b435719936feba60473f02a9e61ae60682", "56bed2599eac99fb27ebf4ffcb770a64772dec4d5849ea2d", "a2c3c1406f33c054a92760a8e0666b84f84fa3a618f0" },
        { "5f5763ff9a30c95da5c9f2a8dfd7cc6efd9dfb431812c075aa3e4f32e04f53e4", "a5fa890efa3b9a034d377926ce0e08ee6d7faccaee41b771", "8a1a5ba898bdbcff602b1036e469a18a5e45789d0e8d9837d81a2388a52b0b6a0f51891528f424c4a7f492a8dd7bce8bac19fbdbe1fb379ac0" },
        { "eadc0e27f77113b5241f8ca9d6f9a5e7f09eee68d8a5cf30700563bf01060b4e", "a171a4ef3fde7c4794c5b86170dc5a099b478f1b852f7b64", "23839f61795c3cdbcee2c749a92543baeeea3cbb721402aa42e6cae140447575f2916c5d71108e3b13357eaf86f060cb" },
        { "91319c9545c7c804ba6b712e22294c386fe31c4ff3d278827637b959d3dbaab2", "410e854b2a911f174aaf1a56540fc3855851f41c65967a4e", "cbe7d24177119b7fdfa8b06ee04dade4256ba7d35ffda6b89f014e479faef6" },
        { "6a6d3f412fc86c4450fc31f89f64ed46baa3256ffcf8616e8c23a06c422842b6", "6b7773fce3c2546a5db4829f53a9165f41b08faae2fb72d5", "8b23e35b3cdd5f3f75525fc37960ec2b68918e8c046d8a832b9838f1546be662e54feb1203e2" },
        { "d45e56368ebc7ba9be7c55cfd2da0feb633c1d86cab67cd5627514fd20c2b391", "fd37da2db31e0c738754463edadc7dafb0833bd45da497fc", "47950efa8217e3dec437454bd6b6a80a287e2570f0a48b3fa1ea3eb868be3d486f6516606d85e5643becc473b370871ab9ef8e2a728f73b92bd98e6e26ea7c8ff96ec5a9e8de95e1eee9300c" },
        { "aface41a64a9a40cbc604d42bd363523bd762eb717f3e08fe2e0b4611eb4dcf3", "6906e0383b895ab9f1cf3803f42f27c79ad47b681c552c63", "a5fa7c0190792ee17675d52ad7570f1fb0892239c76d6e802c26b5b3544d13151e67513b8aaa1ac5af2d7fd0d5e4216964324838" },
        { "9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232", "c047548266b7c370d33566a2425cbf30d82d1eaf5294109e", "a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc" },
    };
    const XChaCha20TV *tv;
    char              *hex;
    unsigned char     *key;
    unsigned char     *nonce;
    unsigned char     *out;
    unsigned char     *out2;
    size_t             out_len;
    int                i;

    key = (unsigned char *) sodium_malloc(crypto_stream_xchacha20_KEYBYTES);
    nonce = (unsigned char *) sodium_malloc(crypto_stream_xchacha20_NONCEBYTES);
    out = (unsigned char *) sodium_malloc(XCHACHA20_OUT_MAX);
    for (i = 0; i < (sizeof tvs) / (sizeof tvs[0]); i++) {
        tv = &tvs[i];

        sodium_hex2bin(key, crypto_stream_xchacha20_KEYBYTES,
                       tv->key, strlen(tv->key), NULL, NULL, NULL);
        sodium_hex2bin(nonce, crypto_stream_xchacha20_NONCEBYTES,
                       tv->nonce, strlen(tv->nonce), NULL, NULL, NULL);
        sodium_hex2bin(out, XCHACHA20_OUT_MAX,
                       tv->out, strlen(tv->out), NULL, &out_len, NULL);
        out2 = (unsigned char *) sodium_malloc(out_len);
        crypto_stream_xchacha20(out2, out_len, nonce, key);
        assert(memcmp(out, out2, out_len) == 0);
        crypto_stream_xchacha20_xor(out2, out, out_len, nonce, key);
        assert(sodium_is_zero(out2, out_len));
        crypto_stream_xchacha20_xor_ic(out2, out, out_len, nonce, 0, key);
        assert(sodium_is_zero(out2, out_len));
        crypto_stream_xchacha20_xor_ic(out2, out, out_len, nonce, 1, key);
        assert(!sodium_is_zero(out2, out_len));
        crypto_stream_xchacha20_xor(out, out, out_len, nonce, key);
        assert(sodium_is_zero(out, out_len));
        sodium_free(out2);
    }

    out2 = (unsigned char *) sodium_malloc(0);
    crypto_stream_xchacha20(out2, 0, nonce, key);
    crypto_stream_xchacha20_xor(out2, out2, 0, nonce, key);
    crypto_stream_xchacha20_xor_ic(out2, out2, 0, nonce, 1, key);
    sodium_free(out2);
    sodium_free(out);

    out = (unsigned char *) sodium_malloc(64);
    out2 = (unsigned char *) sodium_malloc(128);
    randombytes_buf(out, 64);
    randombytes_buf(out2, 64);
    memcpy(out2 + 64, out, 64);
    crypto_stream_xchacha20_xor_ic(out, out, 64, nonce, 1, key);
    crypto_stream_xchacha20_xor(out2, out2, 128, nonce, key);
    assert(memcmp(out, out2 + 64, 64) == 0);
    sodium_free(out);
    sodium_free(out2);

    out = (unsigned char *) sodium_malloc(192);
    out2 = (unsigned char *) sodium_malloc(192);
    memset(out, 0, 192);
    memset(out2, 0, 192);
    crypto_stream_xchacha20_xor_ic(out2, out2, 192, nonce,
                                   (1ULL << 32) - 1ULL, key);
    crypto_stream_xchacha20_xor_ic(out, out, 64, nonce,
                                   (1ULL << 32) - 1ULL, key);
    crypto_stream_xchacha20_xor_ic(out + 64, out + 64, 64, nonce,
                                   (1ULL << 32), key);
    crypto_stream_xchacha20_xor_ic(out + 128, out + 128, 64, nonce,
                                   (1ULL << 32) + 1, key);
    assert(memcmp(out, out2, 192) == 0);
    hex = (char *) sodium_malloc(192 * 2 + 1);
    sodium_bin2hex(hex, 192 * 2 + 1, out, 192);
    printf("%s\n", hex);
    sodium_free(hex);
    sodium_free(out);
    sodium_free(out2);

    sodium_free(nonce);
    sodium_free(key);

    assert(crypto_stream_xchacha20_keybytes() == crypto_stream_xchacha20_KEYBYTES);
    assert(crypto_stream_xchacha20_noncebytes() == crypto_stream_xchacha20_NONCEBYTES);

    printf("tv_stream_xchacha20: ok\n");
}
//DNSCurve initialization
void DNSCurveInit(
	void)
{
//DNSCurve signature request TCP Mode
	if (DNSCurveParameter.DNSCurveProtocol_Transport == REQUEST_MODE_TRANSPORT::FORCE_TCP || DNSCurveParameter.DNSCurveProtocol_Transport == REQUEST_MODE_TRANSPORT::TCP)
	{
	//IPv6 Main
		if (DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.AddressData.Storage.ss_family != 0 && 
			(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
			DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV6) && //IPv6
			((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
			(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
			CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
		{
			std::thread Thread_DNSCurve_SignatureRequest_TCP(std::bind(DNSCurve_SignatureRequest_TCP, static_cast<const uint16_t>(AF_INET6), false));
			Thread_DNSCurve_SignatureRequest_TCP.detach();
		}

	//IPv4 Main
		if (DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.AddressData.Storage.ss_family != 0 && 
			(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
			DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV4) && //IPv4
			((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
			(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
			CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
		{
			std::thread Thread_DNSCurve_SignatureRequest_TCP(std::bind(DNSCurve_SignatureRequest_TCP, static_cast<const uint16_t>(AF_INET), false));
			Thread_DNSCurve_SignatureRequest_TCP.detach();
		}

	//IPv6 Alternate
		if (DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.AddressData.Storage.ss_family != 0 && 
			(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
			DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV6) && //IPv6
			((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
			(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
			CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
		{
			std::thread Thread_DNSCurve_SignatureRequest_TCP(std::bind(DNSCurve_SignatureRequest_TCP, static_cast<const uint16_t>(AF_INET6), true));
			Thread_DNSCurve_SignatureRequest_TCP.detach();
		}

	//IPv4 Alternate
		if (DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.AddressData.Storage.ss_family != 0 && 
			(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
			DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV4) && //IPv4
			((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
			(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
			CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
		{
			std::thread Thread_DNSCurve_SignatureRequest_TCP(std::bind(DNSCurve_SignatureRequest_TCP, static_cast<const uint16_t>(AF_INET), true));
			Thread_DNSCurve_SignatureRequest_TCP.detach();
		}
	}

//Force protocol(TCP).
	if (DNSCurveParameter.DNSCurveProtocol_Transport == REQUEST_MODE_TRANSPORT::FORCE_TCP)
		return;

//DNSCurve signature request UDP Mode
//IPv6 Main
	if (DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.AddressData.Storage.ss_family != 0 && 
		(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
		DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV6) && //IPv6
		((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
		(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
		CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
	{
		std::thread Thread_DNSCurve_SignatureRequest_UDP(std::bind(DNSCurve_SignatureRequest_UDP, static_cast<const uint16_t>(AF_INET6), false));
		Thread_DNSCurve_SignatureRequest_UDP.detach();
	}

//IPv4 Main
	if (DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.AddressData.Storage.ss_family != 0 && 
		(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //IPv4
		DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV4) && //Auto select
		((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
		(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
		CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
	{
		std::thread Thread_DNSCurve_SignatureRequest_UDP(std::bind(DNSCurve_SignatureRequest_UDP, static_cast<const uint16_t>(AF_INET), false));
		Thread_DNSCurve_SignatureRequest_UDP.detach();
	}

//IPv6 Alternate
	if (DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.AddressData.Storage.ss_family != 0 && 
		(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
		DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV6) && //IPv6
		((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
		(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
		CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
	{
		std::thread Thread_DNSCurve_SignatureRequest_UDP(std::bind(DNSCurve_SignatureRequest_UDP, static_cast<const uint16_t>(AF_INET6), true));
		Thread_DNSCurve_SignatureRequest_UDP.detach();
	}

//IPv4 Alternate
	if (DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.AddressData.Storage.ss_family != 0 && 
		(DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::BOTH || //Auto select
		DNSCurveParameter.DNSCurveProtocol_Network == REQUEST_MODE_NETWORK::IPV4) && //IPv4
		((!DNSCurveParameter.IsClientEphemeralKey && sodium_is_zero(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.PrecomputationKey, crypto_box_BEFORENMBYTES) != 0) || 
		(DNSCurveParameter.IsClientEphemeralKey && CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.ServerFingerprint, crypto_box_PUBLICKEYBYTES)) || 
		CheckEmptyBuffer(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)))
	{
		std::thread Thread_DNSCurve_SignatureRequest_UDP(std::bind(DNSCurve_SignatureRequest_UDP, static_cast<const uint16_t>(AF_INET), true));
		Thread_DNSCurve_SignatureRequest_UDP.detach();
	}

	return;
}
static void
str_tests(void)
{
    char       *str_out;
    char       *str_out2;
    char       *salt;
    const char *passwd = "Correct Horse Battery Staple";

    salt     = (char *) sodium_malloc(crypto_pwhash_SALTBYTES);
    str_out  = (char *) sodium_malloc(crypto_pwhash_STRBYTES);
    str_out2 = (char *) sodium_malloc(crypto_pwhash_STRBYTES);
    memcpy(salt, ">A 16-bytes salt", crypto_pwhash_SALTBYTES);
    if (crypto_pwhash_argon2i_str(str_out, passwd, strlen(passwd), OPSLIMIT,
                                  MEMLIMIT) != 0) {
        printf("pwhash_argon2i_str failure\n");
    }
    if (crypto_pwhash_argon2i_str(str_out2, passwd, strlen(passwd), OPSLIMIT,
                                  MEMLIMIT) != 0) {
        printf("pwhash_argon2i_str(2) failure\n");
    }
    if (strcmp(str_out, str_out2) == 0) {
        printf("pwhash_argon2i_str() doesn't generate different salts\n");
    }
    if (crypto_pwhash_argon2i_str_needs_rehash(str_out, OPSLIMIT, MEMLIMIT) != 0) {
        printf("needs_rehash() false positive\n");
    }
    if (crypto_pwhash_argon2i_str_needs_rehash(str_out, OPSLIMIT, MEMLIMIT / 2) != 1 ||
        crypto_pwhash_argon2i_str_needs_rehash(str_out, OPSLIMIT / 2, MEMLIMIT) != 1 ||
        crypto_pwhash_argon2i_str_needs_rehash(str_out, OPSLIMIT, MEMLIMIT * 2) != 1 ||
        crypto_pwhash_argon2i_str_needs_rehash(str_out, OPSLIMIT * 2, MEMLIMIT) != 1) {
        printf("needs_rehash() false negative\n");
    }
    if (crypto_pwhash_argon2i_str_needs_rehash(str_out + 1, OPSLIMIT, MEMLIMIT) != -1) {
        printf("needs_rehash() didn't fail with an invalid hash string\n");
    }
    if (sodium_is_zero((const unsigned char *) str_out + strlen(str_out),
                       crypto_pwhash_STRBYTES - strlen(str_out)) != 1 ||
        sodium_is_zero((const unsigned char *) str_out2 + strlen(str_out2),
                       crypto_pwhash_STRBYTES - strlen(str_out2)) != 1) {
        printf("pwhash_str() doesn't properly pad with zeros\n");
    }
    if (crypto_pwhash_argon2i_str_verify(str_out, passwd, strlen(passwd)) != 0) {
        printf("pwhash_str_verify(1) failure\n");
    }
    str_out[14]++;
    if (crypto_pwhash_argon2i_str_verify(str_out, passwd, strlen(passwd)) != -1) {
        printf("pwhash_str_verify(2) failure\n");
    }
    str_out[14]--;
    assert(str_out[crypto_pwhash_STRBYTES - 1U] == 0);

    if (crypto_pwhash_argon2i_str(str_out2, passwd, 0x100000000ULL, OPSLIMIT,
                                  MEMLIMIT) != -1) {
        printf("pwhash_str() with a large password should have failed\n");
    }
    if (crypto_pwhash_argon2i_str(str_out2, passwd, strlen(passwd), 1, MEMLIMIT) !=
        -1) {
        printf("pwhash_str() with a small opslimit should have failed\n");
    }
    if (crypto_pwhash_argon2i_str_verify("$argon2i$m=65536,t=2,p=1c29tZXNhbHQ"
                                         "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
                                         "password", 0x100000000ULL) != -1) {
        printf("pwhash_str_verify(invalid(0)) failure\n");
    }
    if (crypto_pwhash_argon2i_str_verify("$argon2i$m=65536,t=2,p=1c29tZXNhbHQ"
                                 "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
                                 "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(1)) failure %d\n", errno);
    }
    if (crypto_pwhash_argon2i_str_verify("$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ"
                                         "9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
                                         "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(2)) failure\n");
    }
    if (crypto_pwhash_str_verify("$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ"
                                 "$b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo",
                                 "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(3)) failure\n");
    }
    if (crypto_pwhash_str_verify("$argon2i$v=19$m=65536,t=2,p=1c29tZXNhbHQ"
                                 "$wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA",
                                 "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(4)) failure\n");
    }
    if (crypto_pwhash_str_verify("$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ"
                                 "wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA",
                                 "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(5)) failure\n");
    }
    if (crypto_pwhash_str_verify("$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ"
                                 "$8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM",
                                 "password", strlen("password")) != -1) {
        printf("pwhash_str_verify(invalid(6)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$argon2i$v=19$m=4096,t=3,p=2$b2RpZHVlamRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYIU+0jWipu7Kc9M",
            "password", strlen("password")) != 0) {
        printf("pwhash_str_verify(valid(7)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$argon2i$v=19$m=4096,t=3,p=2$b2RpZHVlamRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYIU+0jWipu7Kc9M",
            "passwore", strlen("passwore")) != -1 || errno != EINVAL) {
        printf("pwhash_str_verify(invalid(7)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$Argon2i$v=19$m=4096,t=3,p=2$b2RpZHVlamRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYIU+0jWipu7Kc9M",
            "password", strlen("password")) != -1 || errno != EINVAL) {
        printf("pwhash_str_verify(invalid(8)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$argon2i$v=1$m=4096,t=3,p=2$b2RpZHVlamRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYIU+0jWipu7Kc9M",
            "password", strlen("password")) != -1 || errno != EINVAL) {
        printf("pwhash_str_verify(invalid(9)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$argon2i$v=1$m=4096,t=3,p=2$b2RpZHVla~=mRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYIU+0jWipu7Kc9M",
            "password", strlen("password")) != -1 || errno != EINVAL) {
        printf("pwhash_str_verify(invalid(10)) failure\n");
    }
    if (crypto_pwhash_str_verify(
            "$argon2i$v=1$m=4096,t=3,p=2$b2RpZHVlamRpc29kaXNrdw"
            "$TNnWIwlu1061JHrnCqIAmjs3huSxYI~=U+0jWipu7Kc9M",
            "password", strlen("password")) != -1 || errno != EINVAL) {
        printf("pwhash_str_verify(invalid(11)) failure\n");
    }
    assert(crypto_pwhash_str_alg(str_out, "test", 4, OPSLIMIT, MEMLIMIT,
                                 crypto_pwhash_ALG_ARGON2I13) == 0);
    assert(crypto_pwhash_argon2i_str_verify(str_out, "test", 4) == 0);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out,
                                                  OPSLIMIT, MEMLIMIT) == 0);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out,
                                                  OPSLIMIT / 2, MEMLIMIT) == 1);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out,
                                                  OPSLIMIT, MEMLIMIT / 2) == 1);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out, 0, 0) == 1);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out, 0, 0) == -1);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out + 1,
                                                  OPSLIMIT, MEMLIMIT) == -1);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out, 0, 0) == -1);
    assert(crypto_pwhash_argon2id_str_needs_rehash("", OPSLIMIT, MEMLIMIT) == -1);
    assert(crypto_pwhash_str_alg(str_out, "test", 4, OPSLIMIT, MEMLIMIT,
                                 crypto_pwhash_ALG_ARGON2ID13) == 0);
    assert(crypto_pwhash_argon2id_str_verify(str_out, "test", 4) == 0);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out,
                                                   OPSLIMIT, MEMLIMIT) == 0);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out,
                                                   OPSLIMIT / 2, MEMLIMIT) == 1);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out,
                                                   OPSLIMIT, MEMLIMIT / 2) == 1);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out, 0, 0) == 1);
    assert(crypto_pwhash_argon2i_str_needs_rehash(str_out, 0, 0) == -1);
    assert(crypto_pwhash_argon2id_str_needs_rehash("", OPSLIMIT, MEMLIMIT) == -1);
    assert(crypto_pwhash_argon2id_str_needs_rehash(str_out + 1,
                                                   OPSLIMIT, MEMLIMIT) == -1);
    sodium_free(salt);
    sodium_free(str_out);
    sodium_free(str_out2);
}
int main(void)
{
    unsigned char  buf1[1000];
    unsigned char  buf2[1000];
    unsigned char  buf1_rev[1000];
    unsigned char  buf2_rev[1000];
    char           buf3[33];
    unsigned char  buf4[4];
    unsigned char  nonce[24];
    char           nonce_hex[49];
    const char    *hex;
    const char    *hex_end;
    size_t         bin_len;
    unsigned int   i;
    unsigned int   j;

    randombytes_buf(buf1, sizeof buf1);
    memcpy(buf2, buf1, sizeof buf2);
    printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1));
    sodium_memzero(buf1, 0U);
    printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1));
    sodium_memzero(buf1, sizeof buf1 / 2);
    printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1));
    printf("%d\n", sodium_memcmp(buf1, buf2, 0U));
    sodium_memzero(buf2, sizeof buf2 / 2);
    printf("%d\n", sodium_memcmp(buf1, buf2, sizeof buf1));
    printf("%s\n",
           sodium_bin2hex(buf3, 33U, (const unsigned char *)"0123456789ABCDEF",
                          16U));
    hex = "Cafe : 6942";
    sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, &hex_end);
    printf("%lu:%02x%02x%02x%02x\n", (unsigned long)bin_len, buf4[0], buf4[1],
           buf4[2], buf4[3]);
    printf("dt1: %ld\n", (long) (hex_end - hex));

    hex = "Cafe : 6942";
    sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, NULL);
    printf("%lu:%02x%02x%02x%02x\n", (unsigned long)bin_len, buf4[2], buf4[3],
           buf4[2], buf4[3]);

    hex = "deadbeef";
    if (sodium_hex2bin(buf1, 1U, hex, 8U, NULL, &bin_len, &hex_end) != -1) {
        printf("sodium_hex2bin() overflow not detected\n");
    }
    printf("dt2: %ld\n", (long) (hex_end - hex));

    hex = "de:ad:be:eff";
    if (sodium_hex2bin(buf1, 4U, hex, 12U, ":", &bin_len, &hex_end) != -1) {
        printf("sodium_hex2bin() with an odd input length and a short output buffer\n");
    }
    printf("dt3: %ld\n", (long) (hex_end - hex));

    hex = "de:ad:be:eff";
    if (sodium_hex2bin(buf1, sizeof buf1, hex, 12U, ":", &bin_len, &hex_end) != 0) {
        printf("sodium_hex2bin() with an odd input length\n");
    }
    printf("dt4: %ld\n", (long) (hex_end - hex));

    hex = "de:ad:be:eff";
    if (sodium_hex2bin(buf1, sizeof buf1, hex, 13U, ":", &bin_len, &hex_end) != 0) {
        printf("sodium_hex2bin() with an odd input length\n");
    }
    printf("dt5: %ld\n", (long) (hex_end - hex));

    memset(nonce, 0, sizeof nonce);
    sodium_increment(nonce, sizeof nonce);
    printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex,
                                  nonce, sizeof nonce));
    memset(nonce, 255, sizeof nonce);
    sodium_increment(nonce, sizeof nonce);
    printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex,
                                  nonce, sizeof nonce));
    nonce[1] = 1U;
    sodium_increment(nonce, sizeof nonce);
    printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex,
                                  nonce, sizeof nonce));
    nonce[1] = 0U;
    sodium_increment(nonce, sizeof nonce);
    printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex,
                                  nonce, sizeof nonce));
    nonce[0] = 255U;
    nonce[2] = 255U;
    sodium_increment(nonce, sizeof nonce);
    printf("%s\n", sodium_bin2hex(nonce_hex, sizeof nonce_hex,
                                  nonce, sizeof nonce));
    for (i = 0U; i < 1000U; i++) {
        bin_len = (size_t) randombytes_uniform(sizeof buf1);
        randombytes_buf(buf1, bin_len);
        randombytes_buf(buf2, bin_len);
        for (j = 0U; j < bin_len; j++) {
            buf1_rev[bin_len - 1 - j] = buf1[j];
            buf2_rev[bin_len - 1 - j] = buf2[j];
        }
        if (memcmp(buf1_rev, buf2_rev, bin_len) *
            sodium_compare(buf1, buf2, bin_len) < 0) {
            printf("sodium_compare() failure with length=%u\n",
                   (unsigned int) bin_len);
        }
        memcpy(buf1, buf2, bin_len);
        if (sodium_compare(buf1, buf2, bin_len)) {
            printf("sodium_compare() equality failure with length=%u\n",
                   (unsigned int) bin_len);
        }
    }
    memset(buf1, 0, sizeof buf1);
    if (sodium_is_zero(buf1, sizeof buf1) != 1) {
        printf("sodium_is_zero() failed\n");
    }
    buf1[randombytes_uniform(sizeof buf1)]++;
    if (sodium_is_zero(buf1, sizeof buf1) != 0) {
        printf("sodium_is_zero() failed\n");
    }
    return 0;
}