]>
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 | ||
7bc0fdd3 | 61 | typedef int PEM_write_bio_of_void_protected(BIO *out, const void *obj, |
e76a6962 RL |
62 | const EVP_CIPHER *enc, |
63 | unsigned char *kstr, int klen, | |
64 | pem_password_cb *cb, void *u); | |
7bc0fdd3 | 65 | typedef int PEM_write_bio_of_void_unprotected(BIO *out, const void *obj); |
e76a6962 RL |
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) | |
f9253152 | 252 | || EVP_PKEY_generate(ctx, &template) <= 0)) |
e76a6962 RL |
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 | ||
69fb52e0 P |
292 | return TEST_long_ge(len_provided, 0) |
293 | && TEST_strn2_eq(str_provided, len_provided, | |
294 | str_legacy, len_legacy); | |
e76a6962 RL |
295 | } |
296 | ||
297 | static int test_protected_PEM(const char *keytype, int evp_type, | |
7bc0fdd3 | 298 | const void *legacy_key, |
e76a6962 RL |
299 | PEM_write_bio_of_void_protected *pem_write_bio, |
300 | PEM_read_bio_of_void *pem_read_bio, | |
301 | EVP_PKEY_eq_fn *evp_pkey_eq, | |
302 | EVP_PKEY_print_fn *evp_pkey_print, | |
303 | EVP_PKEY *provided_pkey, int selection, | |
304 | const char *structure) | |
305 | { | |
306 | int ok = 0; | |
307 | BIO *membio_legacy = NULL; | |
308 | BIO *membio_provided = NULL; | |
309 | OSSL_ENCODER_CTX *ectx = NULL; | |
310 | OSSL_DECODER_CTX *dctx = NULL; | |
311 | void *decoded_legacy_key = NULL; | |
312 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
313 | EVP_PKEY *decoded_provided_pkey = NULL; | |
314 | ||
315 | /* Set up the BIOs, so we have them */ | |
316 | if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem())) | |
317 | || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem()))) | |
318 | goto end; | |
319 | ||
320 | if (!TEST_ptr(ectx = | |
fe75766c TM |
321 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
322 | "PEM", structure, | |
323 | NULL)) | |
e76a6962 RL |
324 | || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided)) |
325 | || !TEST_true(pem_write_bio(membio_legacy, legacy_key, | |
326 | NULL, NULL, 0, NULL, NULL)) | |
327 | || !test_membio_str_eq(membio_provided, membio_legacy)) | |
328 | goto end; | |
329 | ||
330 | if (pem_read_bio != NULL) { | |
331 | /* Now try decoding the results and compare the resulting keys */ | |
332 | ||
333 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
334 | || !TEST_ptr(dctx = | |
fe75766c TM |
335 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
336 | "PEM", structure, | |
337 | keytype, selection, | |
338 | NULL, NULL)) | |
e76a6962 RL |
339 | || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided)) |
340 | || !TEST_ptr(decoded_legacy_key = | |
341 | pem_read_bio(membio_legacy, NULL, NULL, NULL)) | |
342 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
343 | decoded_legacy_key))) | |
344 | goto end; | |
345 | ||
346 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
347 | decoded_legacy_pkey), 0)) { | |
348 | TEST_info("decoded_provided_pkey:"); | |
349 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
350 | TEST_info("decoded_legacy_pkey:"); | |
351 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
352 | } | |
353 | } | |
354 | ok = 1; | |
355 | end: | |
356 | EVP_PKEY_free(decoded_legacy_pkey); | |
357 | EVP_PKEY_free(decoded_provided_pkey); | |
358 | OSSL_ENCODER_CTX_free(ectx); | |
359 | OSSL_DECODER_CTX_free(dctx); | |
360 | BIO_free(membio_provided); | |
361 | BIO_free(membio_legacy); | |
362 | return ok; | |
363 | } | |
364 | ||
365 | static int test_unprotected_PEM(const char *keytype, int evp_type, | |
7bc0fdd3 | 366 | const void *legacy_key, |
e76a6962 RL |
367 | PEM_write_bio_of_void_unprotected *pem_write_bio, |
368 | PEM_read_bio_of_void *pem_read_bio, | |
369 | EVP_PKEY_eq_fn *evp_pkey_eq, | |
370 | EVP_PKEY_print_fn *evp_pkey_print, | |
371 | EVP_PKEY *provided_pkey, int selection, | |
372 | const char *structure) | |
373 | { | |
374 | int ok = 0; | |
375 | BIO *membio_legacy = NULL; | |
376 | BIO *membio_provided = NULL; | |
377 | OSSL_ENCODER_CTX *ectx = NULL; | |
378 | OSSL_DECODER_CTX *dctx = NULL; | |
379 | void *decoded_legacy_key = NULL; | |
380 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
381 | EVP_PKEY *decoded_provided_pkey = NULL; | |
382 | ||
383 | /* Set up the BIOs, so we have them */ | |
384 | if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem())) | |
385 | || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem()))) | |
386 | goto end; | |
387 | ||
388 | if (!TEST_ptr(ectx = | |
fe75766c TM |
389 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
390 | "PEM", structure, | |
391 | NULL)) | |
e76a6962 RL |
392 | || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided)) |
393 | || !TEST_true(pem_write_bio(membio_legacy, legacy_key)) | |
394 | || !test_membio_str_eq(membio_provided, membio_legacy)) | |
395 | goto end; | |
396 | ||
397 | if (pem_read_bio != NULL) { | |
398 | /* Now try decoding the results and compare the resulting keys */ | |
399 | ||
400 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
401 | || !TEST_ptr(dctx = | |
fe75766c TM |
402 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
403 | "PEM", structure, | |
404 | keytype, selection, | |
405 | NULL, NULL)) | |
e76a6962 RL |
406 | || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided)) |
407 | || !TEST_ptr(decoded_legacy_key = | |
408 | pem_read_bio(membio_legacy, NULL, NULL, NULL)) | |
409 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
410 | decoded_legacy_key))) | |
411 | goto end; | |
412 | ||
413 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
414 | decoded_legacy_pkey), 0)) { | |
415 | TEST_info("decoded_provided_pkey:"); | |
416 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
417 | TEST_info("decoded_legacy_pkey:"); | |
418 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
419 | } | |
420 | } | |
421 | ok = 1; | |
422 | end: | |
423 | EVP_PKEY_free(decoded_legacy_pkey); | |
424 | EVP_PKEY_free(decoded_provided_pkey); | |
425 | OSSL_ENCODER_CTX_free(ectx); | |
426 | OSSL_DECODER_CTX_free(dctx); | |
427 | BIO_free(membio_provided); | |
428 | BIO_free(membio_legacy); | |
429 | return ok; | |
430 | } | |
431 | ||
432 | static int test_DER(const char *keytype, int evp_type, | |
7bc0fdd3 | 433 | const void *legacy_key, i2d_of_void *i2d, d2i_of_void *d2i, |
e76a6962 RL |
434 | EVP_PKEY_eq_fn *evp_pkey_eq, |
435 | EVP_PKEY_print_fn *evp_pkey_print, | |
436 | EVP_PKEY *provided_pkey, int selection, | |
437 | const char *structure) | |
438 | { | |
439 | int ok = 0; | |
440 | unsigned char *der_legacy = NULL; | |
441 | const unsigned char *pder_legacy = NULL; | |
442 | size_t der_legacy_len = 0; | |
443 | unsigned char *der_provided = NULL; | |
444 | const unsigned char *pder_provided = NULL; | |
445 | size_t der_provided_len = 0; | |
446 | size_t tmp_size; | |
447 | OSSL_ENCODER_CTX *ectx = NULL; | |
448 | OSSL_DECODER_CTX *dctx = NULL; | |
449 | void *decoded_legacy_key = NULL; | |
450 | EVP_PKEY *decoded_legacy_pkey = NULL; | |
451 | EVP_PKEY *decoded_provided_pkey = NULL; | |
452 | ||
453 | if (!TEST_ptr(ectx = | |
fe75766c TM |
454 | OSSL_ENCODER_CTX_new_for_pkey(provided_pkey, selection, |
455 | "DER", structure, | |
456 | NULL)) | |
e76a6962 RL |
457 | || !TEST_true(OSSL_ENCODER_to_data(ectx, |
458 | &der_provided, &der_provided_len)) | |
459 | || !TEST_size_t_gt(der_legacy_len = i2d(legacy_key, &der_legacy), 0) | |
460 | || !TEST_mem_eq(der_provided, der_provided_len, | |
461 | der_legacy, der_legacy_len)) | |
462 | goto end; | |
463 | ||
464 | if (d2i != NULL) { | |
465 | /* Now try decoding the results and compare the resulting keys */ | |
466 | ||
467 | if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new()) | |
468 | || !TEST_ptr(dctx = | |
fe75766c TM |
469 | OSSL_DECODER_CTX_new_for_pkey(&decoded_provided_pkey, |
470 | "DER", structure, | |
471 | keytype, selection, | |
472 | NULL, NULL)) | |
e76a6962 RL |
473 | || !TEST_true((pder_provided = der_provided, |
474 | tmp_size = der_provided_len, | |
475 | OSSL_DECODER_from_data(dctx, &pder_provided, | |
476 | &tmp_size))) | |
477 | || !TEST_ptr((pder_legacy = der_legacy, | |
478 | decoded_legacy_key = d2i(NULL, &pder_legacy, | |
479 | (long)der_legacy_len))) | |
480 | || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type, | |
481 | decoded_legacy_key))) | |
482 | goto end; | |
483 | ||
484 | if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey, | |
485 | decoded_legacy_pkey), 0)) { | |
486 | TEST_info("decoded_provided_pkey:"); | |
487 | evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL); | |
488 | TEST_info("decoded_legacy_pkey:"); | |
489 | evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL); | |
490 | } | |
491 | } | |
492 | ok = 1; | |
493 | end: | |
494 | EVP_PKEY_free(decoded_legacy_pkey); | |
495 | EVP_PKEY_free(decoded_provided_pkey); | |
496 | OSSL_ENCODER_CTX_free(ectx); | |
497 | OSSL_DECODER_CTX_free(dctx); | |
498 | OPENSSL_free(der_provided); | |
499 | OPENSSL_free(der_legacy); | |
500 | return ok; | |
501 | } | |
502 | ||
503 | static int test_key(int idx) | |
504 | { | |
505 | struct test_stanza_st *test_stanza = NULL; | |
506 | struct key_st *key = NULL; | |
507 | int ok = 0; | |
508 | size_t i; | |
509 | EVP_PKEY *pkey = NULL, *downgraded_pkey = NULL; | |
7bc0fdd3 | 510 | const void *legacy_obj = NULL; |
e76a6962 RL |
511 | |
512 | /* Get the test data */ | |
513 | if (!TEST_ptr(test_stanza = &test_stanzas[idx]) | |
514 | || !TEST_ptr(key = lookup_key(test_stanza->keytype))) | |
515 | goto end; | |
516 | ||
517 | /* Set up the keys */ | |
518 | if (!TEST_ptr(pkey = key->key) | |
519 | || !TEST_true(evp_pkey_copy_downgraded(&downgraded_pkey, pkey)) | |
520 | || !TEST_ptr(downgraded_pkey) | |
ed576acd | 521 | || !TEST_int_eq(EVP_PKEY_get_id(downgraded_pkey), key->evp_type) |
e76a6962 RL |
522 | || !TEST_ptr(legacy_obj = EVP_PKEY_get0(downgraded_pkey))) |
523 | goto end; | |
524 | ||
525 | ok = 1; | |
526 | ||
527 | /* Test PrivateKey to PEM */ | |
528 | if (test_stanza->pem_write_bio_PrivateKey != NULL) { | |
529 | int selection = OSSL_KEYMGMT_SELECT_ALL; | |
530 | ||
531 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
532 | const char *structure = test_stanza->structure[i]; | |
533 | ||
534 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PrivateKey for %s, %s", | |
535 | test_stanza->keytype, structure); | |
536 | if (!test_protected_PEM(key->keytype, key->evp_type, legacy_obj, | |
537 | test_stanza->pem_write_bio_PrivateKey, | |
538 | test_stanza->pem_read_bio_PrivateKey, | |
539 | EVP_PKEY_eq, EVP_PKEY_print_private, | |
540 | pkey, selection, structure)) | |
541 | ok = 0; | |
542 | } | |
543 | } | |
544 | ||
545 | /* Test PublicKey to PEM */ | |
546 | if (test_stanza->pem_write_bio_PublicKey != NULL) { | |
547 | int selection = | |
548 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
549 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
550 | ||
551 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
552 | const char *structure = test_stanza->structure[i]; | |
553 | ||
554 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PublicKey for %s, %s", | |
555 | test_stanza->keytype, structure); | |
556 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
557 | test_stanza->pem_write_bio_PublicKey, | |
558 | test_stanza->pem_read_bio_PublicKey, | |
559 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
560 | pkey, selection, structure)) | |
561 | ok = 0; | |
562 | } | |
563 | } | |
564 | ||
565 | /* Test params to PEM */ | |
566 | if (test_stanza->pem_write_bio_params != NULL) { | |
567 | int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
568 | ||
569 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
570 | const char *structure = test_stanza->structure[i]; | |
571 | ||
572 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}params for %s, %s", | |
573 | test_stanza->keytype, structure); | |
574 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
575 | test_stanza->pem_write_bio_params, | |
576 | test_stanza->pem_read_bio_params, | |
577 | EVP_PKEY_parameters_eq, | |
578 | EVP_PKEY_print_params, | |
579 | pkey, selection, structure)) | |
580 | ok = 0; | |
581 | } | |
582 | } | |
583 | ||
584 | /* Test PUBKEY to PEM */ | |
585 | if (test_stanza->pem_write_bio_PUBKEY != NULL) { | |
586 | int selection = | |
587 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
588 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
589 | const char *structure = "SubjectPublicKeyInfo"; | |
590 | ||
591 | TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}_PUBKEY for %s, %s", | |
592 | test_stanza->keytype, structure); | |
593 | if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj, | |
594 | test_stanza->pem_write_bio_PUBKEY, | |
595 | test_stanza->pem_read_bio_PUBKEY, | |
596 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
597 | pkey, selection, structure)) | |
598 | ok = 0; | |
599 | } | |
600 | ||
601 | ||
602 | /* Test PrivateKey to DER */ | |
603 | if (test_stanza->i2d_PrivateKey != NULL) { | |
604 | int selection = OSSL_KEYMGMT_SELECT_ALL; | |
605 | ||
606 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
607 | const char *structure = test_stanza->structure[i]; | |
608 | ||
609 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PrivateKey for %s, %s", | |
610 | test_stanza->keytype, structure); | |
611 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
612 | test_stanza->i2d_PrivateKey, | |
613 | test_stanza->d2i_PrivateKey, | |
614 | EVP_PKEY_eq, EVP_PKEY_print_private, | |
615 | pkey, selection, structure)) | |
616 | ok = 0; | |
617 | } | |
618 | } | |
619 | ||
620 | /* Test PublicKey to DER */ | |
621 | if (test_stanza->i2d_PublicKey != NULL) { | |
622 | int selection = | |
623 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
624 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
625 | ||
626 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
627 | const char *structure = test_stanza->structure[i]; | |
628 | ||
629 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PublicKey for %s, %s", | |
630 | test_stanza->keytype, structure); | |
631 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
632 | test_stanza->i2d_PublicKey, | |
633 | test_stanza->d2i_PublicKey, | |
634 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
635 | pkey, selection, structure)) | |
636 | ok = 0; | |
637 | } | |
638 | } | |
639 | ||
640 | /* Test params to DER */ | |
641 | if (test_stanza->i2d_params != NULL) { | |
642 | int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
643 | ||
644 | for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) { | |
645 | const char *structure = test_stanza->structure[i]; | |
646 | ||
647 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}params for %s, %s", | |
648 | test_stanza->keytype, structure); | |
649 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
650 | test_stanza->i2d_params, test_stanza->d2i_params, | |
651 | EVP_PKEY_parameters_eq, EVP_PKEY_print_params, | |
652 | pkey, selection, structure)) | |
653 | ok = 0; | |
654 | } | |
655 | } | |
656 | ||
657 | /* Test PUBKEY to DER */ | |
658 | if (test_stanza->i2d_PUBKEY != NULL) { | |
659 | int selection = | |
660 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY | |
661 | | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; | |
662 | const char *structure = "SubjectPublicKeyInfo"; | |
663 | ||
664 | TEST_info("Test OSSL_ENCODER against i2d_{TYPE}_PUBKEY for %s, %s", | |
665 | test_stanza->keytype, structure); | |
666 | if (!test_DER(key->keytype, key->evp_type, legacy_obj, | |
667 | test_stanza->i2d_PUBKEY, test_stanza->d2i_PUBKEY, | |
668 | EVP_PKEY_eq, EVP_PKEY_print_public, | |
669 | pkey, selection, structure)) | |
670 | ok = 0; | |
671 | } | |
672 | end: | |
673 | EVP_PKEY_free(downgraded_pkey); | |
674 | return ok; | |
675 | } | |
676 | ||
91f2b15f DDO |
677 | #define USAGE "rsa-key.pem dh-key.pem\n" |
678 | OPT_TEST_DECLARE_USAGE(USAGE) | |
679 | ||
e76a6962 RL |
680 | int setup_tests(void) |
681 | { | |
682 | size_t i; | |
683 | ||
91f2b15f DDO |
684 | if (!test_skip_common_options()) { |
685 | TEST_error("Error parsing test options\n"); | |
686 | return 0; | |
687 | } | |
688 | if (test_get_argument_count() != 2) { | |
689 | TEST_error("usage: endecoder_legacy_test %s", USAGE); | |
690 | return 0; | |
691 | } | |
692 | ||
e76a6962 RL |
693 | TEST_info("Generating keys..."); |
694 | ||
695 | for (i = 0; i < OSSL_NELEM(keys); i++) { | |
91f2b15f DDO |
696 | #ifndef OPENSSL_NO_DH |
697 | if (strcmp(keys[i].keytype, "DH") == 0) { | |
698 | if (!TEST_ptr(keys[i].key = | |
699 | load_pkey_pem(test_get_argument(1), NULL))) | |
700 | return 0; | |
701 | continue; | |
702 | } | |
703 | #endif | |
704 | #ifndef OPENSSL_NO_DEPRECATED_3_0 | |
705 | if (strcmp(keys[i].keytype, "RSA") == 0) { | |
706 | if (!TEST_ptr(keys[i].key = | |
707 | load_pkey_pem(test_get_argument(0), NULL))) | |
708 | return 0; | |
709 | continue; | |
710 | } | |
711 | #endif | |
712 | TEST_info("Generating %s key...", keys[i].keytype); | |
e76a6962 RL |
713 | if (!TEST_ptr(keys[i].key = |
714 | make_key(keys[i].keytype, keys[i].template_params))) | |
715 | return 0; | |
716 | } | |
717 | ||
91f2b15f | 718 | TEST_info("Generating keys done"); |
e76a6962 RL |
719 | |
720 | ADD_ALL_TESTS(test_key, OSSL_NELEM(test_stanzas)); | |
721 | return 1; | |
722 | } | |
723 | ||
724 | void cleanup_tests(void) | |
725 | { | |
726 | size_t i; | |
727 | ||
728 | for (i = 0; i < OSSL_NELEM(keys); i++) | |
729 | EVP_PKEY_free(keys[i].key); | |
730 | } |