/* * Copyright (c) 2023, [MTG AG](https://www.mtg.de). * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #if defined(ENABLE_PQC) #include "rnp_tests.h" #include #include "crypto/dilithium.h" #include "crypto/sphincsplus.h" #include "crypto/kyber.h" TEST_F(rnp_tests, test_kyber_key_function) { kyber_parameter_e params[2] = {kyber_768, kyber_1024}; for (kyber_parameter_e param : params) { auto public_and_private_key = kyber_generate_keypair(&global_ctx.rng, param); kyber_encap_result_t encap_res = public_and_private_key.first.encapsulate(&global_ctx.rng); std::vector decrypted = public_and_private_key.second.decapsulate( &global_ctx.rng, encap_res.ciphertext.data(), encap_res.ciphertext.size()); assert_int_equal(encap_res.symmetric_key.size(), decrypted.size()); assert_memory_equal( encap_res.symmetric_key.data(), decrypted.data(), decrypted.size()); } } TEST_F(rnp_tests, test_dilithium_key_function) { dilithium_parameter_e params[2] = {dilithium_L3, dilithium_L5}; for (dilithium_parameter_e param : params) { auto public_and_private_key = dilithium_generate_keypair(&global_ctx.rng, param); std::array msg{'H', 'e', 'l', 'l', 'o'}; std::vector signature = public_and_private_key.second.sign(&global_ctx.rng, msg.data(), msg.size()); assert_true(public_and_private_key.first.verify_signature( msg.data(), msg.size(), signature.data(), signature.size())); } } TEST_F(rnp_tests, test_sphincsplus_key_function) { sphincsplus_parameter_t params[] = {sphincsplus_simple_128s, sphincsplus_simple_128f, sphincsplus_simple_192s, sphincsplus_simple_192f, sphincsplus_simple_256s, sphincsplus_simple_256f}; sphincsplus_hash_func_t hash_funcs[] = {sphincsplus_sha256, sphinscplus_shake256}; for (sphincsplus_parameter_t param : params) { for (sphincsplus_hash_func_t hash_func : hash_funcs) { auto public_and_private_key = sphincsplus_generate_keypair(&global_ctx.rng, param, hash_func); std::array msg{'H', 'e', 'l', 'l', 'o'}; pgp_sphincsplus_signature_t sig; assert_rnp_success(public_and_private_key.second.sign( &global_ctx.rng, &sig, msg.data(), msg.size())); assert_rnp_success( public_and_private_key.first.verify(&sig, msg.data(), msg.size())); } } } TEST_F(rnp_tests, test_dilithium_exdsa_direct) { pgp_pubkey_alg_t algs[] = {PGP_PKA_DILITHIUM3_ED25519, /* PGP_PKA_DILITHIUM5_ED448,*/ PGP_PKA_DILITHIUM3_P256, PGP_PKA_DILITHIUM5_P384, PGP_PKA_DILITHIUM3_BP256, PGP_PKA_DILITHIUM5_BP384}; for (size_t i = 0; i < ARRAY_SIZE(algs); i++) { uint8_t message[64]; const pgp_hash_alg_t hash_alg = PGP_HASH_SHA512; // Generate test data. Mainly to make valgrind not to complain about uninitialized data global_ctx.rng.get(message, sizeof(message)); pgp_dilithium_exdsa_key_t key; pgp_dilithium_exdsa_signature_t sig; assert_rnp_success( pgp_dilithium_exdsa_composite_key_t::gen_keypair(&global_ctx.rng, &key, algs[i])); assert_rnp_success( key.priv.sign(&global_ctx.rng, &sig, hash_alg, message, sizeof(message))); assert_rnp_success(key.pub.verify(&sig, hash_alg, message, sizeof(message))); // Fails because message won't verify message[0] = ~message[0]; assert_rnp_failure(key.pub.verify(&sig, hash_alg, message, sizeof(message))); message[0] = ~message[0]; // Fails because first sig won't verify sig.sig.data()[0] = ~sig.sig.data()[0]; assert_rnp_failure(key.pub.verify(&sig, hash_alg, message, sizeof(message))); sig.sig.data()[0] = ~sig.sig.data()[0]; // Fails because second sig won't verify sig.sig.data()[sig.sig.size() - 1] = ~sig.sig.data()[sig.sig.size() - 1]; assert_rnp_failure(key.pub.verify(&sig, hash_alg, message, sizeof(message))); sig.sig.data()[sig.sig.size() - 1] = ~sig.sig.data()[sig.sig.size() - 1]; } } #endif