Coverage Report

Created: 2025-04-22 06:17

/src/neomutt/ncrypt/pgplib.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Misc PGP helper routines
4
 *
5
 * @authors
6
 * Copyright (C) 2017-2023 Richard Russon <rich@flatcap.org>
7
 * Copyright (C) 2020 Pietro Cerutti <gahr@gahr.ch>
8
 *
9
 * @copyright
10
 * This program is free software: you can redistribute it and/or modify it under
11
 * the terms of the GNU General Public License as published by the Free Software
12
 * Foundation, either version 2 of the License, or (at your option) any later
13
 * version.
14
 *
15
 * This program is distributed in the hope that it will be useful, but WITHOUT
16
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18
 * details.
19
 *
20
 * You should have received a copy of the GNU General Public License along with
21
 * this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
/**
25
 * @page crypt_pgplib Misc PGP helper routines
26
 *
27
 * Misc PGP helper routines
28
 */
29
30
#include "config.h"
31
#include <stdbool.h>
32
#include "mutt/lib.h"
33
#ifdef CRYPT_BACKEND_CLASSIC_PGP
34
#include "pgplib.h"
35
#endif
36
37
/**
38
 * pgp_pkalgbytype - Get the name of the algorithm from its ID
39
 * @param type Algorithm ID
40
 * @retval ptr Algorithm name
41
 */
42
const char *pgp_pkalgbytype(unsigned char type)
43
0
{
44
0
  switch (type)
45
0
  {
46
0
    case 1:
47
0
      return "RSA";
48
0
    case 2:
49
0
      return "RSA";
50
0
    case 3:
51
0
      return "RSA";
52
0
    case 16:
53
0
      return "ElG";
54
0
    case 17:
55
0
      return "DSA";
56
0
    case 20:
57
0
      return "ElG";
58
0
    default:
59
0
      return "unk";
60
0
  }
61
0
}
62
63
/**
64
 * pgp_canencrypt - Does this algorithm ID support encryption?
65
 * @param type Algorithm ID
66
 * @retval true Algorithm does support encryption
67
 */
68
bool pgp_canencrypt(unsigned char type)
69
0
{
70
0
  switch (type)
71
0
  {
72
0
    case 1:
73
0
    case 2:
74
0
    case 16:
75
0
    case 20:
76
0
      return true;
77
0
    default:
78
0
      return false;
79
0
  }
80
0
}
81
82
/**
83
 * pgp_cansign - Does this algorithm ID support signing?
84
 * @param type Algorithm ID
85
 * @retval true Algorithm does support signing
86
 */
87
bool pgp_cansign(unsigned char type)
88
0
{
89
0
  switch (type)
90
0
  {
91
0
    case 1:
92
0
    case 3:
93
0
    case 17:
94
0
    case 20:
95
0
      return true;
96
0
    default:
97
0
      return false;
98
0
  }
99
0
}
100
101
/**
102
 * pgp_uid_free - Free a PGP UID
103
 * @param[out] upp PGP UID to free
104
 */
105
static void pgp_uid_free(struct PgpUid **upp)
106
0
{
107
0
  struct PgpUid *up = NULL, *q = NULL;
108
109
0
  if (!upp || !*upp)
110
0
    return;
111
0
  for (up = *upp; up; up = q)
112
0
  {
113
0
    q = up->next;
114
0
    FREE(&up->addr);
115
0
    FREE(&up);
116
0
  }
117
118
0
  *upp = NULL;
119
0
}
120
121
/**
122
 * pgp_copy_uids - Copy a list of PGP UIDs
123
 * @param up     List of PGP UIDs
124
 * @param parent Parent PGP key
125
 * @retval ptr New list of PGP UIDs
126
 */
127
struct PgpUid *pgp_copy_uids(struct PgpUid *up, struct PgpKeyInfo *parent)
128
0
{
129
0
  struct PgpUid *l = NULL;
130
0
  struct PgpUid **lp = &l;
131
132
0
  for (; up; up = up->next)
133
0
  {
134
0
    *lp = MUTT_MEM_CALLOC(1, struct PgpUid);
135
0
    (*lp)->trust = up->trust;
136
0
    (*lp)->flags = up->flags;
137
0
    (*lp)->addr = mutt_str_dup(up->addr);
138
0
    (*lp)->parent = parent;
139
0
    lp = &(*lp)->next;
140
0
  }
141
142
0
  return l;
143
0
}
144
145
/**
146
 * key_free - Free a PGP Key info
147
 * @param[out] ptr PGP Key info to free
148
 */
149
static void key_free(struct PgpKeyInfo **ptr)
150
0
{
151
0
  if (!ptr || !*ptr)
152
0
    return;
153
154
0
  struct PgpKeyInfo *key = *ptr;
155
156
0
  pgp_uid_free(&key->address);
157
0
  FREE(&key->keyid);
158
0
  FREE(&key->fingerprint);
159
160
0
  FREE(ptr);
161
0
}
162
163
/**
164
 * pgp_remove_key - Remove a PGP key from a list
165
 * @param[out] klist List of PGP Keys
166
 * @param[in]  key   Key to remove
167
 * @retval ptr Updated list of PGP Keys
168
 */
169
struct PgpKeyInfo *pgp_remove_key(struct PgpKeyInfo **klist, struct PgpKeyInfo *key)
170
0
{
171
0
  if (!klist || !*klist || !key)
172
0
    return NULL;
173
174
0
  struct PgpKeyInfo **last = NULL;
175
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
176
177
0
  if (key->parent && (key->parent != key))
178
0
    key = key->parent;
179
180
0
  last = klist;
181
0
  for (p = *klist; p && p != key; p = p->next)
182
0
    last = &p->next;
183
184
0
  if (!p)
185
0
    return NULL;
186
187
0
  for (q = p->next, r = p; q && q->parent == p; q = q->next)
188
0
    r = q;
189
190
0
  if (r)
191
0
    r->next = NULL;
192
193
0
  *last = q;
194
0
  return q;
195
0
}
196
197
/**
198
 * pgp_key_free - Free a PGP key info
199
 * @param[out] kpp PGP key info to free
200
 */
201
void pgp_key_free(struct PgpKeyInfo **kpp)
202
0
{
203
0
  if (!kpp || !*kpp)
204
0
    return;
205
206
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
207
208
0
  if ((*kpp)->parent && ((*kpp)->parent != *kpp))
209
0
    *kpp = (*kpp)->parent;
210
211
  /* Order is important here:
212
   *
213
   * - First free all children.
214
   * - If we are an orphan (i.e., our parent was not in the key list),
215
   *   free our parent.
216
   * - free ourselves.  */
217
218
0
  for (p = *kpp; p; p = q)
219
0
  {
220
0
    for (q = p->next; q && q->parent == p; q = r)
221
0
    {
222
0
      r = q->next;
223
0
      key_free(&q);
224
0
    }
225
226
0
    key_free(&p->parent);
227
0
    key_free(&p);
228
0
  }
229
230
0
  *kpp = NULL;
231
0
}