aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/pubkey_test.c
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2024-08-18 20:01:08 +0100
committerMichael Brown <mcb30@ipxe.org>2024-08-18 23:51:43 +0100
commit633f4f362dbdf1f3177ee0f6b5b63085af7c1be5 (patch)
tree03685b30c5c89436a9241da52148af21a9f58d68 /src/tests/pubkey_test.c
parent53f089b723e16eecb4fd2e2a59b74b3932431b30 (diff)
downloadipxe-633f4f362dbdf1f3177ee0f6b5b63085af7c1be5.tar.gz
[test] Generalise public-key algorithm tests and use okx()
Generalise the existing support for performing RSA public-key encryption, decryption, signature, and verification tests, and update the code to use okx() for neater reporting of test results. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/tests/pubkey_test.c')
-rw-r--r--src/tests/pubkey_test.c187
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 );
+}