Coverage Report

Created: 2026-04-12 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/free-packet.c
Line
Count
Source
1
/* free-packet.c - cleanup stuff for packets
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3
 *               2005, 2010  Free Software Foundation, Inc.
4
 *
5
 * This file is part of GnuPG.
6
 *
7
 * GnuPG is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * GnuPG is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "gpg.h"
27
#include "../common/util.h"
28
#include "packet.h"
29
#include "../common/iobuf.h"
30
#include "options.h"
31
32
33
/* This is a wrapper for mpi_copy which handles opaque MPIs with a
34
 * NULL pointer as opaque data; e.g. gcry_mpi_set_opaque(a, NULL, 0).
35
 * It seems that at least gcry_mpi_set_opaque_copy does not yet handle
36
 * this correctly.  */
37
static gcry_mpi_t
38
my_mpi_copy (gcry_mpi_t a)
39
14.5k
{
40
14.5k
  if (a
41
14.5k
      && gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
42
7.81k
      && !gcry_mpi_get_opaque (a, NULL))
43
118
    return NULL;
44
45
14.4k
  return gcry_mpi_copy (a);
46
14.5k
}
47
48
49
void
50
free_symkey_enc( PKT_symkey_enc *enc )
51
1.80k
{
52
1.80k
  if (enc)
53
1.80k
    xfree (enc->seskey);
54
1.80k
  xfree(enc);
55
1.80k
}
56
57
58
/* This is the core of free_pubkey_enc but does only release the
59
 * allocated members of ENC.  */
60
void
61
release_pubkey_enc_parts (PKT_pubkey_enc *enc)
62
957
{
63
957
  int n, i;
64
957
  n = pubkey_get_nenc( enc->pubkey_algo );
65
957
  if (!n)
66
957
    mpi_release (enc->data[0]);
67
1.99k
  for (i=0; i < n; i++ )
68
1.04k
    mpi_release (enc->data[i]);
69
957
}
70
71
void
72
free_pubkey_enc (PKT_pubkey_enc *enc)
73
957
{
74
957
  release_pubkey_enc_parts (enc);
75
957
  xfree (enc);
76
957
}
77
78
79
/* Copy everything from SRC to DST.  This assumes that DST has been
80
 * malloced or statically allocated. */
81
void
82
copy_pubkey_enc_parts (PKT_pubkey_enc *dst, PKT_pubkey_enc *src)
83
0
{
84
0
  int n, i;
85
86
0
  dst->keyid[0] = src->keyid[0];
87
0
  dst->keyid[1] = src->keyid[1];
88
0
  dst->version  = src->version;
89
0
  dst->pubkey_algo = src->pubkey_algo;
90
0
  dst->seskey_algo = src->seskey_algo;
91
0
  dst->throw_keyid = src->throw_keyid;
92
93
0
  if (!(n = pubkey_get_nenc (dst->pubkey_algo)))
94
0
    n = 1;  /* All data is in the first item as an opaque MPI. */
95
0
  for (i=0; i < n; i++)
96
0
    dst->data[i] = my_mpi_copy (src->data[i]);
97
0
  for (; i < PUBKEY_MAX_NENC; i++)
98
0
    dst->data[i] = NULL;
99
0
}
100
101
102
void
103
free_seckey_enc( PKT_signature *sig )
104
10.5M
{
105
10.5M
  int n, i;
106
107
10.5M
  n = pubkey_get_nsig( sig->pubkey_algo );
108
10.5M
  if( !n )
109
10.5M
    mpi_release(sig->data[0]);
110
31.2M
  for(i=0; i < n; i++ )
111
20.7M
    mpi_release( sig->data[i] );
112
113
10.5M
  xfree(sig->revkey);
114
10.5M
  xfree(sig->hashed);
115
10.5M
  xfree(sig->unhashed);
116
117
10.5M
  xfree (sig->signers_uid);
118
119
10.5M
  xfree(sig);
120
10.5M
}
121
122
123
void
124
release_public_key_parts (PKT_public_key *pk)
125
536k
{
126
536k
  int n, i;
127
128
536k
  if (pk->seckey_info)
129
4.45k
    n = pubkey_get_nskey (pk->pubkey_algo);
130
532k
  else
131
532k
    n = pubkey_get_npkey (pk->pubkey_algo);
132
536k
  if (!n)
133
536k
    mpi_release (pk->pkey[0]);
134
2.10M
  for (i=0; i < n; i++ )
135
1.57M
    {
136
1.57M
      mpi_release (pk->pkey[i]);
137
1.57M
      pk->pkey[i] = NULL;
138
1.57M
    }
139
536k
  if (pk->seckey_info)
140
4.45k
    {
141
4.45k
      xfree (pk->seckey_info);
142
4.45k
      pk->seckey_info = NULL;
143
4.45k
    }
144
536k
  if (pk->prefs)
145
1.59k
    {
146
1.59k
      xfree (pk->prefs);
147
1.59k
      pk->prefs = NULL;
148
1.59k
    }
149
536k
  free_user_id (pk->user_id);
150
536k
  pk->user_id = NULL;
151
536k
  if (pk->revkey)
152
9
    {
153
9
      xfree(pk->revkey);
154
9
      pk->revkey=NULL;
155
9
      pk->numrevkeys=0;
156
9
    }
157
536k
  if (pk->serialno)
158
0
    {
159
0
      xfree (pk->serialno);
160
0
      pk->serialno = NULL;
161
0
    }
162
536k
  if (pk->updateurl)
163
0
    {
164
0
      xfree (pk->updateurl);
165
0
      pk->updateurl = NULL;
166
0
    }
167
536k
  if (pk->revoked.reason_comment)
168
0
    {
169
0
      xfree (pk->revoked.reason_comment);
170
0
      pk->revoked.reason_comment = NULL;
171
0
    }
172
536k
}
173
174
175
/* Free an allocated public key structure including all parts.
176
   Passing NULL is allowed.  */
