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 public key encryption and decryption test result
73 *
74 * @v test Public key encryption and decryption test
75 * @v file Test code file
76 * @v line Test code line
77 */
78void pubkey_okx ( struct pubkey_test *test, const char *file,
79 unsigned int line ) {
80 struct pubkey_algorithm *pubkey = test->pubkey;
81 struct asn1_builder plaintext;
82 struct asn1_builder ciphertext;
83
84 /* Test key matching */
85 okx ( pubkey_match ( pubkey, &test->private, &test->public ) == 0,
86 file, line );
87
88 /* Test encrypting with public key to obtain known ciphertext */
89 ciphertext.data = NULL;
90 ciphertext.len = 0;
91 pubkey_random = test->random;
92 pubkey_random_len = test->random_len;
93 okx ( pubkey_encrypt ( pubkey, &test->public, &test->plaintext,
94 &ciphertext ) == 0, file, line );
95 okx ( pubkey_random_len == 0, file, line );
96 okx ( asn1_compare ( asn1_built ( &ciphertext ),
97 &test->ciphertext ) == 0, file, line );
98 free ( ciphertext.data );
99
100 /* Test decrypting with private key to obtain known plaintext */
101 plaintext.data = NULL;
102 plaintext.len = 0;
103 okx ( pubkey_decrypt ( pubkey, &test->private, &test->ciphertext,
104 &plaintext ) == 0, file, line );
105 okx ( asn1_compare ( asn1_built ( &plaintext ),
106 &test->plaintext ) == 0, file, line );
107 free ( plaintext.data );
108
109 /* Test encrypting with private key and decrypting with public key */
110 ciphertext.data = NULL;
111 ciphertext.len = 0;
112 plaintext.data = NULL;
113 plaintext.len = 0;
114 pubkey_random = test->random;
115 pubkey_random_len = test->random_len;
116 okx ( pubkey_encrypt ( pubkey, &test->private, &test->plaintext,
117 &ciphertext ) == 0, file, line );
118 okx ( pubkey_random_len == 0, file, line );
119 okx ( pubkey_decrypt ( pubkey, &test->public,
120 asn1_built ( &ciphertext ),
121 &plaintext ) == 0, file, line );
122 okx ( asn1_compare ( asn1_built ( &plaintext ),
123 &test->plaintext ) == 0, file, line );
124 free ( ciphertext.data );
125 free ( plaintext.data );
126
127 /* Test encrypting with public key and decrypting with private key */
128 ciphertext.data = NULL;
129 ciphertext.len = 0;
130 plaintext.data = NULL;
131 plaintext.len = 0;
132 pubkey_random = test->random;
133 pubkey_random_len = test->random_len;
134 okx ( pubkey_encrypt ( pubkey, &test->public, &test->plaintext,
135 &ciphertext ) == 0, file, line );
136 okx ( pubkey_random_len == 0, file, line );
137 okx ( pubkey_decrypt ( pubkey, &test->private,
138 asn1_built ( &ciphertext ),
139 &plaintext ) == 0, file, line );
140 okx ( asn1_compare ( asn1_built ( &plaintext ),
141 &test->plaintext ) == 0, file, line );
142 free ( ciphertext.data );
143 free ( plaintext.data );
144}
145
146/**
147 * Report public key signature test result
148 *
149 * @v test Public key signature test
150 * @v file Test code file
151 * @v line Test code line
152 */
153void pubkey_sign_okx ( struct pubkey_sign_test *test, const char *file,
154 unsigned int line ) {
155 struct pubkey_algorithm *pubkey = test->pubkey;
156 struct digest_algorithm *digest = test->digest;
157 uint8_t digestctx[digest->ctxsize];
158 uint8_t digestout[digest->digestsize];
159 uint8_t signature[test->signature.len];
160 struct asn1_cursor cursor = { signature, sizeof ( signature ) };
161 struct asn1_builder builder = { NULL, 0 };
162 uint8_t *bad;
163
164 /* Test key matching */
165 okx ( pubkey_match ( pubkey, &test->private, &test->public ) == 0,
166 file, line );
167
168 /* Construct digest over plaintext */
169 digest_init ( digest, digestctx );
170 digest_update ( digest, digestctx, test->plaintext,
171 test->plaintext_len );
172 digest_final ( digest, digestctx, digestout );
173
174 /* Test verification using public key */
175 okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
176 &test->signature ) == 0, file, line );
177
178 /* Test verification failure of modified signature */
179 memcpy ( signature, test->signature.data, sizeof ( signature ) );
180 bad = ( signature + ( sizeof ( signature ) / 2 ) );
181 *bad ^= 0x40;
182 okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
183 &cursor ) != 0, file, line );
184 *bad ^= 0x40;
185 okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
186 &cursor ) == 0, file, line );
187
188 /* Test signing using private key */
189 pubkey_random = test->random;
190 pubkey_random_len = test->random_len;
191 okx ( pubkey_sign ( pubkey, &test->private, digest, digestout,
192 &builder ) == 0, file, line );
193 okx ( pubkey_random_len == 0, file, line );
194 okx ( builder.len != 0, file, line );
195 okx ( asn1_compare ( asn1_built ( &builder ), &test->signature ) == 0,
196 file, line );
197
198 /* Test verification of constructed signature */
199 okx ( pubkey_verify ( pubkey, &test->public, digest, digestout,
200 asn1_built ( &builder ) ) == 0, file, line );
201
202 /* Free signature */
203 free ( builder.data );
204}
#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:528
static struct asn1_cursor * asn1_built(struct asn1_builder *builder)
Get cursor for built object.
Definition asn1.h:499
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
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_okx(struct pubkey_test *test, const char *file, unsigned int line)
Report public key encryption and decryption test result.
Definition pubkey_test.c:78
void pubkey_sign_okx(struct pubkey_sign_test *test, const char *file, unsigned int line)
Report public key signature test result.
static size_t pubkey_random_len
Length of random data input.
Definition pubkey_test.c:47
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
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 signature test.
Definition pubkey_test.h:29
A public-key encryption and decryption test.
Definition pubkey_test.h:11
Self-test infrastructure.
#define okx(success, file, line)
Report test result.
Definition test.h:44