]>
Commit | Line | Data |
---|---|---|
e76a6962 | 1 | /* |
a28d06f3 | 2 | * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. |
e76a6962 RL |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | /* | |
11 | * This program tests the following known key type specific function against | |
12 | * the corresponding OSSL_ENCODER implementation: | |
13 | * | |
14 | * - i2d_{TYPE}PrivateKey() | |
15 | * - i2d_{TYPE}PublicKey(), | |
16 | * - i2d_{TYPE}params(), | |
17 | * - i2d_{TYPE}_PUBKEY(), | |
18 | * - PEM_write_bio_{TYPE}PrivateKey() | |
19 | * - PEM_write_bio_{TYPE}PublicKey() | |
20 | * - PEM_write_bio_{TYPE}params() | |
21 | * - PEM_write_bio_{TYPE}_PUBKEY() | |
22 | * | |
23 | * as well as the following functions against the corresponding OSSL_DECODER | |
24 | * implementation. | |
25 | * | |
26 | * - d2i_{TYPE}PrivateKey() | |
27 | * - d2i_{TYPE}PublicKey(), | |
28 | * - d2i_{TYPE}params(), | |
29 | * - d2i_{TYPE}_PUBKEY(), | |
30 | * - PEM_read_bio_{TYPE}PrivateKey() | |
31 | * - PEM_read_bio_{TYPE}PublicKey() | |
32 | * - PEM_read_bio_{TYPE}params() | |
33 | * - PEM_read_bio_{TYPE}_PUBKEY() | |
34 | */ | |
35 | ||
36 | #include <stdlib.h> | |
37 | #include <string.h> | |
d7e498ac RL |
38 | |
39 | /* | |
40 | * We test deprecated functions, so we need to suppress deprecation warnings. | |
41 | */ | |
42 | #define OPENSSL_SUPPRESS_DEPRECATED | |
43 | ||
e76a6962 RL |
44 | #include <openssl/bio.h> |
45 | #include <openssl/evp.h> | |
46 | #include <openssl/asn1.h> | |
47 | #include <openssl/pem.h> | |
48 | #include <openssl/params.h> | |
49 | #include <openssl/encoder.h> | |
50 | #include <openssl/decoder.h> | |
51 | #include <openssl/dh.h> | |
52 | #include <openssl/dsa.h> | |
53 | #ifndef OPENSSL_NO_DEPRECATED_3_0 | |
54 | # include <openssl/rsa.h> | |
55 | #endif | |
56 | #include "internal/nelem.h" | |
57 | #include "crypto/evp.h" | |
58 | ||
59 | #include "testutil.h" | |
60 | ||
61 | typedef int PEM_write_bio_of_void_protected(BIO *out, void *obj, | |
62 | const EVP_CIPHER *enc, | |
63 | unsigned char *kstr, int klen, | |
64 | pem_password_cb *cb, void *u); | |
65 | typedef int PEM_write_bio_of_void_unprotected(BIO *out, void *obj); | |
66 | typedef void *PEM_read_bio_of_void(BIO *out, void **obj, | |
67 | pem_password_cb *cb, void *u); | |
68 | typedef int EVP_PKEY_print_fn(BIO *out, const EVP_PKEY *pkey, | |
69 | int indent, ASN1_PCTX *pctx); | |
70 | typedef int EVP_PKEY_eq_fn(const EVP_PKEY *a, const EVP_PKEY *b); | |
71 | ||
72 | static struct test_stanza_st { | |
73 | const char *keytype; | |
74 | const char *structure[2]; | |
75 | int evp_type; | |
76 | ||
77 | i2d_of_void *i2d_PrivateKey; | |
78 | i2d_of_void *i2d_PublicKey; | |
79 | i2d_of_void *i2d_params; | |
80 | i2d_of_void *i2d_PUBKEY; | |
81 | PEM_write_bio_of_void_protected *pem_write_bio_PrivateKey; | |
82 | PEM_write_bio_of_void_unprotected *pem_write_bio_PublicKey; | |
83 | PEM_write_bio_of_void_unprotected *pem_write_bio_params; | |
84 | PEM_write_bio_of_void_unprotected *pem_write_bio_PUBKEY; | |
85 | ||
86 | d2i_of_void *d2i_PrivateKey; | |
87 | d2i_of_void *d2i_PublicKey; | |
88 | d2i_of_void *d2i_params; | |
89 | d2i_of_void *d2i_PUBKEY; | |
90 | PEM_read_bio_of_void *pem_read_bio_PrivateKey; | |
91 | PEM_read_bio_of_void *pem_read_bio_PublicKey; | |
92 | PEM_read_bio_of_void *pem_read_bio_params; | |
93 | PEM_read_bio_of_void *pem_read_bio_PUBKEY; | |
94 | } test_stanzas[] = { | |
95 | #ifndef OPENSSL_NO_DH | |
96 | { "DH", { "DH", "type-specific" }, EVP_PKEY_DH, | |
97 | NULL, /* No i2d_DHPrivateKey */ | |
98 | NULL, /* No i2d_DHPublicKey */ | |
99 | (i2d_of_void *)i2d_DHparams, | |
100 | NULL, /* No i2d_DH_PUBKEY */ | |
101 | NULL, /* No PEM_write_bio_DHPrivateKey */ | |
102 | NULL, /* No PEM_write_bio_DHPublicKey */ | |
103 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DHparams, | |
104 | NULL, /* No PEM_write_bio_DH_PUBKEY */ | |
105 | NULL, /* No d2i_DHPrivateKey */ | |
106 | NULL, /* No d2i_DHPublicKey */ | |
107 | (d2i_of_void *)d2i_DHparams, | |
108 | NULL, /* No d2i_DH_PUBKEY */ | |
109 | NULL, /* No PEM_read_bio_DHPrivateKey */ | |
110 | NULL, /* No PEM_read_bio_DHPublicKey */ | |
111 | (PEM_read_bio_of_void *)PEM_read_bio_DHparams, | |
112 | NULL }, /* No PEM_read_bio_DH_PUBKEY */ | |
113 | { "DHX", { "DHX", "type-specific" }, EVP_PKEY_DHX, | |
114 | NULL, /* No i2d_DHxPrivateKey */ | |
115 | NULL, /* No i2d_DHxPublicKey */ | |
116 | (i2d_of_void *)i2d_DHxparams, | |
117 | NULL, /* No i2d_DHx_PUBKEY */ | |
118 | NULL, /* No PEM_write_bio_DHxPrivateKey */ | |
119 | NULL, /* No PEM_write_bio_DHxPublicKey */ | |
120 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DHxparams, | |
121 | NULL, /* No PEM_write_bio_DHx_PUBKEY */ | |
122 | NULL, /* No d2i_DHxPrivateKey */ | |
123 | NULL, /* No d2i_DHxPublicKey */ | |
124 | (d2i_of_void *)d2i_DHxparams, | |
125 | NULL, /* No d2i_DHx_PUBKEY */ | |
126 | NULL, /* No PEM_read_bio_DHxPrivateKey */ | |
127 | NULL, /* No PEM_read_bio_DHxPublicKey */ | |
128 | NULL, /* No PEM_read_bio_DHxparams */ | |
129 | NULL }, /* No PEM_read_bio_DHx_PUBKEY */ | |
130 | #endif | |
131 | #ifndef OPENSSL_NO_DSA | |
132 | { "DSA", { "DSA", "type-specific" }, EVP_PKEY_DSA, | |
133 | (i2d_of_void *)i2d_DSAPrivateKey, | |
134 | (i2d_of_void *)i2d_DSAPublicKey, | |
135 | (i2d_of_void *)i2d_DSAparams, | |
136 | (i2d_of_void *)i2d_DSA_PUBKEY, | |
137 | (PEM_write_bio_of_void_protected *)PEM_write_bio_DSAPrivateKey, | |
138 | NULL, /* No PEM_write_bio_DSAPublicKey */ | |
139 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DSAparams, | |
140 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DSA_PUBKEY, | |
141 | (d2i_of_void *)d2i_DSAPrivateKey, | |
142 | (d2i_of_void *)d2i_DSAPublicKey, | |
143 | (d2i_of_void *)d2i_DSAparams, | |
144 | (d2i_of_void *)d2i_DSA_PUBKEY, | |
145 | (PEM_read_bio_of_void *)PEM_read_bio_DSAPrivateKey, | |
146 | NULL, /* No PEM_write_bio_DSAPublicKey */ | |
147 | (PEM_read_bio_of_void *)PEM_read_bio_DSAparams, | |
148 | (PEM_read_bio_of_void *)PEM_read_bio_DSA_PUBKEY }, | |
149 | #endif | |
150 | #ifndef OPENSSL_NO_EC | |
151 | { "EC", { "EC", "type-specific" }, EVP_PKEY_EC, | |
152 | (i2d_of_void *)i2d_ECPrivateKey, | |
153 | NULL, /* No i2d_ECPublicKey */ | |
154 | (i2d_of_void *)i2d_ECParameters, | |
155 | (i2d_of_void *)i2d_EC_PUBKEY, | |
156 | (PEM_write_bio_of_void_protected *)PEM_write_bio_ECPrivateKey, | |
157 | NULL, /* No PEM_write_bio_ECPublicKey */ | |
158 | NULL, /* No PEM_write_bio_ECParameters */ | |
159 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_EC_PUBKEY, | |
160 | (d2i_of_void *)d2i_ECPrivateKey, | |
161 | NULL, /* No d2i_ECPublicKey */ | |
162 | (d2i_of_void *)d2i_ECParameters, | |
163 | (d2i_of_void *)d2i_EC_PUBKEY, | |
164 | (PEM_read_bio_of_void *)PEM_read_bio_ECPrivateKey, | |
165 | NULL, /* No PEM_read_bio_ECPublicKey */ | |
166 | NULL, /* No PEM_read_bio_ECParameters */ | |
167 | (PEM_read_bio_of_void *)PEM_read_bio_EC_PUBKEY, }, | |
168 | #endif | |
e76a6962 RL |
169 | { "RSA", { "RSA", "type-specific" }, EVP_PKEY_RSA, |
170 | (i2d_of_void *)i2d_RSAPrivateKey, | |
171 | (i2d_of_void *)i2d_RSAPublicKey, | |
172 | NULL, /* No i2d_RSAparams */ | |
173 | (i2d_of_void *)i2d_RSA_PUBKEY, | |
174 | (PEM_write_bio_of_void_protected *)PEM_write_bio_RSAPrivateKey, | |
175 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_RSAPublicKey, | |
176 | NULL, /* No PEM_write_bio_RSAparams */ | |
177 | (PEM_write_bio_of_void_unprotected *)PEM_write_bio_RSA_PUBKEY, | |
178 | (d2i_of_void *)d2i_RSAPrivateKey, | |
179 | (d2i_of_void *)d2i_RSAPublicKey, | |
180 | NULL, /* No d2i_RSAparams */ | |
181 | (d2i_of_void *)d2i_RSA_PUBKEY, | |
182 | (PEM_read_bio_of_void *)PEM_read_bio_RSAPrivateKey, | |
183 | (PEM_read_bio_of_void *)PEM_read_bio_RSAPublicKey, | |
184 | NULL, /* No PEM_read_bio_RSAparams */ | |
185 | (PEM_read_bio_of_void *)PEM_read_bio_RSA_PUBKEY } | |
e76a6962 RL |
186 | }; |
187 | ||
188 | /* | |
189 | * Keys that we're going to test with. We initialize this with the intended | |
190 | * key types, and generate the keys themselves on program setup. | |
191 | * They must all be downgradable with EVP_PKEY_get0() | |
192 | */ | |
193 | ||
194 | #ifndef OPENSSL_NO_DH | |
195 | static const OSSL_PARAM DH_params[] = { OSSL_PARAM_END }; | |
196 | static const OSSL_PARAM DHX_params[] = { OSSL_PARAM_END }; | |
197 | #endif | |
198 | #ifndef OPENSSL_NO_DSA | |
199 | static size_t qbits = 160; /* PVK only tolerates 160 Q bits */ | |
200 | static size_t pbits = 1024; /* With 160 Q bits, we MUST use 1024 P bits */ | |
201 | static const OSSL_PARAM DSA_params[] = { | |
202 | OSSL_PARAM_size_t("pbits", &pbits), | |
203 | OSSL_PARAM_size_t("qbits", &qbits), | |
204 | OSSL_PARAM_END | |
205 | }; | |
206 | #endif | |
207 | #ifndef OPENSSL_NO_EC | |
208 | static char groupname[] = "prime256v1"; | |
209 | static const OSSL_PARAM EC_params[] = { | |
210 | OSSL_PARAM_utf8_string("group", groupname, sizeof(groupname) - 1), | |
211 | OSSL_PARAM_END | |
212 | }; | |
213 | #endif | |
214 | ||
215 | static struct key_st { | |
216 | const char *keytype; | |
217 | int evp_type; | |
218 | /* non-NULL if a template EVP_PKEY must be generated first */ | |
219 | const OSSL_PARAM *template_params; | |
220 | ||
221 | EVP_PKEY *key; | |
222 | } keys[] = { | |
223 | #ifndef OPENSSL_NO_DH | |
224 | { "DH", EVP_PKEY_DH, DH_params, NULL }, | |
225 | { "DHX", EVP_PKEY_DHX, DHX_params, NULL }, | |
226 | #endif | |
227 | #ifndef OPENSSL_NO_DSA | |
228 | { "DSA", EVP_PKEY_DSA, DSA_params, NULL }, | |
229 | #endif | |
230 | #ifndef OPENSSL_NO_EC | |
231 | { "EC", EVP_PKEY_EC, EC_params, NULL }, | |
232 | #endif | |
233 | #ifndef OPENSSL_NO_DEPRECATED_3_0 | |
234 | { "RSA", EVP_PKEY_RSA, NULL, NULL }, | |
235 | #endif | |
236 | }; | |
237 | ||
238 | static EVP_PKEY *make_key(const char *type, | |
239 | const OSSL_PARAM *gen_template_params) | |
240 | { | |
241 | EVP_PKEY *template = NULL; | |
242 | EVP_PKEY *pkey = NULL; | |
243 | EVP_PKEY_CTX *ctx = NULL; | |
244 | OSSL_PARAM *gen_template_params_noconst = | |
245 | (OSSL_PARAM *)gen_template_params; | |
246 | ||
247 | if (gen_template_params != NULL | |
248 | && ((ctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL)) == NULL | |
249 | || EVP_PKEY_paramgen_init(ctx) <= 0 | |
250 | || (gen_template_params[0].key != NULL | |
251 | && EVP_PKEY_CTX_set_params(ctx, gen_template_params_noconst) <= 0) | |
252 | || EVP_PKEY_gen(ctx, &template) <= 0)) | |
253 | goto end; | |
254 | EVP_PKEY_CTX_free(ctx); | |
255 | ||
256 | /* | |
257 | * No real need to check the errors other than for the cascade | |
258 | * effect. |pkey| will simply remain NULL if something goes wrong. | |
259 | */ | |
260 | ctx = | |
261 | template != NULL | |
262 | ? EVP_PKEY_CTX_new(template, NULL) | |
263 | : EVP_PKEY_CTX_new_from_name(NULL, type, NULL); | |
264 | ||
265 | (void)(ctx != NULL | |
266 | && EVP_PKEY_keygen_init(ctx) > 0 | |
267 | && EVP_PKEY_keygen(ctx, &pkey) > 0); | |
268 | ||
269 | end: | |
270 | EVP_PKEY_free(template); | |
271 | EVP_PKEY_CTX_free(ctx); | |
272 | return pkey; | |
273 | } | |
274 | ||
275 | static struct key_st *lookup_key(const char *type) | |
276 | { | |
277 | size_t i; | |
278 | ||
279 | for (i = 0; i < OSSL_NELEM(keys); i++) { | |
280 | if (strcmp(keys[i].keytype, type) == 0) | |
281 | return &keys[i]; | |
282 | } | |
283 | return NULL; | |
284 | } | |
285 | ||
286 | static int test_membio_str_eq(BIO *bio_provided, BIO *bio_legacy) | |
287 | { | |
288 | char *str_provided = NULL, *str_legacy = NULL; | |
289 | long len_provided = BIO_get_mem_data(bio_provided, &str_provided); | |
290 | long len_legacy = BIO_get_mem_data(bio_legacy, &str_legacy); | |
291 | ||
292 | return TEST_strn2_eq(str_provided, len_provided, | |
293 | str_legacy, len_legacy); | |
294 | } | |
295 | ||
296 | static int test_protected_PEM(const char *keytype, int evp_type, | |
297 | void *legacy_key, | |
298 | PEM_write_bio_of_void_protected *pem_write_bio, | |
299 | PEM_read_bio_of_void *pem_read_bio, | |
300 | EVP_PKEY_eq_fn *evp_pkey_eq, | |
301 | EVP_PKEY_print_fn *evp_pkey_print, | |
302 | EVP_PKEY *provided_pkey, int selection, | |
303 | const char *structure) | |
304 | { | |
305 | int ok = 0; | |
306 | BIO *membio_legacy = NULL; | |
307 | BIO *membio_provided = NULL; | |
308 | OSSL_ENCODER_CTX *ectx = NULL; | |
309 | OSSL_DECODER_CTX *dctx = NULL; | |
310 | void *decoded_legacy_key = NULL; | |
311 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
312 | EVP_PKEY *decoded_provided_pkey = NULL; | |
313 | ||
314 | /* Set up the BIOs, so we have them */ | |
315 | if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem())) | |
316 | || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem()))) | |
317 | goto end; | |
318 | ||
319 | if (!TEST_ptr(ectx = | |
fe75766c TM |
320 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
321 | "PEM", structure, | |
322 | NULL)) | |
e76a6962 RL |
323 | || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided)) |
324 | || !TEST_true(pem_write_bio(membio_legacy, legacy_key, | |
325 | NULL, NULL, 0, NULL, NULL)) | |
326 | || !test_membio_str_eq(membio_provided, membio_legacy)) | |
327 | goto end; | |
328 | ||
329 | if (pem_read_bio != NULL) { | |
330 | /* Now try decoding the results and compare the resulting keys */ | |
331 | ||
332 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
333 | || !TEST_ptr(dctx = | |
fe75766c TM |
334 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
335 | "PEM", structure, | |
336 | keytype, selection, | |
337 | NULL, NULL)) | |
e76a6962 RL |
338 | || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided)) |
339 | || !TEST_ptr(decoded_legacy_key = | |
340 | pem_read_bio(membio_legacy, NULL, NULL, NULL)) | |
341 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
342 | decoded_legacy_key))) | |
343 | goto end; | |
344 | ||
345 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
346 | decoded_legacy_pkey), 0)) { | |
347 | TEST_info("decoded_provided_pkey:"); | |
348 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
349 | TEST_info("decoded_legacy_pkey:"); | |
350 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
351 | } | |
352 | } | |
353 | ok = 1; | |
354 | end: | |
355 | EVP_PKEY_free(decoded_legacy_pkey); | |
356 | EVP_PKEY_free(decoded_provided_pkey); | |
357 | OSSL_ENCODER_CTX_free(ectx); | |
358 | OSSL_DECODER_CTX_free(dctx); | |
359 | BIO_free(membio_provided); | |
360 | BIO_free(membio_legacy); | |
361 | return ok; | |
362 | } | |
363 | ||
364 | static int test_unprotected_PEM(const char *keytype, int evp_type, | |
365 | void *legacy_key, | |
366 | PEM_write_bio_of_void_unprotected *pem_write_bio, | |
367 | PEM_read_bio_of_void *pem_read_bio, | |
368 | EVP_PKEY_eq_fn *evp_pkey_eq, | |
369 | EVP_PKEY_print_fn *evp_pkey_print, | |
370 | EVP_PKEY *provided_pkey, int selection, | |
371 | const char *structure) | |
372 | { | |
373 | int ok = 0; | |
374 | BIO *membio_legacy = NULL; | |
375 | BIO *membio_provided = NULL; | |
376 | OSSL_ENCODER_CTX *ectx = NULL; | |
377 | OSSL_DECODER_CTX *dctx = NULL; | |
378 | void *decoded_legacy_key = NULL; | |
379 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
380 | EVP_PKEY *decoded_provided_pkey = NULL; | |
381 | ||
382 | /* Set up the BIOs, so we have them */ | |
383 | if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem())) | |
384 | || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem()))) | |
385 | goto end; | |
386 | ||
387 | if (!TEST_ptr(ectx = | |
fe75766c TM |
388 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
389 | "PEM", structure, | |
390 | NULL)) | |
e76a6962 RL |
391 | || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided)) |
392 | || !TEST_true(pem_write_bio(membio_legacy, legacy_key)) | |
393 | || !test_membio_str_eq(membio_provided, membio_legacy)) | |
394 | goto end; | |
395 | ||
396 | if (pem_read_bio != NULL) { | |
397 | /* Now try decoding the results and compare the resulting keys */ | |
398 | ||
399 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
400 | || !TEST_ptr(dctx = | |
fe75766c TM |
401 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
402 | "PEM", structure, | |
403 | keytype, selection, | |
404 | NULL, NULL)) | |
e76a6962 RL |
405 | || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided)) |
406 | || !TEST_ptr(decoded_legacy_key = | |
407 | pem_read_bio(membio_legacy, NULL, NULL, NULL)) | |
408 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
409 | decoded_legacy_key))) | |
410 | goto end; | |
411 | ||
412 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
413 | decoded_legacy_pkey), 0)) { | |
414 | TEST_info("decoded_provided_pkey:"); | |
415 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
416 | TEST_info("decoded_legacy_pkey:"); | |
417 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
418 | } | |
419 | } | |
420 | ok = 1; | |
421 | end: | |
422 | EVP_PKEY_free(decoded_legacy_pkey); | |
423 | EVP_PKEY_free(decoded_provided_pkey); | |
424 | OSSL_ENCODER_CTX_free(ectx); | |
425 | OSSL_DECODER_CTX_free(dctx); | |
426 | BIO_free(membio_provided); | |
427 | BIO_free(membio_legacy); | |
428 | return ok; | |
429 | } | |
430 | ||
431 | static int test_DER(const char *keytype, int evp_type, | |
432 | void *legacy_key, i2d_of_void *i2d, d2i_of_void *d2i, | |
433 | EVP_PKEY_eq_fn *evp_pkey_eq, | |
434 | EVP_PKEY_print_fn *evp_pkey_print, | |
435 | EVP_PKEY *provided_pkey, int selection, | |
436 | const char *structure) | |
437 | { | |
438 | int ok = 0; | |
439 | unsigned char *der_legacy = NULL; | |
440 | const unsigned char *pder_legacy = NULL; | |
441 | size_t der_legacy_len = 0; | |
442 | unsigned char *der_provided = NULL; | |
443 | const unsigned char *pder_provided = NULL; | |
444 | size_t der_provided_len = 0; | |
445 | size_t tmp_size; | |
446 | OSSL_ENCODER_CTX *ectx = NULL; | |
447 | OSSL_DECODER_CTX *dctx = NULL; | |
448 | void *decoded_legacy_key = NULL; | |
449 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
450 | EVP_PKEY *decoded_provided_pkey = NULL; | |
451 | ||
452 | if (!TEST_ptr(ectx = | |
fe75766c TM |
453 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
454 | "DER", structure, | |
455 | NULL)) | |
e76a6962 RL |
456 | || !TEST_true(OSSL_ENCODER_to_data(ectx, |
457 | &der_provided, &der_provided_len)) | |
458 | || !TEST_size_t_gt(der_legacy_len = i2d(legacy_key, &der_legacy), 0) | |
459 | || !TEST_mem_eq(der_provided, der_provided_len, | |
460 | der_legacy, der_legacy_len)) | |
461 | goto end; | |
462 | ||
463 | if (d2i != NULL) { | |
464 | /* Now try decoding the results and compare the resulting keys */ | |
465 | ||
466 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
467 | || !TEST_ptr(dctx = | |
fe75766c TM |
468 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
469 | "DER", structure, | |
470 | keytype, selection, | |
471 | NULL, NULL)) | |
e76a6962 RL |
472 | || !TEST_true((pder_provided = der_provided, |
473 | tmp_size = der_provided_len, | |
474 | OSSL_DECODER_from_data(dctx, &pder_provided, | |
475 | &tmp_size))) | |
476 | || !TEST_ptr((pder_legacy = der_legacy, | |
477 | decoded_legacy_key = d2i(NULL, &pder_legacy, | |
478 | (long)der_legacy_len))) | |
479 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
480 | decoded_legacy_key))) | |
481 | goto end; | |
482 | ||
483 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
484 | decoded_legacy_pkey), 0)) { | |
485 | TEST_info("decoded_provided_pkey:"); | |
486 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
487 | TEST_info("decoded_legacy_pkey:"); | |
488 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
489 | } | |
490 | } | |
491 | ok = 1; | |
492 | end: | |
493 | EVP_PKEY_free(decoded_legacy_pkey); | |
494 | EVP_PKEY_free(decoded_provided_pkey); | |
495 | OSSL_ENCODER_CTX_free(ectx); | |
496 | OSSL_DECODER_CTX_free(dctx); | |
497 | OPENSSL_free(der_provided); | |
498 | OPENSSL_free(der_legacy); | |
499 | return ok; | |
500 | } | |
501 | ||
502 | static int test_key(int idx) | |
503 | { | |
504 | struct test_stanza_st *test_stanza = NULL; | |
505 | struct key_st *key = NULL; | |
506 | int ok = 0; | |
507 | size_t i; | |
508 | EVP_PKEY *pkey = NULL, *downgraded_pkey = NULL; | |
509 | void *legacy_obj = NULL; | |
510 | ||
511 | /* Get the test data */ | |
512 | if (!TEST_ptr(test_stanza = &test_stanzas[idx]) | |
513 | || !TEST_ptr(key = lookup_key(test_stanza->keytype))) | |
514 | goto end; | |
515 | ||
516 | /* Set up the keys */ | |
517 | if (!TEST_ptr(pkey = key->key) | |
518 | || !TEST_true(evp_pkey_copy_downgraded(&downgraded_pkey, pkey)) | |
519 | || !TEST_ptr(downgraded_pkey) | |
520 | || !TEST_int_eq(EVP_PKEY_id(downgraded_pkey), key->evp_type) | |
521 | || !TEST_ptr(legacy_obj = EVP_PKEY_get0(downgraded_pkey))) | |
522 | goto end; | |
523 | ||
524 | ok = 1; | |
525 | ||
526 | /* Test PrivateKey to PEM */ | |
527 | if (test_stanza->pem_write_bio_PrivateKey != NULL) { | |
528 | int selection = OSSL_KEYMGMT_SELECT_ALL; | |
529 | ||
530 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
531 | const char *structure = test_stanza->structure[i]; | |
532 | ||
533 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PrivateKey for %s, %s", | |
534 | test_stanza->keytype, structure); | |
535 | if (!test_protected_PEM(key->keytype, key->evp_type, legacy_obj, | |
536 | test_stanza->pem_write_bio_PrivateKey, | |
537 | test_stanza->pem_read_bio_PrivateKey, | |
538 | EVP_PKEY_eq, EVP_PKEY_print_private, | |
539 | pkey, selection, structure)) | |
540 | ok = 0; | |
541 | } | |
542 | } | |
543 | ||
544 | /* Test PublicKey to PEM */ | |
545 | if (test_stanza->pem_write_bio_PublicKey != NULL) { | |
546 | int selection = | |
547 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
548 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
549 | ||
550 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
551 | const char *structure = test_stanza->structure[i]; | |
552 | ||
553 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PublicKey for %s, %s", | |
554 | test_stanza->keytype, structure); | |
555 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
556 | test_stanza->pem_write_bio_PublicKey, | |
557 | test_stanza->pem_read_bio_PublicKey, | |
558 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
559 | pkey, selection, structure)) | |
560 | ok = 0; | |
561 | } | |
562 | } | |
563 | ||
564 | /* Test params to PEM */ | |
565 | if (test_stanza->pem_write_bio_params != NULL) { | |
566 | int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
567 | ||
568 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
569 | const char *structure = test_stanza->structure[i]; | |
570 | ||
571 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}params for %s, %s", | |
572 | test_stanza->keytype, structure); | |
573 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
574 | test_stanza->pem_write_bio_params, | |
575 | test_stanza->pem_read_bio_params, | |
576 | EVP_PKEY_parameters_eq, | |
577 | EVP_PKEY_print_params, | |
578 | pkey, selection, structure)) | |
579 | ok = 0; | |
580 | } | |
581 | } | |
582 | ||
583 | /* Test PUBKEY to PEM */ | |
584 | if (test_stanza->pem_write_bio_PUBKEY != NULL) { | |
585 | int selection = | |
586 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
587 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
588 | const char *structure = "SubjectPublicKeyInfo"; | |
589 | ||
590 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}_PUBKEY for %s, %s", | |
591 | test_stanza->keytype, structure); | |
592 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
593 | test_stanza->pem_write_bio_PUBKEY, | |
594 | test_stanza->pem_read_bio_PUBKEY, | |
595 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
596 | pkey, selection, structure)) | |
597 | ok = 0; | |
598 | } | |
599 | ||
600 | ||
601 | /* Test PrivateKey to DER */ | |
602 | if (test_stanza->i2d_PrivateKey != NULL) { | |
603 | int selection = OSSL_KEYMGMT_SELECT_ALL; | |
604 | ||
605 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
606 | const char *structure = test_stanza->structure[i]; | |
607 | ||
608 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PrivateKey for %s, %s", | |
609 | test_stanza->keytype, structure); | |
610 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
611 | test_stanza->i2d_PrivateKey, | |
612 | test_stanza->d2i_PrivateKey, | |
613 | EVP_PKEY_eq, EVP_PKEY_print_private, | |
614 | pkey, selection, structure)) | |
615 | ok = 0; | |
616 | } | |
617 | } | |
618 | ||
619 | /* Test PublicKey to DER */ | |
620 | if (test_stanza->i2d_PublicKey != NULL) { | |
621 | int selection = | |
622 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
623 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
624 | ||
625 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
626 | const char *structure = test_stanza->structure[i]; | |
627 | ||
628 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PublicKey for %s, %s", | |
629 | test_stanza->keytype, structure); | |
630 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
631 | test_stanza->i2d_PublicKey, | |
632 | test_stanza->d2i_PublicKey, | |
633 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
634 | pkey, selection, structure)) | |
635 | ok = 0; | |
636 | } | |
637 | } | |
638 | ||
639 | /* Test params to DER */ | |
640 | if (test_stanza->i2d_params != NULL) { | |
641 | int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
642 | ||
643 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
644 | const char *structure = test_stanza->structure[i]; | |
645 | ||
646 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}params for %s, %s", | |
647 | test_stanza->keytype, structure); | |
648 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
649 | test_stanza->i2d_params, test_stanza->d2i_params, | |
650 | EVP_PKEY_parameters_eq, EVP_PKEY_print_params, | |
651 | pkey, selection, structure)) | |
652 | ok = 0; | |
653 | } | |
654 | } | |
655 | ||
656 | /* Test PUBKEY to DER */ | |
657 | if (test_stanza->i2d_PUBKEY != NULL) { | |
658 | int selection = | |
659 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
660 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
661 | const char *structure = "SubjectPublicKeyInfo"; | |
662 | ||
663 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}_PUBKEY for %s, %s", | |
664 | test_stanza->keytype, structure); | |
665 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
666 | test_stanza->i2d_PUBKEY, test_stanza->d2i_PUBKEY, | |
667 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
668 | pkey, selection, structure)) | |
669 | ok = 0; | |
670 | } | |
671 | end: | |
672 | EVP_PKEY_free(downgraded_pkey); | |
673 | return ok; | |
674 | } | |
675 | ||
676 | int setup_tests(void) | |
677 | { | |
678 | size_t i; | |
679 | ||
680 | TEST_info("Generating keys..."); | |
681 | ||
682 | for (i = 0; i < OSSL_NELEM(keys); i++) { | |
683 | if (!TEST_ptr(keys[i].key = | |
684 | make_key(keys[i].keytype, keys[i].template_params))) | |
685 | return 0; | |
686 | } | |
687 | ||
688 | TEST_info("Generating key... done"); | |
689 | ||
690 | ADD_ALL_TESTS(test_key, OSSL_NELEM(test_stanzas)); | |
691 | return 1; | |
692 | } | |
693 | ||
694 | void cleanup_tests(void) | |
695 | { | |
696 | size_t i; | |
697 | ||
698 | for (i = 0; i < OSSL_NELEM(keys); i++) | |
699 | EVP_PKEY_free(keys[i].key); | |
700 | } |