177
void
178
free_public_key (PKT_public_key *pk)
179
541k
{
180
541k
  if (pk)
181
536k
    {
182
536k
      release_public_key_parts (pk);
183
536k
      xfree(pk);
184
536k
    }
185
541k
}
186
187
188
static subpktarea_t *
189
cp_subpktarea (subpktarea_t *s )
190
3.87k
{
191
3.87k
    subpktarea_t *d;
192
193
3.87k
    if( !s )
194
3.39k
  return NULL;
195
474
    d = xmalloc (sizeof (*d) + s->size - 1 );
196
474
    d->size = s->size;
197
474
    d->len = s->len;
198
474
    memcpy (d->data, s->data, s->len);
199
474
    return d;
200
3.87k
}
201
202
/*
203
 * Return a copy of the preferences
204
 */
205
prefitem_t *
206
copy_prefs (const prefitem_t *prefs)
207
158k
{
208
158k
    size_t n;
209
158k
    prefitem_t *new;
210
211
158k
    if (!prefs)
212
157k
        return NULL;
213
214
18.5k
    for (n=0; prefs[n].type; n++)
215
16.9k
        ;
216
1.59k
    new = xmalloc ( sizeof (*new) * (n+1));
217
18.5k
    for (n=0; prefs[n].type; n++) {
218
16.9k
        new[n].type = prefs[n].type;
219
16.9k
        new[n].value = prefs[n].value;
220
16.9k
    }
221
1.59k
    new[n].type = PREFTYPE_NONE;
222
1.59k
    new[n].value = 0;
223
224
1.59k
    return new;
225
158k
}
226
227
228
/* Copy the public key S to D.  If D is NULL allocate a new public key
229
 * structure.  Only the basic stuff is copied; not any ancillary
230
 * data.  */
231
PKT_public_key *
232
copy_public_key_basics (PKT_public_key *d, PKT_public_key *s)
233
5.24k
{
234
5.24k
  int n, i;
235
236
5.24k
  if (!d)
237
1.88k
    d = xmalloc (sizeof *d);
238
5.24k
  memcpy (d, s, sizeof *d);
239
5.24k
  d->seckey_info = NULL;
240
5.24k
  d->user_id = NULL;
241
5.24k
  d->prefs = NULL;
242
5.24k
  d->revoked.got_reason = 0;
243
5.24k
  d->revoked.reason_code = 0;
244
5.24k
  d->revoked.reason_comment = NULL;
245
5.24k
  d->revoked.reason_comment_len = 0;
246
247
5.24k
  n = pubkey_get_npkey (s->pubkey_algo);
248
5.24k
  i = 0;
249
5.24k
  if (!n)
250
397
    d->pkey[i++] = my_mpi_copy (s->pkey[0]);
251
4.85k
  else
252
4.85k
    {
253
15.9k
      for (; i < n; i++ )
254
11.0k
        d->pkey[i] = my_mpi_copy (s->pkey[i]);
255
4.85k
    }
256
30.4k
  for (; i < PUBKEY_MAX_NSKEY; i++)
257
25.2k
    d->pkey[i] = NULL;
258
259
5.24k
  d->revkey = NULL;
260
5.24k
  d->serialno = NULL;
261
5.24k
  d->updateurl = NULL;
262
263
5.24k
  return d;
264
5.24k
}
265
266
267
/* Copy the public key S to D.  If D is NULL allocate a new public key
268
   structure.  If S has seckret key infos, only the public stuff is
269
   copied.  */
