/src/gnutls/lib/x509/pkcs7-output.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2015 Red Hat, Inc. |
3 | | * |
4 | | * Author: Nikos Mavrogiannopoulos |
5 | | * |
6 | | * This file is part of GnuTLS. |
7 | | * |
8 | | * The GnuTLS is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public License |
10 | | * as published by the Free Software Foundation; either version 2.1 of |
11 | | * the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, but |
14 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
20 | | * |
21 | | */ |
22 | | |
23 | | #include "gnutls_int.h" |
24 | | #include "common.h" |
25 | | #include "x509.h" |
26 | | #include "x509_int.h" |
27 | | #include "num.h" |
28 | | #include "errors.h" |
29 | | #include "extras/randomart.h" |
30 | | #include "pkcs7_int.h" |
31 | | |
32 | 31.1k | #define addf _gnutls_buffer_append_printf |
33 | 1.64M | #define adds _gnutls_buffer_append_str |
34 | | |
35 | | static void print_dn(gnutls_buffer_st *str, const char *prefix, |
36 | | const gnutls_datum_t *raw) |
37 | 7.73k | { |
38 | 7.73k | gnutls_x509_dn_t dn = NULL; |
39 | 7.73k | gnutls_datum_t output = { NULL, 0 }; |
40 | 7.73k | int ret; |
41 | | |
42 | 7.73k | ret = gnutls_x509_dn_init(&dn); |
43 | 7.73k | if (ret < 0) { |
44 | 0 | addf(str, "%s: [error]\n", prefix); |
45 | 0 | return; |
46 | 0 | } |
47 | | |
48 | 7.73k | ret = gnutls_x509_dn_import(dn, raw); |
49 | 7.73k | if (ret < 0) { |
50 | 89 | addf(str, "%s: [error]\n", prefix); |
51 | 89 | goto cleanup; |
52 | 89 | } |
53 | | |
54 | 7.64k | ret = gnutls_x509_dn_get_str2(dn, &output, 0); |
55 | 7.64k | if (ret < 0) { |
56 | 3.24k | addf(str, "%s: [error]\n", prefix); |
57 | 3.24k | goto cleanup; |
58 | 3.24k | } |
59 | | |
60 | 4.39k | addf(str, "%s: %s\n", prefix, output.data); |
61 | | |
62 | 7.73k | cleanup: |
63 | 7.73k | gnutls_x509_dn_deinit(dn); |
64 | 7.73k | gnutls_free(output.data); |
65 | 7.73k | } |
66 | | |
67 | | /* Do not encode ASN1 and type for now */ |
68 | | #define ENTRY(oid, name, type) \ |
69 | | { oid, sizeof(oid) - 1, name, sizeof(name) - 1, NULL, type } |
70 | | #define ENTRY2(oid, name) \ |
71 | | { \ |
72 | | oid, sizeof(oid) - 1, name, sizeof(name) - 1, \ |
73 | | NULL, ASN1_ETYPE_INVALID \ |
74 | | } |
75 | | |
76 | | static const struct oid_to_string pkcs7_attrs[] = { |
77 | | ENTRY("1.2.840.113549.1.9.3", "contentType", ASN1_ETYPE_OBJECT_ID), |
78 | | ENTRY("1.2.840.113549.1.9.4", "messageDigest", ASN1_ETYPE_OCTET_STRING), |
79 | | ENTRY("1.2.840.113549.1.9.5", "signingTime", ASN1_ETYPE_INVALID), |
80 | | ENTRY2("1.2.840.113549.1.9.6", "countersignature"), |
81 | | ENTRY2("1.2.840.113549.1.9.15", "smimeCapabilities"), |
82 | | |
83 | | ENTRY2("1.2.840.113549.1.9.16.2.1", "aa-receiptRequest"), |
84 | | ENTRY2("1.2.840.113549.1.9.16.2.2", "aa-securityLabel"), |
85 | | ENTRY2("1.2.840.113549.1.9.16.2.3", "aa-mlExpandHistory"), |
86 | | ENTRY2("1.2.840.113549.1.9.16.2.4", "aa-contentHint"), |
87 | | ENTRY2("1.2.840.113549.1.9.16.2.9", "aa-equivalentLabels"), |
88 | | ENTRY2("1.2.840.113549.1.9.16.2.10", "aa-contentReference"), |
89 | | ENTRY2("1.2.840.113549.1.9.16.2.11", "aa-encrypKeyPref"), |
90 | | ENTRY2("1.2.840.113549.1.9.16.2.12", "aa-signingCertificate"), |
91 | | ENTRY2("1.2.840.113549.1.9.16.2.19", "aa-ets-otherSigCert"), |
92 | | ENTRY2("1.2.840.113549.1.9.16.2.47", "aa-signingCertificateV2"), |
93 | | |
94 | | { NULL, 0, NULL, 0, NULL, 0 } |
95 | | }; |
96 | | |
97 | | static void print_raw(gnutls_buffer_st *str, const char *prefix, |
98 | | const gnutls_datum_t *raw) |
99 | 19.5k | { |
100 | 19.5k | gnutls_datum_t result; |
101 | 19.5k | int ret; |
102 | | |
103 | 19.5k | if (raw->data == NULL || raw->size == 0) |
104 | 9.77k | return; |
105 | | |
106 | 9.77k | ret = gnutls_hex_encode2(raw, &result); |
107 | 9.77k | if (ret < 0) { |
108 | 0 | addf(str, "%s: [error]\n", prefix); |
109 | 0 | return; |
110 | 0 | } |
111 | | |
112 | 9.77k | addf(str, "%s: %s\n", prefix, result.data); |
113 | 9.77k | gnutls_free(result.data); |
114 | 9.77k | } |
115 | | |
116 | | static void print_pkcs7_info(gnutls_pkcs7_signature_info_st *info, |
117 | | gnutls_buffer_st *str, |
118 | | gnutls_certificate_print_formats_t format) |
119 | 9.77k | { |
120 | 9.77k | unsigned i; |
121 | 9.77k | char *oid; |
122 | 9.77k | gnutls_datum_t data; |
123 | 9.77k | char prefix[128]; |
124 | 9.77k | char s[42]; |
125 | 9.77k | size_t max; |
126 | 9.77k | int ret; |
127 | 9.77k | const struct oid_to_string *entry; |
128 | | |
129 | 9.77k | if (info->issuer_dn.size > 0) |
130 | 7.73k | print_dn(str, "\tSigner's issuer DN", &info->issuer_dn); |
131 | 9.77k | print_raw(str, "\tSigner's serial", &info->signer_serial); |
132 | 9.77k | print_raw(str, "\tSigner's issuer key ID", &info->issuer_keyid); |
133 | 9.77k | if (info->signing_time != -1) { |
134 | 0 | struct tm t; |
135 | 0 | if (gmtime_r(&info->signing_time, &t) == NULL) { |
136 | 0 | addf(str, "error: gmtime_r (%ld)\n", |
137 | 0 | (unsigned long)info->signing_time); |
138 | 0 | } else { |
139 | 0 | max = sizeof(s); |
140 | 0 | if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) == |
141 | 0 | 0) { |
142 | 0 | addf(str, "error: strftime (%ld)\n", |
143 | 0 | (unsigned long)info->signing_time); |
144 | 0 | } else { |
145 | 0 | addf(str, "\tSigning time: %s\n", s); |
146 | 0 | } |
147 | 0 | } |
148 | 0 | } |
149 | | |
150 | 9.77k | addf(str, "\tSignature Algorithm: %s\n", |
151 | 9.77k | gnutls_sign_get_name(info->algo)); |
152 | | |
153 | 9.77k | if (format == GNUTLS_CRT_PRINT_FULL) { |
154 | 9.77k | if (info->signed_attrs) { |
155 | 0 | for (i = 0;; i++) { |
156 | 0 | ret = gnutls_pkcs7_get_attr(info->signed_attrs, |
157 | 0 | i, &oid, &data, 0); |
158 | 0 | if (ret < 0) |
159 | 0 | break; |
160 | 0 | if (i == 0) |
161 | 0 | addf(str, "\tSigned Attributes:\n"); |
162 | |
|
163 | 0 | entry = _gnutls_oid_get_entry(pkcs7_attrs, oid); |
164 | 0 | snprintf(prefix, sizeof(prefix), "\t\t%s", |
165 | 0 | (entry && entry->name_desc) ? |
166 | 0 | entry->name_desc : |
167 | 0 | oid); |
168 | 0 | print_raw(str, prefix, &data); |
169 | 0 | gnutls_free(data.data); |
170 | 0 | } |
171 | 0 | } |
172 | 9.77k | if (info->unsigned_attrs) { |
173 | 0 | for (i = 0;; i++) { |
174 | 0 | ret = gnutls_pkcs7_get_attr( |
175 | 0 | info->unsigned_attrs, i, &oid, &data, |
176 | 0 | 0); |
177 | 0 | if (ret < 0) |
178 | 0 | break; |
179 | 0 | if (i == 0) |
180 | 0 | addf(str, "\tUnsigned Attributes:\n"); |
181 | |
|
182 | 0 | entry = _gnutls_oid_get_entry(pkcs7_attrs, oid); |
183 | 0 | snprintf(prefix, sizeof(prefix), "\t\t%s", |
184 | 0 | (entry && entry->name_desc) ? |
185 | 0 | entry->name_desc : |
186 | 0 | oid); |
187 | 0 | print_raw(str, prefix, &data); |
188 | 0 | gnutls_free(data.data); |
189 | 0 | } |
190 | 0 | } |
191 | 9.77k | } |
192 | 9.77k | adds(str, "\n"); |
193 | 9.77k | } |
194 | | |
195 | | /** |
196 | | * gnutls_pkcs7_print_signature_info: |
197 | | * @info: The PKCS7 signature info struct to be printed |
198 | | * @format: Indicate the format to use |
199 | | * @out: Newly allocated datum with null terminated string. |
200 | | * |
201 | | * This function will pretty print a PKCS #7 signature info structure, suitable |
202 | | * for display to a human. |
203 | | * |
204 | | * Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and |
205 | | * %GNUTLS_CRT_PRINT_COMPACT. |
206 | | * |
207 | | * The output @out needs to be deallocated using gnutls_free(). |
208 | | * |
209 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
210 | | * negative error value. |
211 | | * |
212 | | * Since: 3.6.14 |
213 | | **/ |
214 | | int gnutls_pkcs7_print_signature_info(gnutls_pkcs7_signature_info_st *info, |
215 | | gnutls_certificate_print_formats_t format, |
216 | | gnutls_datum_t *out) |
217 | 0 | { |
218 | 0 | gnutls_buffer_st str; |
219 | |
|
220 | 0 | _gnutls_buffer_init(&str); |
221 | 0 | print_pkcs7_info(info, &str, format); |
222 | |
|
223 | 0 | return _gnutls_buffer_to_datum(&str, out, 1); |
224 | 0 | } |
225 | | |
226 | | /** |
227 | | * gnutls_pkcs7_crt_print: |
228 | | * @pkcs7: The PKCS7 struct to be printed |
229 | | * @format: Indicate the format to use |
230 | | * @out: Newly allocated datum with null terminated string. |
231 | | * |
232 | | * This function will pretty print a signed PKCS #7 structure, suitable for |
233 | | * display to a human. |
234 | | * |
235 | | * Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and |
236 | | * %GNUTLS_CRT_PRINT_COMPACT. |
237 | | * |
238 | | * The output @out needs to be deallocated using gnutls_free(). |
239 | | * |
240 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
241 | | * negative error value. |
242 | | **/ |
243 | | int gnutls_pkcs7_print(gnutls_pkcs7_t pkcs7, |
244 | | gnutls_certificate_print_formats_t format, |
245 | | gnutls_datum_t *out) |
246 | 1.72k | { |
247 | 1.72k | int count, ret, i; |
248 | 1.72k | gnutls_pkcs7_signature_info_st info; |
249 | 1.72k | gnutls_buffer_st str; |
250 | 1.72k | const char *oid; |
251 | | |
252 | 1.72k | _gnutls_buffer_init(&str); |
253 | | |
254 | | /* For backwards compatibility with structures using the default OID, |
255 | | * we don't print the eContent Type explicitly */ |
256 | 1.72k | oid = gnutls_pkcs7_get_embedded_data_oid(pkcs7); |
257 | 1.72k | if (oid) { |
258 | 1.72k | if (!streq(oid, DATA_OID) && !streq(oid, DIGESTED_DATA_OID)) { |
259 | 1.71k | addf(&str, "eContent Type: %s\n", oid); |
260 | 1.71k | } |
261 | 1.72k | } |
262 | | |
263 | 11.5k | for (i = 0;; i++) { |
264 | 11.5k | if (i == 0) |
265 | 1.72k | addf(&str, "Signers:\n"); |
266 | | |
267 | 11.5k | ret = gnutls_pkcs7_get_signature_info(pkcs7, i, &info); |
268 | 11.5k | if (ret < 0) |
269 | 1.72k | break; |
270 | | |
271 | 9.77k | print_pkcs7_info(&info, &str, format); |
272 | 9.77k | gnutls_pkcs7_signature_info_deinit(&info); |
273 | 9.77k | } |
274 | | |
275 | 1.72k | if (format == GNUTLS_CRT_PRINT_FULL) { |
276 | 1.72k | gnutls_datum_t data, b64; |
277 | | |
278 | 1.72k | count = gnutls_pkcs7_get_crt_count(pkcs7); |
279 | | |
280 | 1.72k | if (count > 0) { |
281 | 253 | addf(&str, "Number of certificates: %u\n\n", count); |
282 | | |
283 | 730k | for (i = 0; i < count; i++) { |
284 | 730k | ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, |
285 | 730k | &data); |
286 | 730k | if (ret < 0) { |
287 | 0 | addf(&str, |
288 | 0 | "Error: cannot print certificate %d\n", |
289 | 0 | i); |
290 | 0 | continue; |
291 | 0 | } |
292 | | |
293 | 730k | ret = gnutls_pem_base64_encode_alloc( |
294 | 730k | "CERTIFICATE", &data, &b64); |
295 | 730k | if (ret < 0) { |
296 | 0 | gnutls_free(data.data); |
297 | 0 | continue; |
298 | 0 | } |
299 | | |
300 | 730k | adds(&str, (char *)b64.data); |
301 | 730k | adds(&str, "\n"); |
302 | 730k | gnutls_free(b64.data); |
303 | 730k | gnutls_free(data.data); |
304 | 730k | } |
305 | 253 | } |
306 | | |
307 | 1.72k | count = gnutls_pkcs7_get_crl_count(pkcs7); |
308 | 1.72k | if (count > 0) { |
309 | 145 | addf(&str, "Number of CRLs: %u\n\n", count); |
310 | | |
311 | 86.9k | for (i = 0; i < count; i++) { |
312 | 86.8k | ret = gnutls_pkcs7_get_crl_raw2(pkcs7, i, |
313 | 86.8k | &data); |
314 | 86.8k | if (ret < 0) { |
315 | 0 | addf(&str, |
316 | 0 | "Error: cannot print certificate %d\n", |
317 | 0 | i); |
318 | 0 | continue; |
319 | 0 | } |
320 | | |
321 | 86.8k | ret = gnutls_pem_base64_encode_alloc( |
322 | 86.8k | "X509 CRL", &data, &b64); |
323 | 86.8k | if (ret < 0) { |
324 | 0 | gnutls_free(data.data); |
325 | 0 | continue; |
326 | 0 | } |
327 | | |
328 | 86.8k | adds(&str, (char *)b64.data); |
329 | 86.8k | adds(&str, "\n"); |
330 | 86.8k | gnutls_free(b64.data); |
331 | 86.8k | gnutls_free(data.data); |
332 | 86.8k | } |
333 | 145 | } |
334 | 1.72k | } |
335 | | |
336 | 1.72k | return _gnutls_buffer_to_datum(&str, out, 1); |
337 | 1.72k | } |