1 /* new-packet.c - packet handling (freeing, copying, ...)
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
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/>
34 /* Release an array of MPI values. */
36 _cdk_free_mpibuf (size_t n
, bigint_t
* array
)
40 _gnutls_mpi_release (&array
[n
]);
47 * @r_pkt: the new packet
49 * Allocate a new packet.
52 cdk_pkt_new (cdk_packet_t
* r_pkt
)
58 pkt
= cdk_calloc (1, sizeof *pkt
);
60 return CDK_Out_Of_Core
;
67 free_pubkey_enc (cdk_pkt_pubkey_enc_t enc
)
74 nenc
= cdk_pk_get_nenc (enc
->pubkey_algo
);
75 _cdk_free_mpibuf (nenc
, enc
->mpi
);
81 free_literal (cdk_pkt_literal_t pt
)
85 /* The buffer which is referenced in this packet is closed
86 elsewhere. To close it here would cause a double close. */
92 _cdk_free_userid (cdk_pkt_userid_t uid
)
97 cdk_free (uid
->prefs
);
99 cdk_free (uid
->attrib_img
);
100 uid
->attrib_img
= NULL
;
106 _cdk_free_signature (cdk_pkt_signature_t sig
)
108 cdk_desig_revoker_t r
;
114 nsig
= cdk_pk_get_nsig (sig
->pubkey_algo
);
115 _cdk_free_mpibuf (nsig
, sig
->mpi
);
117 cdk_subpkt_free (sig
->hashed
);
119 cdk_subpkt_free (sig
->unhashed
);
120 sig
->unhashed
= NULL
;
123 r
= sig
->revkeys
->next
;
124 cdk_free (sig
->revkeys
);
132 cdk_pk_release (cdk_pubkey_t pk
)
139 npkey
= cdk_pk_get_npkey (pk
->pubkey_algo
);
140 _cdk_free_userid (pk
->uid
);
142 cdk_free (pk
->prefs
);
144 _cdk_free_mpibuf (npkey
, pk
->mpi
);
150 cdk_sk_release (cdk_seckey_t sk
)
157 nskey
= cdk_pk_get_nskey (sk
->pubkey_algo
);
158 _cdk_free_mpibuf (nskey
, sk
->mpi
);
159 cdk_free (sk
->encdata
);
161 cdk_pk_release (sk
->pk
);
163 cdk_s2k_free (sk
->protect
.s2k
);
164 sk
->protect
.s2k
= NULL
;
169 /* Detach the openpgp packet from the packet structure
170 and release the packet structure itself. */
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
;
182 case CDK_PKT_SECRET_KEY
:
183 case CDK_PKT_SECRET_SUBKEY
:
184 *ctx
= pkt
->pkt
.secret_key
;
192 /* The caller might expect a specific packet type and
193 is not interested to store it for later use. */
195 *r_pkttype
= pkt
->pkttype
;
202 cdk_pkt_free (cdk_packet_t pkt
)
207 switch (pkt
->pkttype
)
209 case CDK_PKT_ATTRIBUTE
:
210 case CDK_PKT_USER_ID
:
211 _cdk_free_userid (pkt
->pkt
.user_id
);
213 case CDK_PKT_PUBLIC_KEY
:
214 case CDK_PKT_PUBLIC_SUBKEY
:
215 cdk_pk_release (pkt
->pkt
.public_key
);
217 case CDK_PKT_SECRET_KEY
:
218 case CDK_PKT_SECRET_SUBKEY
:
219 cdk_sk_release (pkt
->pkt
.secret_key
);
221 case CDK_PKT_SIGNATURE
:
222 _cdk_free_signature (pkt
->pkt
.signature
);
224 case CDK_PKT_PUBKEY_ENC
:
225 free_pubkey_enc (pkt
->pkt
.pubkey_enc
);
228 cdk_free (pkt
->pkt
.mdc
);
230 case CDK_PKT_ONEPASS_SIG
:
231 cdk_free (pkt
->pkt
.onepass_sig
);
233 case CDK_PKT_LITERAL
:
234 free_literal (pkt
->pkt
.literal
);
236 case CDK_PKT_COMPRESSED
:
237 cdk_free (pkt
->pkt
.compressed
);
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. */
253 * Free the contents of the given package and
254 * release the memory of the structure.
257 cdk_pkt_release (cdk_packet_t pkt
)
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.
274 cdk_pkt_alloc (cdk_packet_t
* r_pkt
, cdk_packet_type_t pkttype
)
280 return CDK_Inv_Value
;
282 rc
= cdk_pkt_new (&pkt
);
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
;
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
;
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
;
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
;
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
;
324 pkt
->pkt
.mdc
= cdk_calloc (1, sizeof *pkt
->pkt
.mdc
);
326 return CDK_Out_Of_Core
;
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
;
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
;
345 return CDK_Not_Implemented
;
347 pkt
->pkttype
= pkttype
;
354 _cdk_copy_prefs (const cdk_prefitem_t prefs
)
357 struct cdk_prefitem_s
*new_prefs
;
362 for (n
= 0; prefs
[n
].type
; n
++)
364 new_prefs
= cdk_calloc (1, sizeof *new_prefs
* (n
+ 1));
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;
379 _cdk_copy_userid (cdk_pkt_userid_t
* dst
, cdk_pkt_userid_t src
)
384 return CDK_Inv_Value
;
387 u
= cdk_calloc (1, sizeof *u
+ strlen (src
->name
) + 2);
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
);
396 _cdk_copy_signature (&u
->selfsig
, src
->selfsig
);
404 _cdk_copy_pubkey (cdk_pkt_pubkey_t
* dst
, cdk_pkt_pubkey_t src
)
410 return CDK_Inv_Value
;
413 k
= cdk_calloc (1, sizeof *k
);
415 return CDK_Out_Of_Core
;
416 memcpy (k
, src
, sizeof *k
);
418 _cdk_copy_userid (&k
->uid
, src
->uid
);
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
]);
430 _cdk_copy_seckey (cdk_pkt_seckey_t
* dst
, cdk_pkt_seckey_t src
)
436 return CDK_Inv_Value
;
439 k
= cdk_calloc (1, sizeof *k
);
441 return CDK_Out_Of_Core
;
442 memcpy (k
, src
, sizeof *k
);
443 _cdk_copy_pubkey (&k
->pk
, src
->pk
);
447 k
->encdata
= cdk_calloc (1, src
->enclen
+ 1);
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
]);
465 _cdk_copy_pk_to_sk (cdk_pkt_pubkey_t pk
, cdk_pkt_seckey_t 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];
485 _cdk_copy_signature (cdk_pkt_signature_t
* dst
, cdk_pkt_signature_t src
)
487 cdk_pkt_signature_t s
;
490 return CDK_Inv_Value
;
493 s
= cdk_calloc (1, sizeof *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 */
507 _cdk_pubkey_compare (cdk_pkt_pubkey_t a
, cdk_pkt_pubkey_t b
)
511 if (a
->timestamp
!= b
->timestamp
|| a
->pubkey_algo
!= b
->pubkey_algo
)
513 if (a
->version
< 4 && a
->expiredate
!= b
->expiredate
)
515 na
= cdk_pk_get_npkey (a
->pubkey_algo
);
516 nb
= cdk_pk_get_npkey (b
->pubkey_algo
);
520 for (i
= 0; i
< na
; i
++)
522 if (_gnutls_mpi_cmp (a
->mpi
[i
], b
->mpi
[i
]))
532 * @ctx: the sub packet node to free
534 * Release the context.
537 cdk_subpkt_free (cdk_subpkt_t ctx
)
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.
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.
572 cdk_subpkt_type_count (cdk_subpkt_t ctx
, size_t type
)
578 for (s
= ctx
; s
; s
= s
->next
)
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.
597 cdk_subpkt_find_nth (cdk_subpkt_t ctx
, size_t type
, size_t idx
)
603 for (s
= ctx
; s
; s
= s
->next
)
605 if (s
->type
== type
&& pos
++ == idx
)
615 * @size: the size of the new context
617 * Create a new sub packet node with the size of @size.
620 cdk_subpkt_new (size_t size
)
626 s
= cdk_calloc (1, sizeof *s
+ size
+ 2);
629 s
->d
= (byte
*)s
+ sizeof (*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.
645 cdk_subpkt_get_data (cdk_subpkt_t ctx
, size_t * r_type
, size_t * r_nbytes
)
647 if (!ctx
|| !r_nbytes
)
651 *r_nbytes
= ctx
->size
;
658 * @root: the root node
659 * @node: the node to add
661 * Add the node in @node to the root node @root.
664 cdk_subpkt_add (cdk_subpkt_t root
, cdk_subpkt_t node
)
669 return CDK_Inv_Value
;
670 for (n1
= root
; n1
->next
; n1
= n1
->next
)
678 _cdk_subpkt_get_array (cdk_subpkt_t s
, int count
, size_t * r_nbytes
)
691 for (n
= 0, list
= s
; list
; list
= list
->next
)
695 if (list
->size
< 192)
697 else if (list
->size
< 8384)
702 buf
= cdk_calloc (1, n
+ 1);
707 for (list
= s
; list
; list
= list
->next
)
709 nbytes
= 1 + list
->size
; /* type */
712 else if (nbytes
< 8384)
715 buf
[n
++] = nbytes
/ 256 + 192;
716 buf
[n
++] = nbytes
& 0xff;
721 buf
[n
++] = nbytes
>> 24;
722 buf
[n
++] = nbytes
>> 16;
723 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
)