270
PKT_public_key *
271
copy_public_key (PKT_public_key *d, PKT_public_key *s)
272
5.24k
{
273
5.24k
  d = copy_public_key_basics (d, s);
274
5.24k
  d->user_id = scopy_user_id (s->user_id);
275
5.24k
  d->prefs = copy_prefs (s->prefs);
276
277
5.24k
  if (!s->revkey && s->numrevkeys)
278
0
    BUG();
279
5.24k
  if (s->numrevkeys)
280
4
    {
281
4
      d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
282
4
      memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
283
4
    }
284
285
5.24k
  if (s->serialno)
286
0
    d->serialno = xstrdup (s->serialno);
287
5.24k
  if (s->updateurl)
288
0
    d->updateurl = xstrdup (s->updateurl);
289
5.24k
  if (s->revoked.got_reason)
290
176
    {
291
176
      d->revoked.got_reason = s->revoked.got_reason;
292
176
      d->revoked.reason_code = s->revoked.reason_code;
293
176
      if (s->revoked.reason_comment_len)
294
0
        {
295
0
          d->revoked.reason_comment = xmalloc (s->revoked.reason_comment_len);
296
0
          memcpy (d->revoked.reason_comment, s->revoked.reason_comment,
297
0
                  s->revoked.reason_comment_len);
298
0
          d->revoked.reason_comment_len = s->revoked.reason_comment_len;
299
0
        }
300
176
    }
301
302
5.24k
  return d;
303
5.24k
}
304
305
306
307
PKT_signature *
308
copy_signature( PKT_signature *d, PKT_signature *s )
309
1.93k
{
310
1.93k
    int n, i;
311
312
1.93k
    if( !d )
313
1.93k
  d = xmalloc(sizeof *d);
314
1.93k
    memcpy( d, s, sizeof *d );
315
1.93k
    n = pubkey_get_nsig( s->pubkey_algo );
316
1.93k
    if( !n )
317
697
  d->data[0] = my_mpi_copy(s->data[0]);
318
1.23k
    else {
319
3.61k
  for(i=0; i < n; i++ )
320
2.38k
      d->data[i] = my_mpi_copy( s->data[i] );
321
1.23k
    }
322
1.93k
    d->hashed = cp_subpktarea (s->hashed);
323
1.93k
    d->unhashed = cp_subpktarea (s->unhashed);
324
1.93k
    if (s->signers_uid)
325
1
      d->signers_uid = xstrdup (s->signers_uid);
326
1.93k
    if(s->numrevkeys)
327
0
      {
328
0
  d->revkey=NULL;
329
0
  d->numrevkeys=0;
330
0
  parse_revkeys(d);
331
0
      }
332
1.93k
    return d;
333
1.93k
}
334
335
336
/*
337
 * shallow copy of the user ID
338
 */
