Add Serializers for EC
[openssl.git] / test / evp_pkey_provided_test.c
1 /*
2  * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
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 #include <openssl/evp.h>
11 #include <openssl/pem.h>
12 #include <openssl/serializer.h>
13 #include <openssl/provider.h>
14 #include <openssl/params.h>
15 #include <openssl/core_names.h>
16 #include "crypto/ecx.h"
17 #include "internal/nelem.h"
18 #include "internal/param_build.h"
19 #include "crypto/evp.h"          /* For the internal API */
20 #include "testutil.h"
21
22 static char *datadir = NULL;
23
24 #define PRIV_TEXT    0
25 #define PRIV_PEM     1
26 #define PRIV_DER     2
27 #define PUB_TEXT     3
28 #define PUB_PEM      4
29 #define PUB_DER      5
30
31 static void stripcr(char *buf, size_t *len)
32 {
33     size_t i;
34     char *curr, *writ;
35
36     for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
37         if (*curr == '\r') {
38             (*len)--;
39             continue;
40         }
41         if (curr != writ)
42             *writ = *curr;
43         writ++;
44     }
45 }
46
47 static int compare_with_file(const char *alg, int type, BIO *membio)
48 {
49     char filename[80];
50     BIO *file = NULL;
51     char buf[1024];
52     char *memdata, *fullfile = NULL;
53     const char *suffix;
54     size_t readbytes;
55     int ret = 0;
56     int len;
57     size_t slen;
58
59     switch (type) {
60     case PRIV_TEXT:
61         suffix = "priv.txt";
62         break;
63
64     case PRIV_PEM:
65         suffix = "priv.pem";
66         break;
67
68     case PRIV_DER:
69         suffix = "priv.der";
70         break;
71
72     case PUB_TEXT:
73         suffix = "pub.txt";
74         break;
75
76     case PUB_PEM:
77         suffix = "pub.pem";
78         break;
79
80     case PUB_DER:
81         suffix = "pub.der";
82         break;
83
84     default:
85         TEST_error("Invalid file type");
86         goto err;
87     }
88
89     BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
90     fullfile = test_mk_file_path(datadir, filename);
91     if (!TEST_ptr(fullfile))
92         goto err;
93
94     file = BIO_new_file(fullfile, "rb");
95     if (!TEST_ptr(file))
96         goto err;
97
98     if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
99             || !TEST_true(BIO_eof(file))
100             || !TEST_size_t_lt(readbytes, sizeof(buf)))
101         goto err;
102
103     len = BIO_get_mem_data(membio, &memdata);
104     if (!TEST_int_gt(len, 0))
105         goto err;
106
107     slen = len;
108     if (type != PRIV_DER && type != PUB_DER) {
109         stripcr(memdata, &slen);
110         stripcr(buf, &readbytes);
111     }
112
113     if (!TEST_mem_eq(memdata, slen, buf, readbytes))
114         goto err;
115
116     ret = 1;
117  err:
118     OPENSSL_free(fullfile);
119     (void)BIO_reset(membio);
120     BIO_free(file);
121     return ret;
122 }
123
124 static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
125 {
126     BIO *membio = BIO_new(BIO_s_mem());
127     int ret = 0;
128
129     if (!TEST_ptr(membio))
130         goto err;
131
132     if (!TEST_true(EVP_PKEY_print_private(membio, pk, 0, NULL))
133         || !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
134         /* Public key in PEM form */
135         || !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
136         || !TEST_true(compare_with_file(alg, PUB_PEM, membio))
137         /* Unencrypted private key in PEM form */
138         || !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
139                                                NULL, NULL, 0, NULL, NULL))
140         || !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
141         /* Encrypted private key in PEM form */
142         || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
143                                                (unsigned char *)"pass", 4,
144                                                NULL, NULL)))
145         goto err;
146
147     ret = 1;
148  err:
149     BIO_free(membio);
150     return ret;
151 }
152
153 static int test_print_key_type_using_serializer(const char *alg, int type,
154                                                 const EVP_PKEY *pk)
155 {
156     const char *pq;
157     OSSL_SERIALIZER_CTX *ctx = NULL;
158     BIO *membio = BIO_new(BIO_s_mem());
159     int ret = 0;
160
161     switch (type) {
162     case PRIV_TEXT:
163         pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
164         break;
165
166     case PRIV_PEM:
167         pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
168         break;
169
170     case PRIV_DER:
171         pq = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
172         break;
173
174     case PUB_TEXT:
175         pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
176         break;
177
178     case PUB_PEM:
179         pq = OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ;
180         break;
181
182     case PUB_DER:
183         pq = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
184         break;
185
186     default:
187         TEST_error("Invalid serialization type");
188         goto err;
189     }
190
191     if (!TEST_ptr(membio))
192         goto err;
193
194     /* Make a context, it's valid for several prints */
195     TEST_note("Setting up a OSSL_SERIALIZER context with passphrase");
196     if (!TEST_ptr(ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pk, pq))
197         /* Check that this operation is supported */
198         || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx)))
199         goto err;
200
201     /* Use no cipher.  This should give us an unencrypted PEM */
202     TEST_note("Testing with no encryption");
203     if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
204         || !TEST_true(compare_with_file(alg, type, membio)))
205         goto err;
206
207     if (type == PRIV_PEM) {
208         /* Set a passphrase to be used later */
209         if (!TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
210                                                           (unsigned char *)"pass",
211                                                           4)))
212             goto err;
213
214         /* Use a valid cipher name */
215         TEST_note("Displaying PEM encrypted with AES-256-CBC");
216         if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
217             || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
218             goto err;
219
220         /* Use an invalid cipher name, which should generate no output */
221         TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
222         if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
223             || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
224             goto err;
225
226         /* Clear the cipher.  This should give us an unencrypted PEM again */
227         TEST_note("Testing with encryption cleared (no encryption)");
228         if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
229             || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
230             || !TEST_true(compare_with_file(alg, type, membio)))
231             goto err;
232     }
233     ret = 1;
234 err:
235     BIO_free(membio);
236     OSSL_SERIALIZER_CTX_free(ctx);
237     return ret;
238 }
239
240 static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
241 {
242     int i;
243     int ret = 1;
244
245     for (i = 0; i < 6; i++)
246         ret = ret && test_print_key_type_using_serializer(alg, i, pk);
247
248     return ret;
249 }
250
251 /* Array indexes used in test_fromdata_rsa */
252 #define N       0
253 #define E       1
254 #define D       2
255 #define P       3
256 #define Q       4
257 #define DP      5
258 #define DQ      6
259 #define QINV    7
260
261 static int test_fromdata_rsa(void)
262 {
263     int ret = 0;
264     EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
265     EVP_PKEY *pk = NULL;
266     /*
267      * 32-bit RSA key, extracted from this command,
268      * executed with OpenSSL 1.0.2:
269      *
270      * openssl genrsa 32 | openssl rsa -text
271      */
272     static unsigned long key_numbers[] = {
273         0xbc747fc5,              /* N */
274         0x10001,                 /* E */
275         0x7b133399,              /* D */
276         0xe963,                  /* P */
277         0xceb7,                  /* Q */
278         0x8599,                  /* DP */
279         0xbd87,                  /* DQ */
280         0xcc3b,                  /* QINV */
281     };
282     OSSL_PARAM fromdata_params[] = {
283         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &key_numbers[N]),
284         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &key_numbers[E]),
285         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &key_numbers[D]),
286         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[P]),
287         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[Q]),
288         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DP]),
289         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DQ]),
290         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &key_numbers[QINV]),
291         OSSL_PARAM_END
292     };
293
294     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
295         goto err;
296
297     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
298         || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
299         || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
300         || !TEST_int_eq(EVP_PKEY_security_bits(pk), 8)
301         || !TEST_int_eq(EVP_PKEY_size(pk), 4))
302         goto err;
303
304     if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
305         goto err;
306
307     if (!TEST_true(EVP_PKEY_check(key_ctx))
308         || !TEST_true(EVP_PKEY_public_check(key_ctx))
309         || !TEST_true(EVP_PKEY_private_check(key_ctx))
310         || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
311         goto err;
312
313     ret = test_print_key_using_pem("RSA", pk)
314           && test_print_key_using_serializer("RSA", pk);
315
316  err:
317     EVP_PKEY_free(pk);
318     EVP_PKEY_CTX_free(key_ctx);
319     EVP_PKEY_CTX_free(ctx);
320
321     return ret;
322 }
323
324 #ifndef OPENSSL_NO_DH
325 /* Array indexes used in test_fromdata_dh */
326 #define PRIV_KEY        0
327 #define PUB_KEY         1
328 #define FFC_P           2
329 #define FFC_G           3
330
331 static int test_fromdata_dh(void)
332 {
333     int ret = 0;
334     EVP_PKEY_CTX *ctx = NULL;
335     EVP_PKEY *pk = NULL;
336     /*
337      * 32-bit DH key, extracted from this command,
338      * executed with OpenSSL 1.0.2:
339      *
340      * openssl dhparam -out dhp.pem 32
341      * openssl genpkey -paramfile dhp.pem | openssl pkey -text
342      */
343     static unsigned long key_numbers[] = {
344         0x666c2b06,              /* priv-key */
345         0x6fa6de50,              /* pub-key */
346         0x8bb45f53,              /* P */
347         0x2,                     /* G */
348     };
349     OSSL_PARAM fromdata_params[] = {
350         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PRIV_KEY, &key_numbers[PRIV_KEY]),
351         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PUB_KEY, &key_numbers[PUB_KEY]),
352         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_P, &key_numbers[FFC_P]),
353         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_G, &key_numbers[FFC_G]),
354         OSSL_PARAM_END
355     };
356
357     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
358         goto err;
359
360     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
361         || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
362         || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
363         || !TEST_int_eq(EVP_PKEY_security_bits(pk), 0) /* Missing Q */
364         || !TEST_int_eq(EVP_PKEY_size(pk), 4))
365         goto err;
366
367     ret = test_print_key_using_pem("DH", pk)
368           && test_print_key_using_serializer("DH", pk);
369
370  err:
371     EVP_PKEY_free(pk);
372     EVP_PKEY_CTX_free(ctx);
373
374     return ret;
375 }
376 #endif
377
378 #ifndef OPENSSL_NO_EC
379 /* Array indexes used in test_fromdata_ecx */
380 # define PRIV_KEY        0
381 # define PUB_KEY         1
382
383 # define X25519_IDX      0
384 # define X448_IDX        1
385
386 static int test_fromdata_ecx(int tst)
387 {
388     int ret = 0;
389     EVP_PKEY_CTX *ctx = NULL;
390     EVP_PKEY *pk = NULL;
391     const char *alg = (tst == X25519_IDX) ? "X25519" : "X448";
392
393     /* X448_KEYLEN > X25519_KEYLEN */
394     static unsigned char key_numbers[2][2][X448_KEYLEN] = {
395         /* X25519: Keys from RFC 7748 6.1 */
396         {
397             /* Private Key */
398             {
399                 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
400                 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
401                 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
402                 0x2c, 0x2a
403             },
404             /* Public Key */
405             {
406                 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
407                 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
408                 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
409                 0x4e, 0x6a
410             }
411         },
412         /* X448: Keys from RFC 7748 6.2 */
413         {
414             /* Private Key */
415             {
416                 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
417                 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
418                 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
419                 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
420                 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
421                 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
422             },
423             /* Public Key */
424             {
425                 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
426                 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
427                 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
428                 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
429                 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
430                 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
431             }
432         }
433     };
434     OSSL_PARAM x25519_fromdata_params[] = {
435         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
436                                 key_numbers[X25519_IDX][PRIV_KEY],
437                                 X25519_KEYLEN),
438         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
439                                 key_numbers[X25519_IDX][PUB_KEY],
440                                 X25519_KEYLEN),
441         OSSL_PARAM_END
442     };
443     OSSL_PARAM x448_fromdata_params[] = {
444         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
445                                 key_numbers[X448_IDX][PRIV_KEY],
446                                 X448_KEYLEN),
447         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
448                                 key_numbers[X448_IDX][PUB_KEY],
449                                 X448_KEYLEN),
450         OSSL_PARAM_END
451     };
452     OSSL_PARAM *fromdata_params;
453     int bits, security_bits, size;
454
455     if (tst == X25519_IDX) {
456         fromdata_params = x25519_fromdata_params;
457         bits = X25519_BITS;
458         security_bits = X25519_SECURITY_BITS;
459         size = X25519_KEYLEN;
460     } else {
461         fromdata_params = x448_fromdata_params;
462         bits = X448_BITS;
463         security_bits = X448_SECURITY_BITS;
464         size = X448_KEYLEN;
465     }
466
467     ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
468     if (!TEST_ptr(ctx))
469         goto err;
470
471     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
472         || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
473         || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
474         || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
475         || !TEST_int_eq(EVP_PKEY_size(pk), size))
476         goto err;
477
478     ret = test_print_key_using_pem(alg, pk)
479           && test_print_key_using_serializer(alg, pk);
480
481 err:
482     EVP_PKEY_free(pk);
483     EVP_PKEY_CTX_free(ctx);
484
485     return ret;
486 }
487
488 static int test_fromdata_ec(void)
489 {
490     int ret = 0;
491     EVP_PKEY_CTX *ctx = NULL;
492     EVP_PKEY *pk = NULL;
493     OSSL_PARAM_BLD bld;
494     BIGNUM *ec_priv_bn = NULL;
495     OSSL_PARAM *fromdata_params = NULL;
496     const char *alg = "EC";
497     static const unsigned char ec_pub_keydata[] = {
498        0x04,
499        0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
500        0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
501        0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
502        0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
503        0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
504        0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
505        0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
506        0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
507     };
508     static const unsigned char ec_priv_keydata[] = {
509         0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
510         0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
511         0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
512         0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
513     };
514
515     ossl_param_bld_init(&bld);
516
517     if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
518                                          sizeof(ec_priv_keydata), NULL)))
519         goto err;
520
521     if (ossl_param_bld_push_utf8_string(&bld, OSSL_PKEY_PARAM_EC_NAME,
522                                         "prime256v1", 0) <= 0)
523         goto err;
524     if (ossl_param_bld_push_octet_string(&bld, OSSL_PKEY_PARAM_PUB_KEY,
525                                          ec_pub_keydata,
526                                          sizeof(ec_pub_keydata)) <= 0)
527         goto err;
528     if (ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
529         goto err;
530     if (!TEST_ptr(fromdata_params = ossl_param_bld_to_param(&bld)))
531         goto err;
532     ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
533     if (!TEST_ptr(ctx))
534         goto err;
535
536     if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
537         || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
538         || !TEST_int_eq(EVP_PKEY_bits(pk), 256)
539         || !TEST_int_eq(EVP_PKEY_security_bits(pk), 128)
540         || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2))
541         goto err;
542
543     ret = test_print_key_using_pem(alg, pk)
544           && test_print_key_using_serializer(alg, pk);
545 err:
546     BN_free(ec_priv_bn);
547     ossl_param_bld_free(fromdata_params);
548     EVP_PKEY_free(pk);
549     EVP_PKEY_CTX_free(ctx);
550     return ret;
551 }
552
553 #endif /* OPENSSL_NO_EC */
554
555
556 int setup_tests(void)
557 {
558     if (!test_skip_common_options()) {
559         TEST_error("Error parsing test options\n");
560         return 0;
561     }
562
563     if (!TEST_ptr(datadir = test_get_argument(0)))
564         return 0;
565
566     ADD_TEST(test_fromdata_rsa);
567 #ifndef OPENSSL_NO_DH
568     ADD_TEST(test_fromdata_dh);
569 #endif
570 #ifndef OPENSSL_NO_EC
571     ADD_ALL_TESTS(test_fromdata_ecx, 2);
572     ADD_TEST(test_fromdata_ec);
573 #endif
574     return 1;
575 }