1 /* private-keys.c - Parser and writer for the extended private key format.
2 * Copyright (C) 2016 g10 Code GmbH
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * GnuPG is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <http://www.gnu.org/licenses/>.
33 #include <gpg-error.h>
36 #include "private-keys.h"
41 struct private_key_container
43 struct private_key_entry *first;
44 struct private_key_entry *last;
48 struct private_key_entry
50 struct private_key_entry *prev;
51 struct private_key_entry *next;
53 /* The name. Comments and blank lines have NAME set to NULL. */
56 /* The value as stored in the file. We store it when when we parse
57 a file so that we can reproduce it. */
60 /* The decoded value. */
66 static inline gpg_error_t
67 my_error_from_syserror (void)
69 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
75 /* Allocation and deallocation. */
77 /* Allocate a private key container structure. */
81 return xtrycalloc (1, sizeof (struct private_key_container));
86 pke_release (pke_t entry)
93 wipememory (entry->value, strlen (entry->value));
95 free_strlist_wipe (entry->raw_value);
100 /* Release a private key container structure. */
102 pkc_release (pkc_t pk)
109 for (e = pk->first; e; e = next)
120 /* Dealing with names and values. */
122 /* Check whether the given name is valid. Valid names start with a
123 letter, end with a colon, and contain only alphanumeric characters
126 valid_name (const char *name)
128 size_t i, len = strlen (name);
130 if (! alphap (name) || len == 0 || name[len - 1] != ':')
133 for (i = 1; i < len - 1; i++)
134 if (! alnump (&name[i]) && name[i] != '-')
141 /* Makes sure that ENTRY has a RAW_VALUE. */
143 assert_raw_value (pke_t entry)
150 if (entry->raw_value)
153 len = strlen (entry->value);
157 size_t amount, linelen = LINELEN;
159 /* On the first line we need to subtract space for the name. */
160 if (entry->raw_value == NULL && strlen (entry->name) < linelen)
161 linelen -= strlen (entry->name);
163 /* See if the rest of the value fits in this line. */
170 /* Find a suitable space to break on. */
171 for (i = linelen - 1; linelen - i < 30 && linelen - i > offset; i--)
172 if (ascii_isspace (entry->value[i]))
175 if (ascii_isspace (entry->value[i]))
182 /* Just induce a hard break. */
187 snprintf (buf, sizeof buf, " %.*s\n", (int) amount,
188 &entry->value[offset]);
189 if (append_to_strlist_try (&entry->raw_value, buf) == NULL)
191 err = my_error_from_syserror ();
202 free_strlist_wipe (entry->raw_value);
203 entry->raw_value = NULL;
211 /* Computes the length of the value encoded as continuation. If
212 *SWALLOW_WS is set, all whitespace at the beginning of S is
213 swallowed. If START is given, a pointer to the beginning of the
214 value is stored there. */
216 continuation_length (const char *s, int *swallow_ws, const char **start)
222 /* The previous line was a blank line and we inserted a newline.
223 Swallow all whitespace at the beginning of this line. */
224 while (ascii_isspace (*s))
229 /* Iff a continuation starts with more than one space, it
231 if (ascii_isspace (*s))
235 /* Strip whitespace at the end. */
237 while (len > 0 && ascii_isspace (s[len-1]))
242 /* Blank lines encode newlines. */
257 /* Makes sure that ENTRY has a VALUE. */
259 assert_value (pke_t entry)
271 for (s = entry->raw_value; s; s = s->next)
272 len += continuation_length (s->d, &swallow_ws, NULL);
274 /* Add one for the terminating zero. */
277 entry->value = p = xtrymalloc (len);
278 if (entry->value == NULL)
279 return my_error_from_syserror ();
282 for (s = entry->raw_value; s; s = s->next)
285 size_t l = continuation_length (s->d, &swallow_ws, &start);
287 memcpy (p, start, l);
292 assert (p - entry->value == len);
308 pke_value (pke_t pke)
310 if (assert_value (pke))
317 /* Adding and modifying values. */
319 /* Add (NAME, VALUE, RAW_VALUE) to PK. NAME may be NULL for comments
320 and blank lines. At least one of VALUE and RAW_VALUE must be
321 given. If PRESERVE_ORDER is not given, entries with the same name
322 are grouped. NAME, VALUE and RAW_VALUE is consumed. */
324 _pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value,
330 assert (value || raw_value);
332 if (name && ! valid_name (name))
334 err = gpg_error (GPG_ERR_INV_NAME);
338 if (name && ascii_strcasecmp (name, "Key:") == 0 && pkc_lookup (pk, "Key:"))
340 err = gpg_error (GPG_ERR_INV_NAME);
344 e = xtrycalloc (1, sizeof *e);
347 err = my_error_from_syserror ();
353 e->raw_value = raw_value;
359 if (preserve_order || name == NULL)
363 /* See if there is already an entry with NAME. */
364 last = pkc_lookup (pk, name);
366 /* If so, find the last in that block. */
371 pke_t next = last->next;
373 if (next->name && ascii_strcasecmp (next->name, name) == 0)
379 else /* Otherwise, just find the last entry. */
386 e->next = last->next;
398 pk->first = pk->last = e;
405 wipememory (value, strlen (value));
407 free_strlist_wipe (raw_value);
414 /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it
415 is not updated but the new entry is appended. */
417 pkc_add (pkc_t pk, const char *name, const char *value)
421 k = xtrystrdup (name);
423 return my_error_from_syserror ();
425 v = xtrystrdup (value);
429 return my_error_from_syserror ();
432 return _pkc_add (pk, k, v, NULL, 0);
436 /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it
437 is updated with VALUE. If multiple entries with NAME exist, the
438 first entry is updated. */
440 pkc_set (pkc_t pk, const char *name, const char *value)
444 if (! valid_name (name))
445 return GPG_ERR_INV_NAME;
447 e = pkc_lookup (pk, name);
452 v = xtrystrdup (value);
454 return my_error_from_syserror ();
456 free_strlist_wipe (e->raw_value);
459 wipememory (e->value, strlen (e->value));
466 return pkc_add (pk, name, value);
470 /* Delete the given entry from PK. */
472 pkc_delete (pkc_t pk, pke_t entry)
475 entry->prev->next = entry->next;
477 pk->first = entry->next;
480 entry->next->prev = entry->prev;
482 pk->last = entry->prev;
489 /* Lookup and iteration. */
491 /* Get the first non-comment entry. */
496 for (entry = pk->first; entry; entry = entry->next)
503 /* Get the first entry with the given name. */
505 pkc_lookup (pkc_t pk, const char *name)
508 for (entry = pk->first; entry; entry = entry->next)
509 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
515 /* Get the next non-comment entry. */
517 pke_next (pke_t entry)
519 for (entry = entry->next; entry; entry = entry->next)
526 /* Get the next entry with the given name. */
528 pke_next_value (pke_t entry, const char *name)
530 for (entry = entry->next; entry; entry = entry->next)
531 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
538 /* Private key handling. */
540 /* Get the private key. */
542 pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp)
547 e = pkc_lookup (pk, "Key:");
549 return gpg_error (GPG_ERR_MISSING_KEY);
551 err = assert_value (e);
555 return gcry_sexp_sscan (retsexp, NULL, e->value, strlen (e->value));
559 /* Set the private key. */
561 pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp)
564 char *raw, *clean, *p;
567 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
569 raw = xtrymalloc (len);
571 return my_error_from_syserror ();
573 clean = xtrymalloc (len);
577 return my_error_from_syserror ();
580 gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, raw, len);
582 /* Strip any whitespace at the end. */
583 i = strlen (raw) - 1;
584 while (i && ascii_isspace (raw[i]))
590 /* Replace any newlines with spaces, remove superfluous whitespace. */
592 for (p = clean, i = 0; i < len; i++)
596 /* Collapse contiguous and superfluous spaces. */
597 if (ascii_isspace (c) && i > 0
598 && (ascii_isspace (raw[i-1]) || raw[i-1] == '(' || raw[i-1] == ')'))
608 err = pkc_set (pk, "Key:", clean);
616 /* Parsing and serialization. */
618 /* Parse STREAM and return a newly allocated private key container
619 structure in RESULT. If ERRLINEP is given, the line number the
620 parser was last considering is stored there. */
622 pkc_parse (pkc_t *result, int *errlinep, estream_t stream)
629 strlist_t raw_value = NULL;
632 *result = pkc_new ();
634 return my_error_from_syserror ();
638 while ((len = es_read_line (stream, &buf, &buf_len, NULL)))
644 /* Skip any whitespace. */
645 for (p = buf; *p && ascii_isspace (*p); p++)
648 if (name && (spacep (buf) || *p == 0))
650 /* A continuation. */
651 if (append_to_strlist_try (&raw_value, buf) == NULL)
653 err = my_error_from_syserror ();
659 /* No continuation. Add the current entry if any. */
662 err = _pkc_add (*result, name, NULL, raw_value, 1);
667 /* And prepare for the next one. */
671 if (*p != 0 && *p != '#')
673 char *colon, *value, tmp;
675 colon = strchr (buf, ':');
678 err = gpg_error (GPG_ERR_INV_VALUE);
685 name = xtrystrdup (p);
690 err = my_error_from_syserror ();
694 if (append_to_strlist_try (&raw_value, value) == NULL)
696 err = my_error_from_syserror ();
702 if (append_to_strlist_try (&raw_value, buf) == NULL)
704 err = my_error_from_syserror ();
709 /* Add the final entry. */
711 err = _pkc_add (*result, name, NULL, raw_value, 1);
717 pkc_release (*result);
725 /* Write a representation of PK to STREAM. */
727 pkc_write (pkc_t pk, estream_t stream)
733 for (entry = pk->first; entry; entry = entry->next)
736 es_fputs (entry->name, stream);
738 err = assert_raw_value (entry);
742 for (s = entry->raw_value; s; s = s->next)
743 es_fputs (s->d, stream);
745 if (es_ferror (stream))
746 return my_error_from_syserror ();