339
PKT_user_id *
340
scopy_user_id (PKT_user_id *s)
341
8.72k
{
342
8.72k
    if (s)
343
0
        s->ref++;
344
8.72k
    return s;
345
8.72k
}
346
347
348
349
void
350
free_comment( PKT_comment *rem )
351
876
{
352
876
    xfree(rem);
353
876
}
354
355
void
356
free_attributes(PKT_user_id *uid)
357
44.1k
{
358
44.1k
  if (!uid)
359
0
    return;
360
361
44.1k
  xfree(uid->attribs);
362
44.1k
  xfree(uid->attrib_data);
363
364
44.1k
  uid->attribs=NULL;
365
44.1k
  uid->attrib_data=NULL;
366
44.1k
  uid->attrib_len=0;
367
44.1k
}
368
369
void
370
free_user_id (PKT_user_id *uid)
371
584k
{
372
584k
  if (!uid)
373
540k
    return;
374
375
584k
  log_assert (uid->ref > 0);
376
44.1k
  if (--uid->ref)
377
0
    return;
378
379
44.1k
  free_attributes(uid);
380
44.1k
  xfree (uid->prefs);
381
44.1k
  xfree (uid->namehash);
382
44.1k
  xfree (uid->updateurl);
383
44.1k
  xfree (uid->mbox);
384
44.1k
  xfree (uid);
385
44.1k
}
386
387
void
388
free_compressed( PKT_compressed *zd )
389
364
{
390
364
  if (!zd)
391
0
    return;
392
393
364
  if (zd->buf)
394
364
    {
395
      /* We need to skip some bytes.  Because don't have any
396
       * information about the length, so we assume this is the last
397
       * packet */
398
484
      while (iobuf_read( zd->buf, NULL, 1<<30 ) != -1)
399
120
        ;
400
364
    }
401
364
  xfree(zd);
402
364
}
403
404
void
405
free_encrypted( PKT_encrypted *ed )
406
5.61k
{
407
5.61k
  if (!ed)
408
0
    return;
409
410
5.61k
  if (ed->buf)
411
5.47k
    {
412
      /* We need to skip some bytes. */
413
5.47k
      if (ed->is_partial)
414
1.90k
        {
415
1.95k
          while (iobuf_read( ed->buf, NULL, 1<<30 ) != -1)
416
43
            ;
417
1.90k
  }
418
3.56k
      else
419
3.56k
        {
420
3.87k
          while (ed->len)
421
303
            {
422
              /* Skip the packet. */
423
303
              int n = iobuf_read( ed->buf, NULL, ed->len );
424
303
              if (n == -1)
425
151
                ed->len = 0;
426
152
              else
427
152
                ed->len -= n;
428
303
            }
429
3.56k
  }
430
5.47k
    }
431
5.61k
  xfree (ed);
432
5.61k
}
433
434
435
void
436
free_plaintext( PKT_plaintext *pt )
437
462
{
438
462
  if (!pt)
439
0
    return;
440
441
462
  if (pt->buf)
442
462
    { /* We need to skip some bytes.  */
443
462
      if (pt->is_partial)
444
181
        {
445
351
          while (iobuf_read( pt->buf, NULL, 1<<30 ) != -1)
446
170
            ;
447
181
        }
448
281
      else
449
281
        {
450
463
          while( pt->len )
451
182
            { /* Skip the packet.  */
452
182
              int n = iobuf_read( pt->buf, NULL, pt->len );
453
182
              if (n == -1)
454
100
                pt->len = 0;
455
82
              else
456
82
                pt->len -= n;
457
182
            }
458
281
  }
459
462
    }
460
462
  xfree (pt);
461
462
}
462
463
464
/****************
465
 * Free the packet in PKT.
466
 */
467
void
468
free_packet (PACKET *pkt, parse_packet_ctx_t parsectx)
469
32.9M
{
470
32.9M
  if (!pkt || !pkt->pkt.generic)
471
21.7M
    {
472
21.7M
      if (parsectx && parsectx->last_pkt.pkt.generic)
473
10.6M
        {
474
10.6M
          if (parsectx->free_last_pkt)
475
10.1k
            {
476
10.1k
              free_packet (&parsectx->last_pkt, NULL);
477
10.1k
              parsectx->free_last_pkt = 0;
478
10.1k
            }
479
10.6M
          parsectx->last_pkt.pkttype = 0;
480
10.6M
          parsectx->last_pkt.pkt.generic = NULL;
481
10.6M
        }
482
21.7M
      return;
483
21.7M
    }
484
485
11.1M
  if (DBG_MEMORY)
486
11.1M
    log_debug ("free_packet() type=%d\n", pkt->pkttype);
487
488
  /* If we have a parser context holding PKT then do not free the
489
   * packet but set a flag that the packet in the parser context is
490
   * now a deep copy.  */
491
11.1M
  if (parsectx && !parsectx->free_last_pkt
492
27.6k
      && parsectx->last_pkt.pkttype == pkt->pkttype
493
10.1k
      && parsectx->last_pkt.pkt.generic == pkt->pkt.generic)
494
10.1k
    {
495
10.1k
      parsectx->last_pkt = *pkt;
496
10.1k
      parsectx->free_last_pkt = 1;
497
10.1k
      pkt->pkt.generic = NULL;
498
10.1k
      return;
499
10.1k
    }
500
501
11.1M
  switch (pkt->pkttype)
502
11.1M
    {
503
10.5M
    case PKT_SIGNATURE:
504
10.5M
      free_seckey_enc (pkt->pkt.signature);
505
10.5M
      break;
506
957
    case PKT_PUBKEY_ENC:
507
957
      free_pubkey_enc (pkt->pkt.pubkey_enc);
508
957
      break;
509
1.80k
    case PKT_SYMKEY_ENC:
510
1.80k
      free_symkey_enc (pkt->pkt.symkey_enc);
511
1.80k
      break;
512
20.1k
    case PKT_PUBLIC_KEY:
513
525k
    case PKT_PUBLIC_SUBKEY:
514
530k
    case PKT_SECRET_KEY:
515
532k
    case PKT_SECRET_SUBKEY:
516
532k
      free_public_key (pkt->pkt.public_key);
517
532k
      break;
518
876
    case PKT_COMMENT:
519
876
      free_comment (pkt->pkt.comment);
520
876
      break;
521
44.1k
    case PKT_USER_ID:
522
44.1k
      free_user_id (pkt->pkt.user_id);
523
44.1k
      break;
524
364
    case PKT_COMPRESSED:
525
364
      free_compressed (pkt->pkt.compressed);
526
364
      break;
527
492
    case PKT_ENCRYPTED:
528
2.50k
    case PKT_ENCRYPTED_MDC:
529
5.61k
    case PKT_ENCRYPTED_AEAD:
530
5.61k
      free_encrypted (pkt->pkt.encrypted);
531
5.61k
      break;
532
462
    case PKT_PLAINTEXT:
533
462
      free_plaintext (pkt->pkt.plaintext);
534
462
      break;
535
4.64k
    default:
536
4.64k
      xfree (pkt->pkt.generic);
537
4.64k
      break;
538
11.1M
    }
539
540
11.1M
  pkt->pkt.generic = NULL;
541
11.1M
}
542
543
544
/* Free an entire list of public or symmetric key encrypted data.  */
545
void
546
free_seskey_enc_list (struct seskey_enc_list *sesenc_list)
547
0
{
548
0
  while (sesenc_list)
549
0
    {
550
0
      struct seskey_enc_list *tmp = sesenc_list->next;
551
552
0
      if (!sesenc_list->u_sym)
553
0
        release_pubkey_enc_parts (&sesenc_list->u.pub);
554
0
      xfree (sesenc_list);
555
0
      sesenc_list = tmp;
556
0
    }
557
0
}
558
559
560
/****************
561
 * returns 0 if they match.
562
 */
