1 // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <assert.h>
16
17 #include <openssl/asn1.h>
18 #include <openssl/bio.h>
19 #include <openssl/digest.h>
20 #include <openssl/err.h>
21 #include <openssl/evp.h>
22 #include <openssl/mem.h>
23 #include <openssl/obj.h>
24 #include <openssl/x509.h>
25
26 #include "internal.h"
27
28
X509_print_ex_fp(FILE * fp,X509 * x,unsigned long nmflag,unsigned long cflag)29 int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
30 unsigned long cflag) {
31 BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
32 if (b == NULL) {
33 OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
34 return 0;
35 }
36 int ret = X509_print_ex(b, x, nmflag, cflag);
37 BIO_free(b);
38 return ret;
39 }
40
X509_print_fp(FILE * fp,X509 * x)41 int X509_print_fp(FILE *fp, X509 *x) {
42 return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
43 }
44
X509_print(BIO * bp,X509 * x)45 int X509_print(BIO *bp, X509 *x) {
46 return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
47 }
48
X509_print_ex(BIO * bp,X509 * x,unsigned long nmflags,unsigned long cflag)49 int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
50 unsigned long cflag) {
51 char mlch = ' ';
52 int nmindent = 0;
53 if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
54 mlch = '\n';
55 nmindent = 12;
56 }
57
58 if (nmflags == X509_FLAG_COMPAT) {
59 nmindent = 16;
60 }
61
62 const X509_CINF *ci = x->cert_info;
63 if (!(cflag & X509_FLAG_NO_HEADER)) {
64 if (BIO_write(bp, "Certificate:\n", 13) <= 0) {
65 return 0;
66 }
67 if (BIO_write(bp, " Data:\n", 10) <= 0) {
68 return 0;
69 }
70 }
71 if (!(cflag & X509_FLAG_NO_VERSION)) {
72 long l = X509_get_version(x);
73 assert(X509_VERSION_1 <= l && l <= X509_VERSION_3);
74 if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1,
75 (unsigned long)l) <= 0) {
76 return 0;
77 }
78 }
79 if (!(cflag & X509_FLAG_NO_SERIAL)) {
80 if (BIO_write(bp, " Serial Number:", 22) <= 0) {
81 return 0;
82 }
83
84 const ASN1_INTEGER *serial = X509_get0_serialNumber(x);
85 uint64_t serial_u64;
86 if (ASN1_INTEGER_get_uint64(&serial_u64, serial)) {
87 assert(serial->type != V_ASN1_NEG_INTEGER);
88 if (BIO_printf(bp, " %" PRIu64 " (0x%" PRIx64 ")\n", serial_u64,
89 serial_u64) <= 0) {
90 return 0;
91 }
92 } else {
93 ERR_clear_error(); // Clear |ASN1_INTEGER_get_uint64|'s error.
94 const char *neg =
95 (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
96 if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) {
97 return 0;
98 }
99
100 for (int i = 0; i < serial->length; i++) {
101 if (BIO_printf(bp, "%02x%c", serial->data[i],
102 ((i + 1 == serial->length) ? '\n' : ':')) <= 0) {
103 return 0;
104 }
105 }
106 }
107 }
108
109 if (!(cflag & X509_FLAG_NO_SIGNAME)) {
110 if (X509_signature_print(bp, ci->signature, NULL) <= 0) {
111 return 0;
112 }
113 }
114
115 if (!(cflag & X509_FLAG_NO_ISSUER)) {
116 if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) {
117 return 0;
118 }
119 if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) <
120 0) {
121 return 0;
122 }
123 if (BIO_write(bp, "\n", 1) <= 0) {
124 return 0;
125 }
126 }
127 if (!(cflag & X509_FLAG_NO_VALIDITY)) {
128 if (BIO_write(bp, " Validity\n", 17) <= 0) {
129 return 0;
130 }
131 if (BIO_write(bp, " Not Before: ", 24) <= 0) {
132 return 0;
133 }
134 if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) {
135 return 0;
136 }
137 if (BIO_write(bp, "\n Not After : ", 25) <= 0) {
138 return 0;
139 }
140 if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) {
141 return 0;
142 }
143 if (BIO_write(bp, "\n", 1) <= 0) {
144 return 0;
145 }
146 }
147 if (!(cflag & X509_FLAG_NO_SUBJECT)) {
148 if (BIO_printf(bp, " Subject:%c", mlch) <= 0) {
149 return 0;
150 }
151 if (X509_NAME_print_ex(bp, X509_get_subject_name(x), nmindent, nmflags) <
152 0) {
153 return 0;
154 }
155 if (BIO_write(bp, "\n", 1) <= 0) {
156 return 0;
157 }
158 }
159 if (!(cflag & X509_FLAG_NO_PUBKEY)) {
160 if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) {
161 return 0;
162 }
163 if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) {
164 return 0;
165 }
166 if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) {
167 return 0;
168 }
169 if (BIO_puts(bp, "\n") <= 0) {
170 return 0;
171 }
172
173 const EVP_PKEY *pkey = X509_get0_pubkey(x);
174 if (pkey == NULL) {
175 BIO_printf(bp, "%12sUnable to load Public Key\n", "");
176 ERR_print_errors(bp);
177 } else {
178 EVP_PKEY_print_public(bp, pkey, 16, NULL);
179 }
180 }
181
182 if (!(cflag & X509_FLAG_NO_IDS)) {
183 if (ci->issuerUID) {
184 if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) {
185 return 0;
186 }
187 if (!X509_signature_dump(bp, ci->issuerUID, 12)) {
188 return 0;
189 }
190 }
191 if (ci->subjectUID) {
192 if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) {
193 return 0;
194 }
195 if (!X509_signature_dump(bp, ci->subjectUID, 12)) {
196 return 0;
197 }
198 }
199 }
200
201 if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
202 X509V3_extensions_print(bp, "X509v3 extensions", ci->extensions, cflag, 8);
203 }
204
205 if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
206 if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) {
207 return 0;
208 }
209 }
210 if (!(cflag & X509_FLAG_NO_AUX)) {
211 if (!X509_CERT_AUX_print(bp, x->aux, 0)) {
212 return 0;
213 }
214 }
215
216 return 1;
217 }
218
X509_signature_print(BIO * bp,const X509_ALGOR * sigalg,const ASN1_STRING * sig)219 int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
220 const ASN1_STRING *sig) {
221 if (BIO_puts(bp, " Signature Algorithm: ") <= 0) {
222 return 0;
223 }
224 if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) {
225 return 0;
226 }
227
228 // RSA-PSS signatures have parameters to print.
229 int sig_nid = OBJ_obj2nid(sigalg->algorithm);
230 if (sig_nid == NID_rsassaPss &&
231 !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) {
232 return 0;
233 }
234
235 if (sig) {
236 return X509_signature_dump(bp, sig, 9);
237 } else if (BIO_puts(bp, "\n") <= 0) {
238 return 0;
239 }
240 return 1;
241 }
242
X509_NAME_print(BIO * bp,const X509_NAME * name,int obase)243 int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) {
244 char *s, *c, *b;
245 int ret = 0, i;
246
247 b = X509_NAME_oneline(name, NULL, 0);
248 if (!b) {
249 return 0;
250 }
251 if (!*b) {
252 OPENSSL_free(b);
253 return 1;
254 }
255 s = b + 1; // skip the first slash
256
257 c = s;
258 for (;;) {
259 if (((*s == '/') && ((s[1] >= 'A') && (s[1] <= 'Z') &&
260 ((s[2] == '=') || ((s[2] >= 'A') && (s[2] <= 'Z') &&
261 (s[3] == '='))))) ||
262 (*s == '\0')) {
263 i = s - c;
264 if (BIO_write(bp, c, i) != i) {
265 goto err;
266 }
267 c = s + 1; // skip following slash
268 if (*s != '\0') {
269 if (BIO_write(bp, ", ", 2) != 2) {
270 goto err;
271 }
272 }
273 }
274 if (*s == '\0') {
275 break;
276 }
277 s++;
278 }
279
280 ret = 1;
281 if (0) {
282 err:
283 OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
284 }
285 OPENSSL_free(b);
286 return ret;
287 }
288