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