1 /* new-packet.c - packet handling (freeing, copying, ...)
2 * Copyright (C) 2001, 2002, 2003, 2007, 2008, 2010 Free Software
7 * This file is part of OpenCDK.
9 * The OpenCDK library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
36 /* Release an array of MPI values. */
38 _cdk_free_mpibuf (size_t n, bigint_t * array)
42 _gnutls_mpi_release (&array[n]);
49 * @r_pkt: the new packet
51 * Allocate a new packet.
54 cdk_pkt_new (cdk_packet_t * r_pkt)
60 pkt = cdk_calloc (1, sizeof *pkt);
62 return CDK_Out_Of_Core;
69 free_pubkey_enc (cdk_pkt_pubkey_enc_t enc)
76 nenc = cdk_pk_get_nenc (enc->pubkey_algo);
77 _cdk_free_mpibuf (nenc, enc->mpi);
83 free_literal (cdk_pkt_literal_t pt)
87 /* The buffer which is referenced in this packet is closed
88 elsewhere. To close it here would cause a double close. */
94 _cdk_free_userid (cdk_pkt_userid_t uid)
99 cdk_free (uid->prefs);
101 cdk_free (uid->attrib_img);
102 uid->attrib_img = NULL;
108 _cdk_free_signature (cdk_pkt_signature_t sig)
110 cdk_desig_revoker_t r;
116 nsig = cdk_pk_get_nsig (sig->pubkey_algo);
117 _cdk_free_mpibuf (nsig, sig->mpi);
119 cdk_subpkt_free (sig->hashed);
121 cdk_subpkt_free (sig->unhashed);
122 sig->unhashed = NULL;
125 r = sig->revkeys->next;
126 cdk_free (sig->revkeys);
134 cdk_pk_release (cdk_pubkey_t pk)
141 npkey = cdk_pk_get_npkey (pk->pubkey_algo);
142 _cdk_free_userid (pk->uid);
144 cdk_free (pk->prefs);
146 _cdk_free_mpibuf (npkey, pk->mpi);
152 cdk_sk_release (cdk_seckey_t sk)
159 nskey = cdk_pk_get_nskey (sk->pubkey_algo);
160 _cdk_free_mpibuf (nskey, sk->mpi);
161 cdk_free (sk->encdata);
163 cdk_pk_release (sk->pk);
165 cdk_s2k_free (sk->protect.s2k);
166 sk->protect.s2k = NULL;
171 /* Detach the openpgp packet from the packet structure
172 and release the packet structure itself. */
174 _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx)
176 /* For now we just allow this for keys. */
177 switch (pkt->pkttype)
179 case CDK_PKT_PUBLIC_KEY:
180 case CDK_PKT_PUBLIC_SUBKEY:
181 *ctx = pkt->pkt.public_key;
184 case CDK_PKT_SECRET_KEY:
185 case CDK_PKT_SECRET_SUBKEY:
186 *ctx = pkt->pkt.secret_key;
194 /* The caller might expect a specific packet type and
195 is not interested to store it for later use. */
197 *r_pkttype = pkt->pkttype;
204 cdk_pkt_free (cdk_packet_t pkt)
209 switch (pkt->pkttype)
211 case CDK_PKT_ATTRIBUTE:
212 case CDK_PKT_USER_ID:
213 _cdk_free_userid (pkt->pkt.user_id);
215 case CDK_PKT_PUBLIC_KEY:
216 case CDK_PKT_PUBLIC_SUBKEY:
217 cdk_pk_release (pkt->pkt.public_key);
219 case CDK_PKT_SECRET_KEY:
220 case CDK_PKT_SECRET_SUBKEY:
221 cdk_sk_release (pkt->pkt.secret_key);
223 case CDK_PKT_SIGNATURE:
224 _cdk_free_signature (pkt->pkt.signature);
226 case CDK_PKT_PUBKEY_ENC:
227 free_pubkey_enc (pkt->pkt.pubkey_enc);
230 cdk_free (pkt->pkt.mdc);
232 case CDK_PKT_ONEPASS_SIG:
233 cdk_free (pkt->pkt.onepass_sig);
235 case CDK_PKT_LITERAL:
236 free_literal (pkt->pkt.literal);
238 case CDK_PKT_COMPRESSED:
239 cdk_free (pkt->pkt.compressed);
245 /* Reset the packet type to avoid, when cdk_pkt_release() will be
246 used, that the second cdk_pkt_free() call will double free the data. */
255 * Free the contents of the given package and
256 * release the memory of the structure.
259 cdk_pkt_release (cdk_packet_t pkt)
270 * @r_pkt: output is the new packet
271 * @pkttype: the requested packet type
273 * Allocate a new packet structure with the given packet type.
276 cdk_pkt_alloc (cdk_packet_t * r_pkt, cdk_packet_type_t pkttype)
282 return CDK_Inv_Value;
284 rc = cdk_pkt_new (&pkt);
290 case CDK_PKT_USER_ID:
291 pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id);
292 if (!pkt->pkt.user_id)
293 return CDK_Out_Of_Core;
294 pkt->pkt.user_id->name = NULL;
297 case CDK_PKT_PUBLIC_KEY:
298 case CDK_PKT_PUBLIC_SUBKEY:
299 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
300 if (!pkt->pkt.public_key)
301 return CDK_Out_Of_Core;
304 case CDK_PKT_SECRET_KEY:
305 case CDK_PKT_SECRET_SUBKEY:
306 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
307 pkt->pkt.secret_key->pk =
308 cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
309 if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk)
310 return CDK_Out_Of_Core;
313 case CDK_PKT_SIGNATURE:
314 pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
315 if (!pkt->pkt.signature)
316 return CDK_Out_Of_Core;
319 case CDK_PKT_PUBKEY_ENC:
320 pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
321 if (!pkt->pkt.pubkey_enc)
322 return CDK_Out_Of_Core;
326 pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
328 return CDK_Out_Of_Core;
331 case CDK_PKT_ONEPASS_SIG:
332 pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
333 if (!pkt->pkt.onepass_sig)
334 return CDK_Out_Of_Core;
337 case CDK_PKT_LITERAL:
338 /* FIXME: We would need the size of the file name to allocate extra
339 bytes, otherwise the result would be useless. */
340 pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
341 if (!pkt->pkt.literal)
342 return CDK_Out_Of_Core;
343 pkt->pkt.literal->name = NULL;
347 return CDK_Not_Implemented;
349 pkt->pkttype = pkttype;
356 _cdk_copy_prefs (const cdk_prefitem_t prefs)
359 struct cdk_prefitem_s *new_prefs;
364 for (n = 0; prefs[n].type; n++)
366 new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1));
369 for (n = 0; prefs[n].type; n++)
371 new_prefs[n].type = prefs[n].type;
372 new_prefs[n].value = prefs[n].value;
374 new_prefs[n].type = CDK_PREFTYPE_NONE;
375 new_prefs[n].value = 0;
381 _cdk_copy_userid (cdk_pkt_userid_t * dst, cdk_pkt_userid_t src)
386 return CDK_Inv_Value;
389 u = cdk_calloc (1, sizeof *u + strlen (src->name) + 2);
391 return CDK_Out_Of_Core;
392 u->name = (char *) u + sizeof (*u);
394 memcpy (u, src, sizeof *u);
395 memcpy (u->name, src->name, strlen (src->name));
396 u->prefs = _cdk_copy_prefs (src->prefs);
398 _cdk_copy_signature (&u->selfsig, src->selfsig);
406 _cdk_copy_pubkey (cdk_pkt_pubkey_t * dst, cdk_pkt_pubkey_t src)
412 return CDK_Inv_Value;
415 k = cdk_calloc (1, sizeof *k);
417 return CDK_Out_Of_Core;
418 memcpy (k, src, sizeof *k);
420 _cdk_copy_userid (&k->uid, src->uid);
422 k->prefs = _cdk_copy_prefs (src->prefs);
423 for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++)
424 k->mpi[i] = _gnutls_mpi_copy (src->mpi[i]);
432 _cdk_copy_seckey (cdk_pkt_seckey_t * dst, cdk_pkt_seckey_t src)
438 return CDK_Inv_Value;
441 k = cdk_calloc (1, sizeof *k);
443 return CDK_Out_Of_Core;
444 memcpy (k, src, sizeof *k);
445 _cdk_copy_pubkey (&k->pk, src->pk);
449 k->encdata = cdk_calloc (1, src->enclen + 1);
451 return CDK_Out_Of_Core;
452 memcpy (k->encdata, src->encdata, src->enclen);
455 _cdk_s2k_copy (&k->protect.s2k, src->protect.s2k);
456 for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++)
458 k->mpi[i] = _gnutls_mpi_copy (src->mpi[i]);
467 _cdk_copy_pk_to_sk (cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk)
470 return CDK_Inv_Value;
472 sk->version = pk->version;
473 sk->expiredate = pk->expiredate;
474 sk->pubkey_algo = _pgp_pub_algo_to_cdk (pk->pubkey_algo);
475 sk->has_expired = pk->has_expired;
476 sk->is_revoked = pk->is_revoked;
477 sk->main_keyid[0] = pk->main_keyid[0];
478 sk->main_keyid[1] = pk->main_keyid[1];
479 sk->keyid[0] = pk->keyid[0];
480 sk->keyid[1] = pk->keyid[1];
487 _cdk_copy_signature (cdk_pkt_signature_t * dst, cdk_pkt_signature_t src)
489 cdk_pkt_signature_t s;
492 return CDK_Inv_Value;
495 s = cdk_calloc (1, sizeof *s);
497 return CDK_Out_Of_Core;
498 memcpy (s, src, sizeof *src);
499 _cdk_subpkt_copy (&s->hashed, src->hashed);
500 _cdk_subpkt_copy (&s->unhashed, src->unhashed);
501 /* FIXME: Copy MPI parts */
509 _cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b)
513 if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo)
515 if (a->version < 4 && a->expiredate != b->expiredate)
517 na = cdk_pk_get_npkey (a->pubkey_algo);
518 nb = cdk_pk_get_npkey (b->pubkey_algo);
522 for (i = 0; i < na; i++)
524 if (_gnutls_mpi_cmp (a->mpi[i], b->mpi[i]))
534 * @ctx: the sub packet node to free
536 * Release the context.
539 cdk_subpkt_free (cdk_subpkt_t ctx)
554 * @ctx: the sub packet node
555 * @type: the packet type to find
557 * Find the given packet type in the node. If no packet with this
558 * type was found, return null otherwise pointer to the node.
561 cdk_subpkt_find (cdk_subpkt_t ctx, size_t type)
563 return cdk_subpkt_find_nth (ctx, type, 0);
567 * cdk_subpkt_type_count:
568 * @ctx: The sub packet context
569 * @type: The sub packet type.
571 * Return the amount of sub packets with this type.
574 cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type)
580 for (s = ctx; s; s = s->next)
591 * cdk_subpkt_find_nth:
592 * @ctx: The sub packet context
593 * @type: The sub packet type
594 * @index: The nth packet to retrieve, 0 means the first
596 * Return the nth sub packet of the given type.
599 cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t idx)
605 for (s = ctx; s; s = s->next)
607 if (s->type == type && pos++ == idx)
617 * @size: the size of the new context
619 * Create a new sub packet node with the size of @size.
622 cdk_subpkt_new (size_t size)
628 s = cdk_calloc (1, sizeof *s + size + 2);
631 s->d = (char *) s + sizeof (*s);
638 * cdk_subpkt_get_data:
639 * @ctx: the sub packet node
640 * @r_type: pointer store the packet type
641 * @r_nbytes: pointer to store the packet size
643 * Extract the data from the given sub packet. The type is returned
644 * in @r_type and the size in @r_nbytes.
647 cdk_subpkt_get_data (cdk_subpkt_t ctx, size_t * r_type, size_t * r_nbytes)
649 if (!ctx || !r_nbytes)
653 *r_nbytes = ctx->size;
660 * @root: the root node
661 * @node: the node to add
663 * Add the node in @node to the root node @root.
666 cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node)
671 return CDK_Inv_Value;
672 for (n1 = root; n1->next; n1 = n1->next)
680 _cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes)
693 for (n = 0, list = s; list; list = list->next)
697 if (list->size < 192)
699 else if (list->size < 8384)
704 buf = cdk_calloc (1, n + 1);
709 for (list = s; list; list = list->next)
711 nbytes = 1 + list->size; /* type */
714 else if (nbytes < 8384)
716 buf[n++] = nbytes / 256 + 192;
717 buf[n++] = nbytes % 256;
722 buf[n++] = nbytes >> 24;
723 buf[n++] = nbytes >> 16;
724 buf[n++] = nbytes >> 8;
727 buf[n++] = list->type;
728 memcpy (buf + n, list->d, list->size);
744 _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src)
746 cdk_subpkt_t root, p, node;
749 return CDK_Inv_Value;
752 for (p = src; p; p = p->next)
754 node = cdk_subpkt_new (p->size);
757 memcpy (node->d, p->d, p->size);
758 node->type = p->type;
759 node->size = p->size;
764 cdk_subpkt_add (root, node);
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.
781 cdk_subpkt_init (cdk_subpkt_t node, size_t type,
782 const void *buf, size_t buflen)
788 memcpy (node->d, buf, buflen);
792 /* FIXME: We need to think of a public interface for it. */
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;
811 if (n && r_class && r_algid)
813 *r_class = n->r_class;
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.
830 cdk_subpkt_find_next (cdk_subpkt_t root, size_t type)
834 for (node = root->next; node; node = node->next)
838 else if (node->type == type)