iPXE
pubkey_test.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * Public key self-tests
29  *
30  */
31 
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34 
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <assert.h>
39 #include <ipxe/crypto.h>
40 #include <ipxe/test.h>
41 #include "pubkey_test.h"
42 
43 /**
44  * Report public key encryption and decryption test result
45  *
46  * @v test Public key encryption and decryption test
47  * @v file Test code file
48  * @v line Test code line
49  */
50 void pubkey_okx ( struct pubkey_test *test, const char *file,
51  unsigned int line ) {
52  struct pubkey_algorithm *pubkey = test->pubkey;
53  size_t max_len = pubkey_max_len ( pubkey, &test->private );
54  uint8_t encrypted[max_len];
55  uint8_t decrypted[max_len];
56  int encrypted_len;
57  int decrypted_len;
58 
59  /* Test decrypting with private key to obtain known plaintext */
60  decrypted_len = pubkey_decrypt ( pubkey, &test->private,
61  test->ciphertext, test->ciphertext_len,
62  decrypted );
63  okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
64  okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
65  file, line );
66 
67  /* Test encrypting with private key and decrypting with public key */
68  encrypted_len = pubkey_encrypt ( pubkey, &test->private,
69  test->plaintext, test->plaintext_len,
70  encrypted );
71  okx ( encrypted_len >= 0, file, line );
72  decrypted_len = pubkey_decrypt ( pubkey, &test->public, encrypted,
73  encrypted_len, decrypted );
74  okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
75  okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
76  file, line );
77 
78  /* Test encrypting with public key and decrypting with private key */
79  encrypted_len = pubkey_encrypt ( pubkey, &test->public,
80  test->plaintext, test->plaintext_len,
81  encrypted );
82  okx ( encrypted_len >= 0, file, line );
83  decrypted_len = pubkey_decrypt ( pubkey, &test->private, encrypted,
84  encrypted_len, decrypted );
85  okx ( decrypted_len == ( ( int ) test->plaintext_len ), file, line );
86  okx ( memcmp ( decrypted, test->plaintext, test->plaintext_len ) == 0,
87  file, line );
88 }
89 
90 /**
91  * Report public key signature test result
92  *
93  * @v test Public key signature test
94  * @v file Test code file
95  * @v line Test code line
96  */
97 void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file,
98  unsigned int line ) {
99  struct pubkey_algorithm *pubkey = test->pubkey;
100  struct digest_algorithm *digest = test->digest;
101  size_t max_len = pubkey_max_len ( pubkey, &test->private );
102  uint8_t bad[test->signature_len];
103  uint8_t digestctx[digest->ctxsize ];
104  uint8_t digestout[digest->digestsize];
105  uint8_t signature[max_len];
106  int signature_len;
107 
108  /* Construct digest over plaintext */
109  digest_init ( digest, digestctx );
110  digest_update ( digest, digestctx, test->plaintext,
111  test->plaintext_len );
112  digest_final ( digest, digestctx, digestout );
113 
114  /* Test signing using private key */
115  signature_len = pubkey_sign ( pubkey, &test->private, digest,
116  digestout, signature );
117  okx ( signature_len == ( ( int ) test->signature_len ), file, line );
118  okx ( memcmp ( signature, test->signature, test->signature_len ) == 0,
119  file, line );
120 
121  /* Test verification using public key */
122  okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
123  test->signature, test->signature_len ) == 0,
124  file, line );
125 
126  /* Test verification failure of modified signature */
127  memcpy ( bad, test->signature, test->signature_len );
128  bad[ test->signature_len / 2 ] ^= 0x40;
129  okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
130  bad, sizeof ( bad ) ) != 0, file, line );
131 }
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition: crypto.h:206
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const void *signature, size_t signature_len)
Definition: crypto.h:294
void pubkey_okx(struct pubkey_test *test, const char *file, unsigned int line)
Report public key encryption and decryption test result.
Definition: pubkey_test.c:50
static int pubkey_encrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const void *data, size_t len, void *out)
Definition: crypto.h:275
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition: crypto.h:212
A public-key encryption and decryption test.
Definition: pubkey_test.h:11
Self-test infrastructure.
static int pubkey_decrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const void *data, size_t len, void *out)
Definition: crypto.h:281
Cryptographic API.
void pubkey_sign_okx(struct pubkey_sign_test *test, const char *file, unsigned int line)
Report public key signature test result.
Definition: pubkey_test.c:97
A public-key signature test.
Definition: pubkey_test.h:34
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define okx(success, file, line)
Report test result.
Definition: test.h:44
Assertions.
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition: crypto.h:201
unsigned char uint8_t
Definition: stdint.h:10
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
size_t ctxsize
Context size.
Definition: crypto.h:22
size_t digestsize
Digest size.
Definition: crypto.h:26
A message digest algorithm.
Definition: crypto.h:18
static size_t pubkey_max_len(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key)
Definition: crypto.h:269
static int pubkey_sign(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, void *signature)
Definition: crypto.h:287
u8 signature
CPU signature.
Definition: CIB_PRM.h:35
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
String functions.
A public key algorithm.
Definition: crypto.h:121
size_t(* max_len)(const struct asn1_cursor *key)
Calculate maximum output length.
Definition: crypto.h:129
static int test
Definition: epic100.c:73