563
int
564
cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
565
39.1k
{
566
39.1k
    int n, i;
567
568
39.1k
    if( a->timestamp != b->timestamp )
569
42
  return -1;
570
39.1k
    if( a->version < 4 && a->expiredate != b->expiredate )
571
0
  return -1;
572
39.1k
    if( a->pubkey_algo != b->pubkey_algo )
573
0
  return -1;
574
575
39.1k
    n = pubkey_get_npkey( b->pubkey_algo );
576
39.1k
    if( !n ) { /* unknown algorithm, rest is in opaque MPI */
577
0
  if( mpi_cmp( a->pkey[0], b->pkey[0] ) )
578
0
      return -1; /* can't compare due to unknown algorithm */
579
39.1k
    } else {
580
100k
  for(i=0; i < n; i++ ) {
581
88.2k
      if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
582
26.7k
    return -1;
583
88.2k
  }
584
39.1k
    }
585
586
12.3k
    return 0;
587
39.1k
}
588
589
590
591
int
592
cmp_signatures( PKT_signature *a, PKT_signature *b )
593
1.76M
{
594
1.76M
    int n, i;
595
596
1.76M
    if( a->keyid[0] != b->keyid[0] )
597
40.0k
  return -1;
598
1.72M
    if( a->keyid[1] != b->keyid[1] )
599
21.5k
  return -1;
600
1.69M
    if( a->pubkey_algo != b->pubkey_algo )
601
17.0k
  return -1;
602
603
1.68M
    n = pubkey_get_nsig( a->pubkey_algo );
604
1.68M
    if( !n )
605
127
  return -1; /* can't compare due to unknown algorithm */
606
3.06M
    for(i=0; i < n; i++ ) {
607
3.06M
  if( mpi_cmp( a->data[i] , b->data[i] ) )
608
1.68M
      return -1;
609
3.06M
    }
610
572
    return 0;
611
1.68M
}
612
613
614
/****************
615
 * Returns: true if the user ids do not match
616
 */
617
int
618
cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
619
6.73k
{
620
6.73k
    int res=1;
621
622
6.73k
    if( a == b )
623
0
        return 0;
624
625
6.73k
    if( a->attrib_data && b->attrib_data )
626
0
      {
627
0
  res = a->attrib_len - b->attrib_len;
628
0
  if( !res )
629
0
    res = memcmp( a->attrib_data, b->attrib_data, a->attrib_len );
630
0
      }
631
6.73k
    else if( !a->attrib_data && !b->attrib_data )
632
6.73k
      {
633
6.73k
  res = a->len - b->len;
634
6.73k
  if( !res )
635
4.76k
    res = memcmp( a->name, b->name, a->len );
636
6.73k
      }
637
638
6.73k
    return res;
639
6.73k
}