1 | /*
|
---|
2 | * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | * or in the file LICENSE in the source distribution.
|
---|
9 | */
|
---|
10 |
|
---|
11 | #include <stdio.h>
|
---|
12 | #include <string.h>
|
---|
13 | #include <errno.h>
|
---|
14 |
|
---|
15 | #include <openssl/x509.h>
|
---|
16 | #include <openssl/pem.h>
|
---|
17 | #include <openssl/conf.h>
|
---|
18 | #include <openssl/err.h>
|
---|
19 | #include "testutil.h"
|
---|
20 |
|
---|
21 | static int test_certs(int num)
|
---|
22 | {
|
---|
23 | int c;
|
---|
24 | char *name = 0;
|
---|
25 | char *header = 0;
|
---|
26 | unsigned char *data = 0;
|
---|
27 | long len;
|
---|
28 | typedef X509 *(*d2i_X509_t)(X509 **, const unsigned char **, long);
|
---|
29 | typedef int (*i2d_X509_t)(const X509 *, unsigned char **);
|
---|
30 | int err = 0;
|
---|
31 | BIO *fp = BIO_new_file(test_get_argument(num), "r");
|
---|
32 |
|
---|
33 | if (!TEST_ptr(fp))
|
---|
34 | return 0;
|
---|
35 |
|
---|
36 | for (c = 0; !err && PEM_read_bio(fp, &name, &header, &data, &len); ++c) {
|
---|
37 | const int trusted = (strcmp(name, PEM_STRING_X509_TRUSTED) == 0);
|
---|
38 | d2i_X509_t d2i = trusted ? d2i_X509_AUX : d2i_X509;
|
---|
39 | i2d_X509_t i2d = trusted ? i2d_X509_AUX : i2d_X509;
|
---|
40 | X509 *cert = NULL;
|
---|
41 | X509 *reuse = NULL;
|
---|
42 | const unsigned char *p = data;
|
---|
43 | unsigned char *buf = NULL;
|
---|
44 | unsigned char *bufp;
|
---|
45 | long enclen;
|
---|
46 |
|
---|
47 | if (!trusted
|
---|
48 | && strcmp(name, PEM_STRING_X509) != 0
|
---|
49 | && strcmp(name, PEM_STRING_X509_OLD) != 0) {
|
---|
50 | TEST_error("unexpected PEM object: %s", name);
|
---|
51 | err = 1;
|
---|
52 | goto next;
|
---|
53 | }
|
---|
54 | cert = d2i(NULL, &p, len);
|
---|
55 |
|
---|
56 | if (cert == NULL || (p - data) != len) {
|
---|
57 | TEST_error("error parsing input %s", name);
|
---|
58 | err = 1;
|
---|
59 | goto next;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /* Test traditional 2-pass encoding into caller allocated buffer */
|
---|
63 | enclen = i2d(cert, NULL);
|
---|
64 | if (len != enclen) {
|
---|
65 | TEST_error("encoded length %ld of %s != input length %ld",
|
---|
66 | enclen, name, len);
|
---|
67 | err = 1;
|
---|
68 | goto next;
|
---|
69 | }
|
---|
70 | if ((buf = bufp = OPENSSL_malloc(len)) == NULL) {
|
---|
71 | TEST_perror("malloc");
|
---|
72 | err = 1;
|
---|
73 | goto next;
|
---|
74 | }
|
---|
75 | enclen = i2d(cert, &bufp);
|
---|
76 | if (len != enclen) {
|
---|
77 | TEST_error("encoded length %ld of %s != input length %ld",
|
---|
78 | enclen, name, len);
|
---|
79 | err = 1;
|
---|
80 | goto next;
|
---|
81 | }
|
---|
82 | enclen = (long) (bufp - buf);
|
---|
83 | if (enclen != len) {
|
---|
84 | TEST_error("unexpected buffer position after encoding %s", name);
|
---|
85 | err = 1;
|
---|
86 | goto next;
|
---|
87 | }
|
---|
88 | if (memcmp(buf, data, len) != 0) {
|
---|
89 | TEST_error("encoded content of %s does not match input", name);
|
---|
90 | err = 1;
|
---|
91 | goto next;
|
---|
92 | }
|
---|
93 | p = buf;
|
---|
94 | reuse = d2i(NULL, &p, enclen);
|
---|
95 | if (reuse == NULL) {
|
---|
96 | TEST_error("second d2i call failed for %s", name);
|
---|
97 | err = 1;
|
---|
98 | goto next;
|
---|
99 | }
|
---|
100 | err = X509_cmp(reuse, cert);
|
---|
101 | if (err != 0) {
|
---|
102 | TEST_error("X509_cmp for %s resulted in %d", name, err);
|
---|
103 | err = 1;
|
---|
104 | goto next;
|
---|
105 | }
|
---|
106 | OPENSSL_free(buf);
|
---|
107 | buf = NULL;
|
---|
108 |
|
---|
109 | /* Test 1-pass encoding into library allocated buffer */
|
---|
110 | enclen = i2d(cert, &buf);
|
---|
111 | if (len != enclen) {
|
---|
112 | TEST_error("encoded length %ld of %s != input length %ld",
|
---|
113 | enclen, name, len);
|
---|
114 | err = 1;
|
---|
115 | goto next;
|
---|
116 | }
|
---|
117 | if (memcmp(buf, data, len) != 0) {
|
---|
118 | TEST_error("encoded content of %s does not match input", name);
|
---|
119 | err = 1;
|
---|
120 | goto next;
|
---|
121 | }
|
---|
122 |
|
---|
123 | if (trusted) {
|
---|
124 | /* Encode just the cert and compare with initial encoding */
|
---|
125 | OPENSSL_free(buf);
|
---|
126 | buf = NULL;
|
---|
127 |
|
---|
128 | /* Test 1-pass encoding into library allocated buffer */
|
---|
129 | enclen = i2d(cert, &buf);
|
---|
130 | if (enclen > len) {
|
---|
131 | TEST_error("encoded length %ld of %s > input length %ld",
|
---|
132 | enclen, name, len);
|
---|
133 | err = 1;
|
---|
134 | goto next;
|
---|
135 | }
|
---|
136 | if (memcmp(buf, data, enclen) != 0) {
|
---|
137 | TEST_error("encoded cert content does not match input");
|
---|
138 | err = 1;
|
---|
139 | goto next;
|
---|
140 | }
|
---|
141 | }
|
---|
142 |
|
---|
143 | /*
|
---|
144 | * If any of these were null, PEM_read() would have failed.
|
---|
145 | */
|
---|
146 | next:
|
---|
147 | X509_free(cert);
|
---|
148 | X509_free(reuse);
|
---|
149 | OPENSSL_free(buf);
|
---|
150 | OPENSSL_free(name);
|
---|
151 | OPENSSL_free(header);
|
---|
152 | OPENSSL_free(data);
|
---|
153 | }
|
---|
154 | BIO_free(fp);
|
---|
155 |
|
---|
156 | if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
|
---|
157 | /* Reached end of PEM file */
|
---|
158 | if (c > 0) {
|
---|
159 | ERR_clear_error();
|
---|
160 | return 1;
|
---|
161 | }
|
---|
162 | }
|
---|
163 |
|
---|
164 | /* Some other PEM read error */
|
---|
165 | return 0;
|
---|
166 | }
|
---|
167 |
|
---|
168 | OPT_TEST_DECLARE_USAGE("certfile...\n")
|
---|
169 |
|
---|
170 | int setup_tests(void)
|
---|
171 | {
|
---|
172 | size_t n;
|
---|
173 |
|
---|
174 | if (!test_skip_common_options()) {
|
---|
175 | TEST_error("Error parsing test options\n");
|
---|
176 | return 0;
|
---|
177 | }
|
---|
178 |
|
---|
179 | n = test_get_argument_count();
|
---|
180 | if (n == 0)
|
---|
181 | return 0;
|
---|
182 |
|
---|
183 | ADD_ALL_TESTS(test_certs, (int)n);
|
---|
184 | return 1;
|
---|
185 | }
|
---|