diff options
Diffstat (limited to 'src/tests/pubkey_test.c')
-rw-r--r-- | src/tests/pubkey_test.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/tests/pubkey_test.c b/src/tests/pubkey_test.c new file mode 100644 index 000000000..93962516a --- /dev/null +++ b/src/tests/pubkey_test.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Public key self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ipxe/crypto.h> +#include <ipxe/test.h> +#include "pubkey_test.h" + +/** + * Report public key encryption and decryption test result + * + * @v test Public key encryption and decryption test + * @v file Test code file + * @v line Test code line + */ +void pubkey_okx ( struct pubkey_test *test, const char *file, + unsigned int line ) { + struct pubkey_algorithm *pubkey = test->pubkey; + uint8_t private_ctx[pubkey->ctxsize]; + uint8_t public_ctx[pubkey->ctxsize]; + size_t max_len; + + /* Initialize contexts */ + okx ( pubkey_init ( pubkey, private_ctx, &test->private ) == 0, + file, line ); + okx ( pubkey_init ( pubkey, public_ctx, &test->public ) == 0, + file, line ); + max_len = pubkey_max_len ( pubkey, private_ctx ); + + /* Test decrypting with private key to obtain known plaintext */ + { + uint8_t decrypted[max_len]; + int decrypted_len; + + decrypted_len = pubkey_decrypt ( pubkey, private_ctx, + test->ciphertext, + test->ciphertext_len, + decrypted ); + okx ( decrypted_len == ( ( int ) test->plaintext_len ), + file, line ); + okx ( memcmp ( decrypted, test->plaintext, + test->plaintext_len ) == 0, file, line ); + } + + /* Test encrypting with private key and decrypting with public key */ + { + uint8_t encrypted[max_len]; + uint8_t decrypted[max_len]; + int encrypted_len; + int decrypted_len; + + encrypted_len = pubkey_encrypt ( pubkey, private_ctx, + test->plaintext, + test->plaintext_len, + encrypted ); + okx ( encrypted_len >= 0, file, line ); + decrypted_len = pubkey_decrypt ( pubkey, public_ctx, + encrypted, encrypted_len, + decrypted ); + okx ( decrypted_len == ( ( int ) test->plaintext_len ), + file, line ); + okx ( memcmp ( decrypted, test->plaintext, + test->plaintext_len ) == 0, file, line ); + } + + /* Test encrypting with public key and decrypting with private key */ + { + uint8_t encrypted[max_len]; + uint8_t decrypted[max_len]; + int encrypted_len; + int decrypted_len; + + encrypted_len = pubkey_encrypt ( pubkey, public_ctx, + test->plaintext, + test->plaintext_len, + encrypted ); + okx ( encrypted_len >= 0, file, line ); + decrypted_len = pubkey_decrypt ( pubkey, private_ctx, + encrypted, encrypted_len, + decrypted ); + okx ( decrypted_len == ( ( int ) test->plaintext_len ), + file, line ); + okx ( memcmp ( decrypted, test->plaintext, + test->plaintext_len ) == 0, file, line ); + } + + /* Free contexts */ + pubkey_final ( pubkey, public_ctx ); + pubkey_final ( pubkey, private_ctx ); +} + +/** + * Report public key signature test result + * + * @v test Public key signature test + * @v file Test code file + * @v line Test code line + */ +void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file, + unsigned int line ) { + struct pubkey_algorithm *pubkey = test->pubkey; + struct digest_algorithm *digest = test->digest; + uint8_t private_ctx[pubkey->ctxsize]; + uint8_t public_ctx[pubkey->ctxsize]; + uint8_t digestctx[digest->ctxsize ]; + uint8_t digestout[digest->digestsize]; + size_t max_len; + + /* Initialize contexts */ + okx ( pubkey_init ( pubkey, private_ctx, &test->private ) == 0, + file, line ); + okx ( pubkey_init ( pubkey, public_ctx, &test->public ) == 0, + file, line ); + max_len = pubkey_max_len ( pubkey, private_ctx ); + + /* Construct digest over plaintext */ + digest_init ( digest, digestctx ); + digest_update ( digest, digestctx, test->plaintext, + test->plaintext_len ); + digest_final ( digest, digestctx, digestout ); + + /* Test signing using private key */ + { + uint8_t signature[max_len]; + int signature_len; + + signature_len = pubkey_sign ( pubkey, private_ctx, digest, + digestout, signature ); + okx ( signature_len == ( ( int ) test->signature_len ), + file, line ); + okx ( memcmp ( signature, test->signature, + test->signature_len ) == 0, file, line ); + } + + /* Test verification using public key */ + okx ( pubkey_verify ( pubkey, public_ctx, digest, digestout, + test->signature, test->signature_len ) == 0, + file, line ); + + /* Test verification failure of modified signature */ + { + uint8_t bad[test->signature_len]; + + memcpy ( bad, test->signature, test->signature_len ); + bad[ test->signature_len / 2 ] ^= 0x40; + okx ( pubkey_verify ( pubkey, public_ctx, digest, digestout, + bad, sizeof ( bad ) ) != 0, file, line ); + } + + /* Free contexts */ + pubkey_final ( pubkey, public_ctx ); + pubkey_final ( pubkey, private_ctx ); +} |