113d40330Schristos /*
26f6db51eSchristos * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
313d40330Schristos *
4b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
513d40330Schristos * this file except in compliance with the License. You can obtain a copy
613d40330Schristos * in the file LICENSE in the source distribution or at
713d40330Schristos * https://www.openssl.org/source/license.html
813d40330Schristos */
913d40330Schristos
1013d40330Schristos #include <string.h>
1113d40330Schristos #include <openssl/bio.h>
1213d40330Schristos #include <openssl/pem.h>
1313d40330Schristos
1413d40330Schristos #include "testutil.h"
1513d40330Schristos #include "internal/nelem.h"
1613d40330Schristos
1713d40330Schristos typedef struct {
1813d40330Schristos const char *raw;
1913d40330Schristos const char *encoded;
2013d40330Schristos } TESTDATA;
2113d40330Schristos
2213d40330Schristos static TESTDATA b64_pem_data[] = {
2313d40330Schristos { "hello world",
2413d40330Schristos "aGVsbG8gd29ybGQ=" },
2513d40330Schristos { "a very ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong input",
2613d40330Schristos "YSB2ZXJ5IG9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29uZyBpbnB1dA==" }
2713d40330Schristos };
2813d40330Schristos
2913d40330Schristos static const char *pemtype = "PEMTESTDATA";
3013d40330Schristos
31b0d17251Schristos static char *pemfile;
32b0d17251Schristos
test_b64(int idx)3313d40330Schristos static int test_b64(int idx)
3413d40330Schristos {
3513d40330Schristos BIO *b = BIO_new(BIO_s_mem());
3613d40330Schristos char *name = NULL, *header = NULL;
3713d40330Schristos unsigned char *data = NULL;
3813d40330Schristos long len;
3913d40330Schristos int ret = 0;
4013d40330Schristos const char *raw = b64_pem_data[idx].raw;
4113d40330Schristos const char *encoded = b64_pem_data[idx].encoded;
4213d40330Schristos
4313d40330Schristos if (!TEST_ptr(b)
4413d40330Schristos || !TEST_true(BIO_printf(b, "-----BEGIN %s-----\n", pemtype))
4513d40330Schristos || !TEST_true(BIO_printf(b, "%s\n", encoded))
4613d40330Schristos || !TEST_true(BIO_printf(b, "-----END %s-----\n", pemtype))
4713d40330Schristos || !TEST_true(PEM_read_bio_ex(b, &name, &header, &data, &len,
4813d40330Schristos PEM_FLAG_ONLY_B64)))
4913d40330Schristos goto err;
5013d40330Schristos if (!TEST_int_eq(memcmp(pemtype, name, strlen(pemtype)), 0)
5113d40330Schristos || !TEST_int_eq(len, strlen(raw))
5213d40330Schristos || !TEST_int_eq(memcmp(data, raw, strlen(raw)), 0))
5313d40330Schristos goto err;
5413d40330Schristos ret = 1;
5513d40330Schristos err:
5613d40330Schristos BIO_free(b);
5713d40330Schristos OPENSSL_free(name);
5813d40330Schristos OPENSSL_free(header);
5913d40330Schristos OPENSSL_free(data);
6013d40330Schristos return ret;
6113d40330Schristos }
6213d40330Schristos
test_invalid(void)6313d40330Schristos static int test_invalid(void)
6413d40330Schristos {
6513d40330Schristos BIO *b = BIO_new(BIO_s_mem());
6613d40330Schristos char *name = NULL, *header = NULL;
6713d40330Schristos unsigned char *data = NULL;
6813d40330Schristos long len;
6913d40330Schristos const char *encoded = b64_pem_data[0].encoded;
7013d40330Schristos
7113d40330Schristos if (!TEST_ptr(b)
7213d40330Schristos || !TEST_true(BIO_printf(b, "-----BEGIN %s-----\n", pemtype))
7313d40330Schristos || !TEST_true(BIO_printf(b, "%c%s\n", '\t', encoded))
7413d40330Schristos || !TEST_true(BIO_printf(b, "-----END %s-----\n", pemtype))
7513d40330Schristos /* Expected to fail due to non-base64 character */
7613d40330Schristos || TEST_true(PEM_read_bio_ex(b, &name, &header, &data, &len,
7713d40330Schristos PEM_FLAG_ONLY_B64))) {
7813d40330Schristos BIO_free(b);
7913d40330Schristos return 0;
8013d40330Schristos }
8113d40330Schristos BIO_free(b);
8213d40330Schristos OPENSSL_free(name);
8313d40330Schristos OPENSSL_free(header);
8413d40330Schristos OPENSSL_free(data);
8513d40330Schristos return 1;
8613d40330Schristos }
8713d40330Schristos
test_cert_key_cert(void)88b0d17251Schristos static int test_cert_key_cert(void)
89b0d17251Schristos {
90b0d17251Schristos EVP_PKEY *key;
91b0d17251Schristos
92b0d17251Schristos if (!TEST_ptr(key = load_pkey_pem(pemfile, NULL)))
93b0d17251Schristos return 0;
94b0d17251Schristos
95b0d17251Schristos EVP_PKEY_free(key);
96b0d17251Schristos return 1;
97b0d17251Schristos }
98b0d17251Schristos
test_empty_payload(void)996f6db51eSchristos static int test_empty_payload(void)
1006f6db51eSchristos {
1016f6db51eSchristos BIO *b;
1026f6db51eSchristos static char *emptypay =
1036f6db51eSchristos "-----BEGIN CERTIFICATE-----\n"
1046f6db51eSchristos "-\n" /* Base64 EOF character */
1056f6db51eSchristos "-----END CERTIFICATE-----";
1066f6db51eSchristos char *name = NULL, *header = NULL;
1076f6db51eSchristos unsigned char *data = NULL;
1086f6db51eSchristos long len;
1096f6db51eSchristos int ret = 0;
1106f6db51eSchristos
1116f6db51eSchristos b = BIO_new_mem_buf(emptypay, strlen(emptypay));
1126f6db51eSchristos if (!TEST_ptr(b))
1136f6db51eSchristos return 0;
1146f6db51eSchristos
1156f6db51eSchristos /* Expected to fail because the payload is empty */
1166f6db51eSchristos if (!TEST_false(PEM_read_bio_ex(b, &name, &header, &data, &len, 0)))
1176f6db51eSchristos goto err;
1186f6db51eSchristos
1196f6db51eSchristos ret = 1;
1206f6db51eSchristos err:
1216f6db51eSchristos OPENSSL_free(name);
1226f6db51eSchristos OPENSSL_free(header);
1236f6db51eSchristos OPENSSL_free(data);
1246f6db51eSchristos BIO_free(b);
1256f6db51eSchristos return ret;
1266f6db51eSchristos }
1276f6db51eSchristos
test_protected_params(void)128*4778aedeSchristos static int test_protected_params(void)
129*4778aedeSchristos {
130*4778aedeSchristos BIO *b;
131*4778aedeSchristos static char *protectedpay =
132*4778aedeSchristos "-----BEGIN RSA PRIVATE KEY-----\n"
133*4778aedeSchristos "Proc-Type: 4,ENCRYPTED\n"
134*4778aedeSchristos "DEK-Info: AES-256-CBC,4A44448ED28992710556549B35100CEA\n"
135*4778aedeSchristos "\n"
136*4778aedeSchristos "Xw3INxKeH+rUUF57mjATpvj6zknVhedwrlRmRvnwlLv5wqIy5Ae4UVLPh7SUswfC\n"
137*4778aedeSchristos "-----END RSA PRIVATE KEY-----\n";
138*4778aedeSchristos EVP_PKEY *pkey = NULL;
139*4778aedeSchristos int ret = 0;
140*4778aedeSchristos
141*4778aedeSchristos b = BIO_new_mem_buf(protectedpay, strlen(protectedpay));
142*4778aedeSchristos if (!TEST_ptr(b))
143*4778aedeSchristos return 0;
144*4778aedeSchristos
145*4778aedeSchristos /* Expected to fail because we cannot decrypt protected PEM files */
146*4778aedeSchristos pkey = PEM_read_bio_Parameters(b, NULL);
147*4778aedeSchristos if (!TEST_ptr_null(pkey))
148*4778aedeSchristos goto err;
149*4778aedeSchristos
150*4778aedeSchristos ret = 1;
151*4778aedeSchristos err:
152*4778aedeSchristos EVP_PKEY_free(pkey);
153*4778aedeSchristos BIO_free(b);
154*4778aedeSchristos return ret;
155*4778aedeSchristos }
156*4778aedeSchristos
setup_tests(void)15713d40330Schristos int setup_tests(void)
15813d40330Schristos {
159b0d17251Schristos if (!TEST_ptr(pemfile = test_get_argument(0)))
160b0d17251Schristos return 0;
16113d40330Schristos ADD_ALL_TESTS(test_b64, OSSL_NELEM(b64_pem_data));
16213d40330Schristos ADD_TEST(test_invalid);
163b0d17251Schristos ADD_TEST(test_cert_key_cert);
1646f6db51eSchristos ADD_TEST(test_empty_payload);
165*4778aedeSchristos ADD_TEST(test_protected_params);
16613d40330Schristos return 1;
16713d40330Schristos }
168