Doc fixes.
[gnutls:gnutls.git] / lib / openpgp / output.c
1 /*
2  * Copyright (C) 2007, 2008 Free Software Foundation
3  *
4  * Author: Simon Josefsson, Nikos Mavrogiannopoulos
5  *
6  * This file is part of GNUTLS.
7  *
8  * The GNUTLS library 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
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301, USA
22  *
23  */
24
25 /* Functions for printing X.509 Certificate structures
26  */
27
28 #include <gnutls_int.h>
29 #include <gnutls/openpgp.h>
30 #include <gnutls_errors.h>
31
32 /* I18n of error codes. */
33 #include "gettext.h"
34 #define _(String) dgettext (PACKAGE, String)
35 #define N_(String) gettext_noop (String)
36
37 #define addf _gnutls_string_append_printf
38 #define adds _gnutls_string_append_str
39
40 static void
41 hexdump (gnutls_string * str, const char *data, size_t len, const char *spc)
42 {
43   size_t j;
44
45   if (spc)
46     adds (str, spc);
47   for (j = 0; j < len; j++)
48     {
49       if (((j + 1) % 16) == 0)
50         {
51           addf (str, "%.2x\n", (unsigned char) data[j]);
52           if (spc && j != (len - 1))
53             adds (str, spc);
54         }
55       else if (j == (len - 1))
56         addf (str, "%.2x", (unsigned char) data[j]);
57       else
58         addf (str, "%.2x:", (unsigned char) data[j]);
59     }
60   if ((j % 16) != 0)
61     adds (str, "\n");
62 }
63
64 static void
65 hexprint (gnutls_string * str, const char *data, size_t len)
66 {
67   size_t j;
68
69   if (len == 0)
70     adds (str, "00");
71   else
72     {
73       for (j = 0; j < len; j++)
74         addf (str, "%.2x", (unsigned char) data[j]);
75     }
76 }
77
78 static void
79 print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int idx)
80 {
81   unsigned int key_usage;
82   int err;
83
84   addf (str, _("\t\tKey Usage:\n"));
85
86
87   if (idx == -1)
88     err = gnutls_openpgp_crt_get_key_usage (cert, &key_usage);
89   else
90     err = gnutls_openpgp_crt_get_subkey_usage (cert, idx, &key_usage);
91   if (err < 0)
92     {
93       addf (str, _("error: get_key_usage: %s\n"), gnutls_strerror (err));
94       return;
95     }
96
97   if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
98     addf (str, _("\t\t\tDigital signatures.\n"));
99   if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
100     addf (str, _("\t\t\tCommunications encipherment.\n"));
101   if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
102     addf (str, _("\t\t\tStorage data encipherment.\n"));
103   if (key_usage & GNUTLS_KEY_KEY_AGREEMENT)
104     addf (str, _("\t\t\tAuthentication.\n"));
105   if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN)
106     addf (str, _("\t\t\tCertificate signing.\n"));
107 }
108
109 /* idx == -1 indicates main key
110  * otherwise the subkey.
111  */
112 static void
113 print_key_id (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
114 {
115     gnutls_openpgp_keyid_t id;
116     int err;
117
118     if (idx < 0)
119       err = gnutls_openpgp_crt_get_key_id (cert, id);
120     else
121       err = gnutls_openpgp_crt_get_subkey_id( cert, idx, id);
122
123     if (err < 0)
124       addf (str, "error: get_key_id: %s\n", gnutls_strerror (err));
125     else
126       {
127         addf (str, _("\tID (hex): "));
128         hexprint (str, id, sizeof(id));
129         addf (str, "\n");
130       }
131 }
132
133 /* idx == -1 indicates main key
134  * otherwise the subkey.
135  */
136 static void
137 print_key_fingerprint (gnutls_string * str, gnutls_openpgp_crt_t cert)
138 {
139     char fpr[128];
140     size_t fpr_size = sizeof (fpr);
141     int err;
142
143     err = gnutls_openpgp_crt_get_fingerprint (cert, fpr, &fpr_size);
144     if (err < 0)
145       addf (str, "error: get_fingerprint: %s\n", gnutls_strerror (err));
146     else
147       {
148         addf (str, _("\tFingerprint (hex): "));
149         hexprint (str, fpr, fpr_size);
150         addf (str, "\n");
151       }
152 }
153
154 static void
155 print_key_revoked (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
156 {
157     int err;
158
159     if (idx < 0)
160       err = gnutls_openpgp_crt_get_revoked_status (cert);
161     else
162       err = gnutls_openpgp_crt_get_subkey_revoked_status( cert, idx);
163
164     if (err != 0)
165       addf (str, "\tRevoked: True\n");
166     else
167       addf (str, "\tRevoked: False\n");
168 }
169
170 static void
171 print_key_times(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
172 {
173     time_t tim;
174
175     addf (str, _("\tTime stamps:\n"));
176
177     if (idx == -1)
178       tim = gnutls_openpgp_crt_get_creation_time (cert);
179     else
180       tim = gnutls_openpgp_crt_get_subkey_creation_time (cert, idx);
181       
182     {
183       char s[42];
184       size_t max = sizeof (s);
185       struct tm t;
186
187       if (gmtime_r (&tim, &t) == NULL)
188         addf (str, "error: gmtime_r (%d)\n", t);
189       else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0)
190         addf (str, "error: strftime (%d)\n", t);
191       else
192         addf (str, _("\t\tCreation: %s\n"), s);
193     }
194
195     if (idx == -1)
196       tim = gnutls_openpgp_crt_get_expiration_time (cert);
197     else
198       tim = gnutls_openpgp_crt_get_subkey_expiration_time (cert, idx);
199     {
200       char s[42];
201       size_t max = sizeof (s);
202       struct tm t;
203
204       if (gmtime_r (&tim, &t) == NULL)
205         addf (str, "error: gmtime_r (%d)\n", t);
206       else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0)
207         addf (str, "error: strftime (%d)\n", t);
208       else
209         addf (str, _("\t\tExpiration: %s\n"), s);
210     }
211 }
212
213 static void
214 print_key_info(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
215 {
216     int err;
217     unsigned int bits;
218
219     if (idx == -1)
220       err = gnutls_openpgp_crt_get_pk_algorithm (cert, &bits);
221     else
222       err = gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, &bits);
223
224     if (err < 0)
225       addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err));
226     else
227       {
228         const char *name = gnutls_pk_algorithm_get_name (err);
229         if (name == NULL)
230           name = "Unknown";
231
232         addf (str, _("\tPublic Key Algorithm: %s\n"), name);
233         switch (err)
234           {
235           case GNUTLS_PK_RSA:
236             {
237               gnutls_datum_t m, e;
238
239               if (idx == -1)
240                 err = gnutls_openpgp_crt_get_pk_rsa_raw (cert, &m, &e);
241               else
242                 err = gnutls_openpgp_crt_get_subkey_pk_rsa_raw (cert, idx, &m, &e);
243                 
244               if (err < 0)
245                 addf (str, "error: get_pk_rsa_raw: %s\n",
246                       gnutls_strerror (err));
247               else
248                 {
249                   addf (str, _("\t\tModulus (bits %d):\n"), bits);
250                   hexdump (str, m.data, m.size, "\t\t\t");
251                   addf (str, _("\t\tExponent:\n"));
252                   hexdump (str, e.data, e.size, "\t\t\t");
253
254                   gnutls_free (m.data);
255                   gnutls_free (e.data);
256                 }
257
258             }
259             break;
260
261           case GNUTLS_PK_DSA:
262             {
263               gnutls_datum_t p, q, g, y;
264
265               if (idx == -1)
266                 err = gnutls_openpgp_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y);
267               else
268                 err = gnutls_openpgp_crt_get_subkey_pk_dsa_raw (cert, idx, &p, &q, &g, &y);
269               if (err < 0)
270                 addf (str, "error: get_pk_dsa_raw: %s\n",
271                       gnutls_strerror (err));
272               else
273                 {
274                   addf (str, _("\t\tPublic key (bits %d):\n"), bits);
275                   hexdump (str, y.data, y.size, "\t\t\t");
276                   addf (str, _("\t\tP:\n"));
277                   hexdump (str, p.data, p.size, "\t\t\t");
278                   addf (str, _("\t\tQ:\n"));
279                   hexdump (str, q.data, q.size, "\t\t\t");
280                   addf (str, _("\t\tG:\n"));
281                   hexdump (str, g.data, g.size, "\t\t\t");
282
283                   gnutls_free (p.data);
284                   gnutls_free (q.data);
285                   gnutls_free (g.data);
286                   gnutls_free (y.data);
287                 }
288             }
289             break;
290
291           default:
292             break;
293           }
294       }
295 }
296
297
298 static void
299 print_cert (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int format)
300 {
301 int i, subkeys;
302 int err;
303 char dn[1024];
304 size_t dn_size;
305
306   print_key_revoked( str, cert, -1);
307
308   /* Version. */
309   {
310     int version = gnutls_openpgp_crt_get_version (cert);
311     if (version < 0)
312       addf (str, "error: get_version: %s\n", gnutls_strerror (version));
313     else
314       addf (str, _("\tVersion: %d\n"), version);
315   }
316
317   /* ID. */
318   print_key_id( str, cert, -1);
319
320   print_key_fingerprint( str, cert);
321
322   /* Names. */
323   i = 0;
324   do {
325       dn_size = sizeof(dn);
326       err = gnutls_openpgp_crt_get_name (cert, i++, dn, &dn_size);
327
328       if (err < 0 && err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE &&
329           err != GNUTLS_E_OPENPGP_UID_REVOKED)
330         {
331           addf (str, "error: get_name: %s %d\n", gnutls_strerror (err), err);
332           break;
333         }
334
335       if (err >= 0)
336         addf (str, _("\tName[%d]: %s\n"), i-1, dn);
337       else if (err == GNUTLS_E_OPENPGP_UID_REVOKED) {
338         addf (str, _("\tRevoked Name[%d]: %s\n"), i-1, dn);
339       }
340
341   } while( err >= 0);
342
343   print_key_times( str, cert, -1);
344
345   print_key_info( str, cert, -1);
346   print_key_usage( str, cert, -1);
347
348   subkeys = gnutls_openpgp_crt_get_subkey_count( cert);
349   if (subkeys < 0)
350     return;
351
352   for (i=0;i<subkeys;i++) {
353     addf( str, _("\n\tSubkey[%d]:\n"), i);
354
355     print_key_revoked( str, cert, i);
356     print_key_id( str, cert, i);
357     print_key_times( str, cert, i);
358     print_key_info( str, cert, i);
359     print_key_usage( str, cert, i);
360   }
361
362 }
363
364 /**
365  * gnutls_openpgp_crt_print - Pretty print OpenPGP certificates
366  * @cert: The structure to be printed
367  * @format: Indicate the format to use
368  * @out: Newly allocated datum with zero terminated string.
369  *
370  * This function will pretty print an OpenPGP certificate, suitable
371  * for display to a human.
372  *
373  * The format should be zero for future compatibility.
374  *
375  * The output @out needs to be deallocate using gnutls_free().
376  *
377  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
378  **/
379 int
380 gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert,
381                        gnutls_certificate_print_formats_t format,
382                        gnutls_datum_t *out)
383 {
384   gnutls_string str;
385
386   _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
387
388   _gnutls_string_append_str (&str, _("OpenPGP Certificate Information:\n"));
389
390   print_cert (&str, cert, format);
391
392   _gnutls_string_append_data (&str, "\0", 1);
393   out->data = str.data;
394   out->size = strlen (str.data);
395
396   return 0;
397 }
398