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
24FILE_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/** Random data input */
44static const uint8_t *pubkey_random;
45
46/** Length of random data input */
47static size_t pubkey_random_len;
48
49/**
50 * Get random data input
51 *
52 * @v data Output buffer
53 * @v len Length of output buffer
54 * @ret rc Return status code
55 */
56int pubkey_test_get_random ( void *data, size_t len ) {
57
58 /* Sanity check */
60
61 /* Return random data */
63
64 /* Consume random data */
67
68 return 0;
69}
70
71/**
72 * Report a public key encryption test result
73 *
74 * @v test Public key encryption/decryption test
75 * @v file Test code file
76 * @v line Test code line
77 */
79 const char *file, unsigned int line ) {
80 struct pubkey_algorithm *pubkey = test->key->pubkey;
81 struct asn1_builder ciphertext;
82
83 /* Sanity checks */
84 okx ( test->key->public.len != 0, file, line );
85 okx ( test->ciphertext.len != 0, file, line );
86
87 /* Test encrypting with public key to obtain known ciphertext */
88 ciphertext.data = NULL;
89 ciphertext.len = 0;
90 pubkey_random = test->random;
91 pubkey_random_len = test->random_len;
92 okx ( pubkey_encrypt ( pubkey, &test->key->public, &test->plaintext,
93 &ciphertext ) == 0, file, line );
94 okx ( pubkey_random_len == 0, file, line );
95 okx ( asn1_compare ( asn1_built ( &ciphertext ),
96 &test->ciphertext ) == 0, file, line );
97 free ( ciphertext.data );
98}
99
100/**
101 * Report a public key decryption test result
102 *
103 * @v test Public key encryption/decryption test
104 * @v file Test code file
105 * @v line Test code line
106 */
108 const char *file, unsigned int line ) {
109 struct pubkey_algorithm *pubkey = test->key->pubkey;
110 struct asn1_builder plaintext;
111
112 /* Sanity checks */
113 okx ( test->key->private.len != 0, file, line );
114 okx ( test->ciphertext.len != 0, file, line );
115
116 /* Test decrypting with private key to obtain known plaintext */
117 plaintext.data = NULL;
118 plaintext.len = 0;
119 okx ( pubkey_decrypt ( pubkey, &test->key->private, &test->ciphertext,
120 &plaintext ) == 0, file, line );
121 okx ( asn1_compare ( asn1_built ( &plaintext ),
122 &test->plaintext ) == 0, file, line );
123 free ( plaintext.data );
124}
125
126/**
127 * Report a public key encryption failure test result
128 *
129 * @v test Public key encryption/decryption test
130 * @v file Test code file
131 * @v line Test code line
132 */
134 const char *file, unsigned int line ) {
135 struct pubkey_algorithm *pubkey = test->key->pubkey;
136 struct asn1_builder ciphertext;
137
138 /* Test encrypting with public key */
139 ciphertext.data = NULL;
140 ciphertext.len = 0;
141 pubkey_random = test->random;
142 pubkey_random_len = test->random_len;
143 okx ( pubkey_encrypt ( pubkey, &test->key->public, &test->plaintext,
144 &ciphertext ) != 0, file, line );
145 free ( ciphertext.data );
146}
147
148/**
149 * Report a public key decryption failure test result
150 *
151 * @v test Public key encryption/decryption test
152 * @v file Test code file
153 * @v line Test code line
154 */
156 const char *file, unsigned int line ) {
157 struct pubkey_algorithm *pubkey = test->key->pubkey;
158 struct asn1_builder plaintext;
159
160 /* Test decrypting with private key to obtain known plaintext */
161 plaintext.data = NULL;
162 plaintext.len = 0;
163 okx ( pubkey_decrypt ( pubkey, &test->key->private, &test->ciphertext,
164 &plaintext ) != 0, file, line );
165 free ( plaintext.data );
166}
167
168/**
169 * Report a public key encryption and decryption test result
170 *
171 * @v test Public key encryption/decryption test
172 * @v file Test code file
173 * @v line Test code line
174 */
176 const char *file, unsigned int line ) {
177 struct pubkey_algorithm *pubkey = test->key->pubkey;
178 struct asn1_builder plaintext;
179 struct asn1_builder ciphertext;
180
181 /* Sanity checks */
182 okx ( test->key->private.len != 0, file, line );
183 okx ( test->key->public.len != 0, file, line );
184 okx ( test->ciphertext.len != 0, file, line );
185
186 /* Test key matching */
187 okx ( pubkey_match ( pubkey, &test->key->private,
188 &test->key->public ) == 0, file, line );
189
190 /* Test encrypting with public key to obtain known ciphertext */
191 pubkey_encrypt_okx ( test, file, line );
192
193 /* Test decrypting with private key to obtain known plaintext */
194 pubkey_decrypt_okx ( test, file, line );
195
196 /* Test encrypting with private key and decrypting with public key */
197 ciphertext.data = NULL;
198 ciphertext.len = 0;
199 plaintext.data = NULL;
200 plaintext.len = 0;
201 pubkey_random = test->random;
202 pubkey_random_len = test->random_len;
203 okx ( pubkey_encrypt ( pubkey, &test->key->private, &test->plaintext,
204 &ciphertext ) == 0, file, line );
205 okx ( pubkey_random_len == 0, file, line );
206 okx ( pubkey_decrypt ( pubkey, &test->key->public,
207 asn1_built ( &ciphertext ),
208 &plaintext ) == 0, file, line );
209 okx ( asn1_compare ( asn1_built ( &plaintext ),
210 &test->plaintext ) == 0, file, line );
211 free ( ciphertext.data );
212 free ( plaintext.data );
213
214 /* Test encrypting with public key and decrypting with private key */
215 ciphertext.data = NULL;
216 ciphertext.len = 0;
217 plaintext.data = NULL;
218 plaintext.len = 0;
219 pubkey_random = test->random;
220 pubkey_random_len = test->random_len;
221 okx ( pubkey_encrypt ( pubkey, &test->key->public, &test->plaintext,
222 &ciphertext ) == 0, file, line );
223 okx ( pubkey_random_len == 0, file, line );
224 okx ( pubkey_decrypt ( pubkey, &test->key->private,
225 asn1_built ( &ciphertext ),
226 &plaintext ) == 0, file, line );
227 okx ( asn1_compare ( asn1_built ( &plaintext ),
228 &test->plaintext ) == 0, file, line );
229 free ( ciphertext.data );
230 free ( plaintext.data );
231}
232
233/**
234 * Report a public key signature test result
235 *
236 * @v test Public key signature/verification test
237 * @v file Test code file
238 * @v line Test code line
239 */
241 const char *file, unsigned int line ) {
242 struct pubkey_algorithm *pubkey = test->key->pubkey;
243 struct digest_algorithm *digest = test->digest;
244 uint8_t digestctx[digest->ctxsize];
245 uint8_t digestout[digest->digestsize];
246 struct asn1_builder builder = { NULL, 0 };
247
248 /* Sanity checks */
249 okx ( test->key->private.len != 0, file, line );
250 okx ( test->key->public.len != 0, file, line );
251 okx ( test->signature.len != 0, file, line );
252
253 /* Test key matching */
254 okx ( pubkey_match ( pubkey, &test->key->private,
255 &test->key->public ) == 0, file, line );
256
257 /* Construct digest over plaintext */
258 digest_init ( digest, digestctx );
259 digest_update ( digest, digestctx, test->plaintext,
260 test->plaintext_len );
261 digest_final ( digest, digestctx, digestout );
262
263 /* Test signing using private key */
264 pubkey_random = test->random;
265 pubkey_random_len = test->random_len;
266 okx ( pubkey_sign ( pubkey, &test->key->private, digest, digestout,
267 &builder ) == 0, file, line );
268 okx ( pubkey_random_len == 0, file, line );
269 okx ( builder.len != 0, file, line );
270 okx ( asn1_compare ( asn1_built ( &builder ), &test->signature ) == 0,
271 file, line );
272
273 /* Test verification of constructed signature */
274 okx ( pubkey_verify ( pubkey, &test->key->public, digest, digestout,
275 asn1_built ( &builder ) ) == 0, file, line );
276
277 /* Free signature */
278 free ( builder.data );
279}
280
281/**
282 * Report a public key verification test result
283 *
284 * @v test Public key signature/verification test
285 * @v file Test code file
286 * @v line Test code line
287 */
289 const char *file, unsigned int line ) {
290 struct pubkey_algorithm *pubkey = test->key->pubkey;
291 struct digest_algorithm *digest = test->digest;
292 uint8_t digestctx[digest->ctxsize];
293 uint8_t digestout[digest->digestsize];
294 uint8_t signature[test->signature.len];
295 struct asn1_cursor cursor = { signature, sizeof ( signature ) };
296 uint8_t *bad;
297
298 /* Sanity checks */
299 okx ( test->key->public.len != 0, file, line );
300 okx ( test->signature.len != 0, file, line );
301
302 /* Construct digest over plaintext */
303 digest_init ( digest, digestctx );
304 digest_update ( digest, digestctx, test->plaintext,
305 test->plaintext_len );
306 digest_final ( digest, digestctx, digestout );
307
308 /* Test verification using public key */
309 okx ( pubkey_verify ( pubkey, &test->key->public, digest, digestout,
310 &test->signature ) == 0, file, line );
311
312 /* Test verification failure of modified signature */
313 memcpy ( signature, test->signature.data, sizeof ( signature ) );
314 bad = ( signature + ( sizeof ( signature ) / 2 ) );
315 *bad ^= 0x40;
316 okx ( pubkey_verify ( pubkey, &test->key->public, digest, digestout,
317 &cursor ) != 0, file, line );
318 *bad ^= 0x40;
319 okx ( pubkey_verify ( pubkey, &test->key->public, digest, digestout,
320 &cursor ) == 0, file, line );
321}
322
323/**
324 * Report a public key verification failure test result
325 *
326 * @v test Public key signature/verification test
327 * @v file Test code file
328 * @v line Test code line
329 */
331 const char *file, unsigned int line ) {
332 struct pubkey_algorithm *pubkey = test->key->pubkey;
333 struct digest_algorithm *digest = test->digest;
334 uint8_t digestctx[digest->ctxsize];
335 uint8_t digestout[digest->digestsize];
336
337 /* Construct digest over plaintext */
338 digest_init ( digest, digestctx );
339 digest_update ( digest, digestctx, test->plaintext,
340 test->plaintext_len );
341 digest_final ( digest, digestctx, digestout );
342
343 /* Test verification using public key */
344 okx ( pubkey_verify ( pubkey, &test->key->public, digest, digestout,
345 &test->signature ) != 0, file, line );
346}
347
348/**
349 * Report a public key signature and verification test result
350 *
351 * @v test Public key signature/verification test
352 * @v file Test code file
353 * @v line Test code line
354 */
356 const char *file, unsigned int line ) {
357 struct pubkey_algorithm *pubkey = test->key->pubkey;
358
359 /* Sanity checks */
360 okx ( test->key->private.len != 0, file, line );
361 okx ( test->key->public.len != 0, file, line );
362 okx ( test->signature.len != 0, file, line );
363
364 /* Test key matching */
365 okx ( pubkey_match ( pubkey, &test->key->private,
366 &test->key->public ) == 0, file, line );
367
368 /* Test signature */
369 pubkey_sign_okx ( test, file, line );
370
371 /* Test verification */
372 pubkey_verify_okx ( test, file, line );
373}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
u8 signature
CPU signature.
Definition CIB_PRM.h:7
unsigned char uint8_t
Definition stdint.h:10
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:566
static struct asn1_cursor * asn1_built(struct asn1_builder *builder)
Get cursor for built object.
Definition asn1.h:518
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int test
Definition epic100.c:73
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
Cryptographic API.
static int pubkey_match(struct pubkey_algorithm *pubkey, const struct asn1_cursor *private_key, const struct asn1_cursor *public_key)
Definition crypto.h:390
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
static int pubkey_encrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *plaintext, struct asn1_builder *ciphertext)
Definition crypto.h:362
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition crypto.h:383
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299
static int pubkey_decrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *ciphertext, struct asn1_builder *plaintext)
Definition crypto.h:369
static int pubkey_sign(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
Definition crypto.h:376
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void pubkey_encrypt_fail_okx(struct pubkey_encryption_test *test, const char *file, unsigned int line)
Report a public key encryption failure test result.
void pubkey_sign_okx(struct pubkey_signature_test *test, const char *file, unsigned int line)
Report a public key signature test result.
void pubkey_encrypt_decrypt_okx(struct pubkey_encryption_test *test, const char *file, unsigned int line)
Report a public key encryption and decryption test result.
void pubkey_decrypt_fail_okx(struct pubkey_encryption_test *test, const char *file, unsigned int line)
Report a public key decryption failure test result.
void pubkey_sign_verify_okx(struct pubkey_signature_test *test, const char *file, unsigned int line)
Report a public key signature and verification test result.
static size_t pubkey_random_len
Length of random data input.
Definition pubkey_test.c:47
void pubkey_decrypt_okx(struct pubkey_encryption_test *test, const char *file, unsigned int line)
Report a public key decryption test result.
void pubkey_verify_okx(struct pubkey_signature_test *test, const char *file, unsigned int line)
Report a public key verification test result.
void pubkey_encrypt_okx(struct pubkey_encryption_test *test, const char *file, unsigned int line)
Report a public key encryption test result.
Definition pubkey_test.c:78
int pubkey_test_get_random(void *data, size_t len)
Get random data input.
Definition pubkey_test.c:56
static const uint8_t * pubkey_random
Random data input.
Definition pubkey_test.c:44
void pubkey_verify_fail_okx(struct pubkey_signature_test *test, const char *file, unsigned int line)
Report a public key verification failure test result.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38
An ASN.1 object cursor.
Definition asn1.h:21
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
A public key algorithm.
Definition crypto.h:142
A public-key encryption/decryption test.
Definition pubkey_test.h:21
A public-key signature/verification test.
Definition pubkey_test.h:35
Self-test infrastructure.
#define okx(success, file, line)
Report test result.
Definition test.h:44