removed unused variables.
[gnutls.git] / lib / opencdk / new-packet.c
blob7a7179aff1b185a04d1264f8a326998074bd1f34
1 /* new-packet.c - packet handling (freeing, copying, ...)
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz
6 * This file is part of OpenCDK.
8 * The OpenCDK 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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <string.h>
27 #include <stdio.h>
29 #include "opencdk.h"
30 #include "main.h"
31 #include "packet.h"
34 /* Release an array of MPI values. */
35 void
36 _cdk_free_mpibuf (size_t n, bigint_t * array)
38 while (n--)
40 _gnutls_mpi_release (&array[n]);
45 /**
46 * cdk_pkt_new:
47 * @r_pkt: the new packet
49 * Allocate a new packet.
50 **/
51 cdk_error_t
52 cdk_pkt_new (cdk_packet_t * r_pkt)
54 cdk_packet_t pkt;
56 if (!r_pkt)
57 return CDK_Inv_Value;
58 pkt = cdk_calloc (1, sizeof *pkt);
59 if (!pkt)
60 return CDK_Out_Of_Core;
61 *r_pkt = pkt;
62 return 0;
66 static void
67 free_pubkey_enc (cdk_pkt_pubkey_enc_t enc)
69 size_t nenc;
71 if (!enc)
72 return;
74 nenc = cdk_pk_get_nenc (enc->pubkey_algo);
75 _cdk_free_mpibuf (nenc, enc->mpi);
76 cdk_free (enc);
80 static void
81 free_literal (cdk_pkt_literal_t pt)
83 if (!pt)
84 return;
85 /* The buffer which is referenced in this packet is closed
86 elsewhere. To close it here would cause a double close. */
87 cdk_free (pt);
91 void
92 _cdk_free_userid (cdk_pkt_userid_t uid)
94 if (!uid)
95 return;
97 cdk_free (uid->prefs);
98 uid->prefs = NULL;
99 cdk_free (uid->attrib_img);
100 uid->attrib_img = NULL;
101 cdk_free (uid);
105 void
106 _cdk_free_signature (cdk_pkt_signature_t sig)
108 cdk_desig_revoker_t r;
109 size_t nsig;
111 if (!sig)
112 return;
114 nsig = cdk_pk_get_nsig (sig->pubkey_algo);
115 _cdk_free_mpibuf (nsig, sig->mpi);
117 cdk_subpkt_free (sig->hashed);
118 sig->hashed = NULL;
119 cdk_subpkt_free (sig->unhashed);
120 sig->unhashed = NULL;
121 while (sig->revkeys)
123 r = sig->revkeys->next;
124 cdk_free (sig->revkeys);
125 sig->revkeys = r;
127 cdk_free (sig);
131 void
132 cdk_pk_release (cdk_pubkey_t pk)
134 size_t npkey;
136 if (!pk)
137 return;
139 npkey = cdk_pk_get_npkey (pk->pubkey_algo);
140 _cdk_free_userid (pk->uid);
141 pk->uid = NULL;
142 cdk_free (pk->prefs);
143 pk->prefs = NULL;
144 _cdk_free_mpibuf (npkey, pk->mpi);
145 cdk_free (pk);
149 void
150 cdk_sk_release (cdk_seckey_t sk)
152 size_t nskey;
154 if (!sk)
155 return;
157 nskey = cdk_pk_get_nskey (sk->pubkey_algo);
158 _cdk_free_mpibuf (nskey, sk->mpi);
159 cdk_free (sk->encdata);
160 sk->encdata = NULL;
161 cdk_pk_release (sk->pk);
162 sk->pk = NULL;
163 cdk_s2k_free (sk->protect.s2k);
164 sk->protect.s2k = NULL;
165 cdk_free (sk);
169 /* Detach the openpgp packet from the packet structure
170 and release the packet structure itself. */
171 void
172 _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx)
174 /* For now we just allow this for keys. */
175 switch (pkt->pkttype)
177 case CDK_PKT_PUBLIC_KEY:
178 case CDK_PKT_PUBLIC_SUBKEY:
179 *ctx = pkt->pkt.public_key;
180 break;
182 case CDK_PKT_SECRET_KEY:
183 case CDK_PKT_SECRET_SUBKEY:
184 *ctx = pkt->pkt.secret_key;
185 break;
187 default:
188 *r_pkttype = 0;
189 return;
192 /* The caller might expect a specific packet type and
193 is not interested to store it for later use. */
194 if (r_pkttype)
195 *r_pkttype = pkt->pkttype;
197 cdk_free (pkt);
201 void
202 cdk_pkt_free (cdk_packet_t pkt)
204 if (!pkt)
205 return;
207 switch (pkt->pkttype)
209 case CDK_PKT_ATTRIBUTE:
210 case CDK_PKT_USER_ID:
211 _cdk_free_userid (pkt->pkt.user_id);
212 break;
213 case CDK_PKT_PUBLIC_KEY:
214 case CDK_PKT_PUBLIC_SUBKEY:
215 cdk_pk_release (pkt->pkt.public_key);
216 break;
217 case CDK_PKT_SECRET_KEY:
218 case CDK_PKT_SECRET_SUBKEY:
219 cdk_sk_release (pkt->pkt.secret_key);
220 break;
221 case CDK_PKT_SIGNATURE:
222 _cdk_free_signature (pkt->pkt.signature);
223 break;
224 case CDK_PKT_PUBKEY_ENC:
225 free_pubkey_enc (pkt->pkt.pubkey_enc);
226 break;
227 case CDK_PKT_MDC:
228 cdk_free (pkt->pkt.mdc);
229 break;
230 case CDK_PKT_ONEPASS_SIG:
231 cdk_free (pkt->pkt.onepass_sig);
232 break;
233 case CDK_PKT_LITERAL:
234 free_literal (pkt->pkt.literal);
235 break;
236 case CDK_PKT_COMPRESSED:
237 cdk_free (pkt->pkt.compressed);
238 break;
239 default:
240 break;
243 /* Reset the packet type to avoid, when cdk_pkt_release() will be
244 used, that the second cdk_pkt_free() call will double free the data. */
245 pkt->pkttype = 0;
250 * cdk_pkt_release:
251 * @pkt: the packet
253 * Free the contents of the given package and
254 * release the memory of the structure.
256 void
257 cdk_pkt_release (cdk_packet_t pkt)
259 if (!pkt)
260 return;
261 cdk_pkt_free (pkt);
262 cdk_free (pkt);
267 * cdk_pkt_alloc:
268 * @r_pkt: output is the new packet
269 * @pkttype: the requested packet type
271 * Allocate a new packet structure with the given packet type.
273 cdk_error_t
274 cdk_pkt_alloc (cdk_packet_t * r_pkt, cdk_packet_type_t pkttype)
276 cdk_packet_t pkt;
277 int rc;
279 if (!r_pkt)
280 return CDK_Inv_Value;
282 rc = cdk_pkt_new (&pkt);
283 if (rc)
284 return rc;
286 switch (pkttype)
288 case CDK_PKT_USER_ID:
289 pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id);
290 if (!pkt->pkt.user_id)
291 return CDK_Out_Of_Core;
292 pkt->pkt.user_id->name = NULL;
293 break;
295 case CDK_PKT_PUBLIC_KEY:
296 case CDK_PKT_PUBLIC_SUBKEY:
297 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
298 if (!pkt->pkt.public_key)
299 return CDK_Out_Of_Core;
300 break;
302 case CDK_PKT_SECRET_KEY:
303 case CDK_PKT_SECRET_SUBKEY:
304 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
305 pkt->pkt.secret_key->pk =
306 cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
307 if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk)
308 return CDK_Out_Of_Core;
309 break;
311 case CDK_PKT_SIGNATURE:
312 pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
313 if (!pkt->pkt.signature)
314 return CDK_Out_Of_Core;
315 break;
317 case CDK_PKT_PUBKEY_ENC:
318 pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
319 if (!pkt->pkt.pubkey_enc)
320 return CDK_Out_Of_Core;
321 break;
323 case CDK_PKT_MDC:
324 pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
325 if (!pkt->pkt.mdc)
326 return CDK_Out_Of_Core;
327 break;
329 case CDK_PKT_ONEPASS_SIG:
330 pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
331 if (!pkt->pkt.onepass_sig)
332 return CDK_Out_Of_Core;
333 break;
335 case CDK_PKT_LITERAL:
336 /* FIXME: We would need the size of the file name to allocate extra
337 bytes, otherwise the result would be useless. */
338 pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
339 if (!pkt->pkt.literal)
340 return CDK_Out_Of_Core;
341 pkt->pkt.literal->name = NULL;
342 break;
344 default:
345 return CDK_Not_Implemented;
347 pkt->pkttype = pkttype;
348 *r_pkt = pkt;
349 return 0;
353 cdk_prefitem_t
354 _cdk_copy_prefs (const cdk_prefitem_t prefs)
356 size_t n = 0;
357 struct cdk_prefitem_s *new_prefs;
359 if (!prefs)
360 return NULL;
362 for (n = 0; prefs[n].type; n++)
364 new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1));
365 if (!new_prefs)
366 return NULL;
367 for (n = 0; prefs[n].type; n++)
369 new_prefs[n].type = prefs[n].type;
370 new_prefs[n].value = prefs[n].value;
372 new_prefs[n].type = CDK_PREFTYPE_NONE;
373 new_prefs[n].value = 0;
374 return new_prefs;
378 cdk_error_t
379 _cdk_copy_userid (cdk_pkt_userid_t * dst, cdk_pkt_userid_t src)
381 cdk_pkt_userid_t u;
383 if (!dst || !src)
384 return CDK_Inv_Value;
386 *dst = NULL;
387 u = cdk_calloc (1, sizeof *u + strlen (src->name) + 2);
388 if (!u)
389 return CDK_Out_Of_Core;
390 u->name = (char *) u + sizeof (*u);
392 memcpy (u, src, sizeof *u);
393 memcpy (u->name, src->name, strlen (src->name));
394 u->prefs = _cdk_copy_prefs (src->prefs);
395 if (src->selfsig)
396 _cdk_copy_signature (&u->selfsig, src->selfsig);
397 *dst = u;
399 return 0;
403 cdk_error_t
404 _cdk_copy_pubkey (cdk_pkt_pubkey_t * dst, cdk_pkt_pubkey_t src)
406 cdk_pkt_pubkey_t k;
407 int i;
409 if (!dst || !src)
410 return CDK_Inv_Value;
412 *dst = NULL;
413 k = cdk_calloc (1, sizeof *k);
414 if (!k)
415 return CDK_Out_Of_Core;
416 memcpy (k, src, sizeof *k);
417 if (src->uid)
418 _cdk_copy_userid (&k->uid, src->uid);
419 if (src->prefs)
420 k->prefs = _cdk_copy_prefs (src->prefs);
421 for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++)
422 k->mpi[i] = _gnutls_mpi_copy (src->mpi[i]);
423 *dst = k;
425 return 0;
429 cdk_error_t
430 _cdk_copy_seckey (cdk_pkt_seckey_t * dst, cdk_pkt_seckey_t src)
432 cdk_pkt_seckey_t k;
433 int i;
435 if (!dst || !src)
436 return CDK_Inv_Value;
438 *dst = NULL;
439 k = cdk_calloc (1, sizeof *k);
440 if (!k)
441 return CDK_Out_Of_Core;
442 memcpy (k, src, sizeof *k);
443 _cdk_copy_pubkey (&k->pk, src->pk);
445 if (src->encdata)
447 k->encdata = cdk_calloc (1, src->enclen + 1);
448 if (!k->encdata)
449 return CDK_Out_Of_Core;
450 memcpy (k->encdata, src->encdata, src->enclen);
453 _cdk_s2k_copy (&k->protect.s2k, src->protect.s2k);
454 for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++)
456 k->mpi[i] = _gnutls_mpi_copy (src->mpi[i]);
459 *dst = k;
460 return 0;
464 cdk_error_t
465 _cdk_copy_pk_to_sk (cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk)
467 if (!pk || !sk)
468 return CDK_Inv_Value;
470 sk->version = pk->version;
471 sk->expiredate = pk->expiredate;
472 sk->pubkey_algo = _pgp_pub_algo_to_cdk (pk->pubkey_algo);
473 sk->has_expired = pk->has_expired;
474 sk->is_revoked = pk->is_revoked;
475 sk->main_keyid[0] = pk->main_keyid[0];
476 sk->main_keyid[1] = pk->main_keyid[1];
477 sk->keyid[0] = pk->keyid[0];
478 sk->keyid[1] = pk->keyid[1];
480 return 0;
484 cdk_error_t
485 _cdk_copy_signature (cdk_pkt_signature_t * dst, cdk_pkt_signature_t src)
487 cdk_pkt_signature_t s;
489 if (!dst || !src)
490 return CDK_Inv_Value;
492 *dst = NULL;
493 s = cdk_calloc (1, sizeof *s);
494 if (!s)
495 return CDK_Out_Of_Core;
496 memcpy (s, src, sizeof *src);
497 _cdk_subpkt_copy (&s->hashed, src->hashed);
498 _cdk_subpkt_copy (&s->unhashed, src->unhashed);
499 /* FIXME: Copy MPI parts */
500 *dst = s;
502 return 0;
506 cdk_error_t
507 _cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
509 int na, nb, i;
511 if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo)
512 return -1;
513 if (a->version < 4 && a->expiredate != b->expiredate)
514 return -1;
515 na = cdk_pk_get_npkey (a->pubkey_algo);
516 nb = cdk_pk_get_npkey (b->pubkey_algo);
517 if (na != nb)
518 return -1;
520 for (i = 0; i < na; i++)
522 if (_gnutls_mpi_cmp (a->mpi[i], b->mpi[i]))
523 return -1;
526 return 0;
531 * cdk_subpkt_free:
532 * @ctx: the sub packet node to free
534 * Release the context.
536 void
537 cdk_subpkt_free (cdk_subpkt_t ctx)
539 cdk_subpkt_t s;
541 while (ctx)
543 s = ctx->next;
544 cdk_free (ctx);
545 ctx = s;
551 * cdk_subpkt_find:
552 * @ctx: the sub packet node
553 * @type: the packet type to find
555 * Find the given packet type in the node. If no packet with this
556 * type was found, return null otherwise pointer to the node.
558 cdk_subpkt_t
559 cdk_subpkt_find (cdk_subpkt_t ctx, size_t type)
561 return cdk_subpkt_find_nth (ctx, type, 0);
565 * cdk_subpkt_type_count:
566 * @ctx: The sub packet context
567 * @type: The sub packet type.
569 * Return the amount of sub packets with this type.
571 size_t
572 cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type)
574 cdk_subpkt_t s;
575 size_t count;
577 count = 0;
578 for (s = ctx; s; s = s->next)
580 if (s->type == type)
581 count++;
584 return count;
589 * cdk_subpkt_find_nth:
590 * @ctx: The sub packet context
591 * @type: The sub packet type
592 * @index: The nth packet to retrieve, 0 means the first
594 * Return the nth sub packet of the given type.
596 cdk_subpkt_t
597 cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t idx)
599 cdk_subpkt_t s;
600 size_t pos;
602 pos = 0;
603 for (s = ctx; s; s = s->next)
605 if (s->type == type && pos++ == idx)
606 return s;
609 return NULL;
614 * cdk_subpkt_new:
615 * @size: the size of the new context
617 * Create a new sub packet node with the size of @size.
619 cdk_subpkt_t
620 cdk_subpkt_new (size_t size)
622 cdk_subpkt_t s;
624 if (!size)
625 return NULL;
626 s = cdk_calloc (1, sizeof *s + size + 2);
627 if (!s)
628 return NULL;
629 s->d = (byte*)s + sizeof (*s);
631 return s;
636 * cdk_subpkt_get_data:
637 * @ctx: the sub packet node
638 * @r_type: pointer store the packet type
639 * @r_nbytes: pointer to store the packet size
641 * Extract the data from the given sub packet. The type is returned
642 * in @r_type and the size in @r_nbytes.
644 const byte *
645 cdk_subpkt_get_data (cdk_subpkt_t ctx, size_t * r_type, size_t * r_nbytes)
647 if (!ctx || !r_nbytes)
648 return NULL;
649 if (r_type)
650 *r_type = ctx->type;
651 *r_nbytes = ctx->size;
652 return ctx->d;
657 * cdk_subpkt_add:
658 * @root: the root node
659 * @node: the node to add
661 * Add the node in @node to the root node @root.
663 cdk_error_t
664 cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node)
666 cdk_subpkt_t n1;
668 if (!root)
669 return CDK_Inv_Value;
670 for (n1 = root; n1->next; n1 = n1->next)
672 n1->next = node;
673 return 0;
677 byte *
678 _cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes)
680 cdk_subpkt_t list;
681 byte *buf;
682 size_t n, nbytes;
684 if (!s)
686 if (r_nbytes)
687 *r_nbytes = 0;
688 return NULL;
691 for (n = 0, list = s; list; list = list->next)
693 n++; /* type */
694 n += list->size;
695 if (list->size < 192)
696 n++;
697 else if (list->size < 8384)
698 n += 2;
699 else
700 n += 5;
702 buf = cdk_calloc (1, n + 1);
703 if (!buf)
704 return NULL;
706 n = 0;
707 for (list = s; list; list = list->next)
709 nbytes = 1 + list->size; /* type */
710 if (nbytes < 192)
711 buf[n++] = nbytes;
712 else if (nbytes < 8384)
714 nbytes -= 192;
715 buf[n++] = nbytes / 256 + 192;
716 buf[n++] = nbytes & 0xff;
718 else
720 buf[n++] = 0xFF;
721 buf[n++] = nbytes >> 24;
722 buf[n++] = nbytes >> 16;
723 buf[n++] = nbytes >> 8;
724 buf[n++] = nbytes;
727 buf[n++] = list->type;
728 memcpy (buf + n, list->d, list->size);
729 n += list->size;
732 if (count)
734 cdk_free (buf);
735 buf = NULL;
737 if (r_nbytes)
738 *r_nbytes = n;
739 return buf;
743 cdk_error_t
744 _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src)
746 cdk_subpkt_t root, p, node;
748 if (!src || !r_dst)
749 return CDK_Inv_Value;
751 root = NULL;
752 for (p = src; p; p = p->next)
754 node = cdk_subpkt_new (p->size);
755 if (node)
757 memcpy (node->d, p->d, p->size);
758 node->type = p->type;
759 node->size = p->size;
761 if (!root)
762 root = node;
763 else
764 cdk_subpkt_add (root, node);
766 *r_dst = root;
767 return 0;
772 * cdk_subpkt_init:
773 * @node: the sub packet node
774 * @type: type of the packet which data should be initialized
775 * @buf: the buffer with the actual data
776 * @buflen: the size of the data
778 * Set the packet data of the given root and set the type of it.
780 void
781 cdk_subpkt_init (cdk_subpkt_t node, size_t type,
782 const void *buf, size_t buflen)
784 if (!node)
785 return;
786 node->type = type;
787 node->size = buflen;
788 memcpy (node->d, buf, buflen);
792 /* FIXME: We need to think of a public interface for it. */
793 const byte *
794 cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
795 cdk_desig_revoker_t * ctx,
796 int *r_class, int *r_algid)
798 cdk_desig_revoker_t n;
800 if (!*ctx)
802 *ctx = root;
803 n = root;
805 else
807 n = (*ctx)->next;
808 *ctx = n;
811 if (n && r_class && r_algid)
813 *r_class = n->r_class;
814 *r_algid = n->algid;
817 return n ? n->fpr : NULL;
822 * cdk_subpkt_find_next:
823 * @root: the base where to begin the iteration
824 * @type: the type to find or 0 for the next node.
826 * Try to find the next node after @root with type.
827 * If type is 0, the next node will be returned.
829 cdk_subpkt_t
830 cdk_subpkt_find_next (cdk_subpkt_t root, size_t type)
832 cdk_subpkt_t node;
834 for (node = root->next; node; node = node->next)
836 if (!type)
837 return node;
838 else if (node->type == type)
839 return node;
842 return NULL;