1 /* kbnode.c - keyblock node utility functions
2 * Copyright (C) 1998-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/>
37 * @pkt: the packet to add
39 * Allocates a new key node and adds a packet.
42 cdk_kbnode_new (cdk_packet_t pkt
)
46 n
= cdk_calloc (1, sizeof *n
);
55 _cdk_kbnode_clone (cdk_kbnode_t node
)
57 /* Mark the node as clone which means that the packet
58 will not be freed, just the node itself. */
68 * Releases the memory of the node.
71 cdk_kbnode_release (cdk_kbnode_t node
)
79 cdk_pkt_release (node
->pkt
);
90 * Marks the given node as deleted.
93 cdk_kbnode_delete (cdk_kbnode_t node
)
100 /* Append NODE to ROOT. ROOT must exist! */
102 _cdk_kbnode_add (cdk_kbnode_t root
, cdk_kbnode_t node
)
106 for (n1
= root
; n1
->next
; n1
= n1
->next
)
114 * @root: the root key node
115 * @node: the node to add
116 * @pkttype: packet type
118 * Inserts @node into the list after @root but before a packet which is not of
119 * type @pkttype (only if @pkttype != 0).
122 cdk_kbnode_insert (cdk_kbnode_t root
, cdk_kbnode_t node
,
123 cdk_packet_type_t pkttype
)
127 node
->next
= root
->next
;
134 for (n1
= root
; n1
->next
; n1
= n1
->next
)
135 if (pkttype
!= n1
->next
->pkt
->pkttype
)
137 node
->next
= n1
->next
;
141 /* No such packet, append */
149 * cdk_kbnode_find_prev:
150 * @root: the root key node
151 * @node: the key node
152 * @pkttype: packet type
154 * Finds the previous node (if @pkttype = 0) or the previous node
155 * with pkttype @pkttype in the list starting with @root of @node.
158 cdk_kbnode_find_prev (cdk_kbnode_t root
, cdk_kbnode_t node
,
159 cdk_packet_type_t pkttype
)
163 for (n1
= NULL
; root
&& root
!= node
; root
= root
->next
)
165 if (!pkttype
|| root
->pkt
->pkttype
== pkttype
)
173 * cdk_kbnode_find_next:
174 * @node: the key node
175 * @pkttype: packet type
177 * Ditto, but find the next packet. The behaviour is trivial if
178 * @pkttype is 0 but if it is specified, the next node with a packet
179 * of this type is returned. The function has some knowledge about
180 * the valid ordering of packets: e.g. if the next signature packet
181 * is requested, the function will not return one if it encounters
185 cdk_kbnode_find_next (cdk_kbnode_t node
, cdk_packet_type_t pkttype
)
187 for (node
= node
->next
; node
; node
= node
->next
)
191 else if (pkttype
== CDK_PKT_USER_ID
&&
192 (node
->pkt
->pkttype
== CDK_PKT_PUBLIC_KEY
||
193 node
->pkt
->pkttype
== CDK_PKT_SECRET_KEY
))
195 else if (pkttype
== CDK_PKT_SIGNATURE
&&
196 (node
->pkt
->pkttype
== CDK_PKT_USER_ID
||
197 node
->pkt
->pkttype
== CDK_PKT_PUBLIC_KEY
||
198 node
->pkt
->pkttype
== CDK_PKT_SECRET_KEY
))
200 else if (node
->pkt
->pkttype
== pkttype
)
209 * @node: the key node
210 * @pkttype: packet type
212 * Tries to find the next node with the packettype @pkttype.
215 cdk_kbnode_find (cdk_kbnode_t node
, cdk_packet_type_t pkttype
)
217 for (; node
; node
= node
->next
)
219 if (node
->pkt
->pkttype
== pkttype
)
227 * cdk_kbnode_find_packet:
228 * @node: the key node
229 * @pkttype: packet type
231 * Same as cdk_kbnode_find but it returns the packet instead of the node.
234 cdk_kbnode_find_packet (cdk_kbnode_t node
, cdk_packet_type_t pkttype
)
238 res
= cdk_kbnode_find (node
, pkttype
);
239 return res
? res
->pkt
: NULL
;
246 * Walks through a list of kbnodes. This function returns
247 * the next kbnode for each call; before using the function the first
248 * time, the caller must set CONTEXT to NULL (This has simply the effect
249 * to start with ROOT).
252 cdk_kbnode_walk (cdk_kbnode_t root
, cdk_kbnode_t
* ctx
, int all
)
269 while (!all
&& n
&& n
->is_deleted
);
278 * Commits changes made to the kblist at ROOT. Note that ROOT my change,
279 * and it is therefore passed by reference.
280 * The function has the effect of removing all nodes marked as deleted.
282 * Returns: true if any node has been changed
285 cdk_kbnode_commit (cdk_kbnode_t
* root
)
290 for (n
= *root
, nl
= NULL
; n
; n
= nl
->next
)
295 *root
= nl
= n
->next
;
299 cdk_pkt_release (n
->pkt
);
312 * @root: the root node
313 * @node: the node to delete
315 * Removes a node from the root node.
318 cdk_kbnode_remove (cdk_kbnode_t
* root
, cdk_kbnode_t node
)
322 for (n
= *root
, nl
= NULL
; n
; n
= nl
->next
)
327 *root
= nl
= n
->next
;
331 cdk_pkt_release (n
->pkt
);
344 * @node: the node to move
345 * @where: destination place where to move the node.
347 * Moves NODE behind right after WHERE or to the beginning if WHERE is NULL.
350 cdk_kbnode_move (cdk_kbnode_t
* root
, cdk_kbnode_t node
, cdk_kbnode_t where
)
352 cdk_kbnode_t tmp
, prev
;
354 if (!root
|| !*root
|| !node
)
356 for (prev
= *root
; prev
&& prev
->next
!= node
; prev
= prev
->next
)
359 return; /* Node is not in the list */
362 { /* Move node before root */
365 prev
->next
= node
->next
;
370 if (node
== where
) /* Move it after where. */
373 node
->next
= where
->next
;
380 * cdk_kbnode_get_packet:
381 * @node: the key node
383 * Get packet in node.
385 * Returns: the packet which is stored inside the node in @node.
388 cdk_kbnode_get_packet (cdk_kbnode_t node
)
397 * cdk_kbnode_read_from_mem:
398 * @ret_node: the new key node
399 * @armor: whether base64 or not
400 * @buf: the buffer which stores the key sequence
401 * @buflen: the length of the buffer
403 * Tries to read a key node from the memory buffer @buf.
406 cdk_kbnode_read_from_mem (cdk_kbnode_t
* ret_node
,
408 const byte
* buf
, size_t buflen
)
413 if (!ret_node
|| !buf
)
414 return CDK_Inv_Value
;
418 return gnutls_assert_val(CDK_Too_Short
);
420 rc
= cdk_stream_tmp_from_mem (buf
, buflen
, &inp
);
422 return gnutls_assert_val(rc
);
425 cdk_stream_set_armor_flag (inp
, 0);
427 rc
= cdk_keydb_get_keyblock (inp
, ret_node
);
430 cdk_stream_close (inp
);
436 * cdk_kbnode_write_to_mem_alloc:
437 * @node: the key node
438 * @r_buf: buffer to hold the raw data
439 * @r_buflen: buffer length of the allocated raw data.
441 * The function acts similar to cdk_kbnode_write_to_mem but
442 * it allocates the buffer to avoid the lengthy second run.
445 cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node
,
446 byte
** r_buf
, size_t * r_buflen
)
453 if (!node
|| !r_buf
|| !r_buflen
)
456 return CDK_Inv_Value
;
462 rc
= cdk_stream_tmp_new (&s
);
469 for (n
= node
; n
; n
= n
->next
)
471 /* Skip all packets which cannot occur in a key composition. */
472 if (n
->pkt
->pkttype
!= CDK_PKT_PUBLIC_KEY
&&
473 n
->pkt
->pkttype
!= CDK_PKT_PUBLIC_SUBKEY
&&
474 n
->pkt
->pkttype
!= CDK_PKT_SECRET_KEY
&&
475 n
->pkt
->pkttype
!= CDK_PKT_SECRET_SUBKEY
&&
476 n
->pkt
->pkttype
!= CDK_PKT_SIGNATURE
&&
477 n
->pkt
->pkttype
!= CDK_PKT_USER_ID
&&
478 n
->pkt
->pkttype
!= CDK_PKT_ATTRIBUTE
)
480 rc
= cdk_pkt_write (s
, n
->pkt
);
483 cdk_stream_close (s
);
489 cdk_stream_seek (s
, 0);
490 len
= cdk_stream_get_length (s
);
491 *r_buf
= cdk_calloc (1, len
);
492 *r_buflen
= cdk_stream_read (s
, *r_buf
, len
);
493 cdk_stream_close (s
);
499 * cdk_kbnode_write_to_mem:
500 * @node: the key node
501 * @buf: the buffer to store the node data
502 * @r_nbytes: the new length of the buffer.
504 * Tries to write the contents of the key node to the buffer @buf and
505 * return the length of it in @r_nbytes. If buf is (0), only the
506 * length of the node is calculated and returned in @r_nbytes.
507 * Whenever it is possible, the cdk_kbnode_write_to_mem_alloc should be used.
510 cdk_kbnode_write_to_mem (cdk_kbnode_t node
, byte
* buf
, size_t * r_nbytes
)
517 if (!node
|| !r_nbytes
)
520 return CDK_Inv_Value
;
523 rc
= cdk_stream_tmp_new (&s
);
530 for (n
= node
; n
; n
= n
->next
)
532 /* Skip all packets which cannot occur in a key composition. */
533 if (n
->pkt
->pkttype
!= CDK_PKT_PUBLIC_KEY
&&
534 n
->pkt
->pkttype
!= CDK_PKT_PUBLIC_SUBKEY
&&
535 n
->pkt
->pkttype
!= CDK_PKT_SECRET_KEY
&&
536 n
->pkt
->pkttype
!= CDK_PKT_SECRET_SUBKEY
&&
537 n
->pkt
->pkttype
!= CDK_PKT_SIGNATURE
&&
538 n
->pkt
->pkttype
!= CDK_PKT_USER_ID
&&
539 n
->pkt
->pkttype
!= CDK_PKT_ATTRIBUTE
)
541 rc
= cdk_pkt_write (s
, n
->pkt
);
544 cdk_stream_close (s
);
550 cdk_stream_seek (s
, 0);
551 len
= cdk_stream_get_length (s
);
554 *r_nbytes
= len
; /* Only return the length of the buffer */
555 cdk_stream_close (s
);
564 *r_nbytes
= cdk_stream_read (s
, buf
, len
);
567 cdk_stream_close (s
);
574 * @node: the key node
575 * @hashctx: uint8_t pointer to the hash context
576 * @is_v4: OpenPGP signature (yes=1, no=0)
577 * @pkttype: packet type to hash (if (0) use the packet type from the node)
578 * @flags: flags which depend on the operation
580 * Hashes the key node contents. Two modes are supported. If the packet
581 * type is used (!= 0) then the function searches the first node with
582 * this type. Otherwise the node is seen as a single node and the type
583 * is extracted from it.
586 cdk_kbnode_hash (cdk_kbnode_t node
, digest_hd_st
* md
, int is_v4
,
587 cdk_packet_type_t pkttype
, int flags
)
594 return CDK_Inv_Value
;
598 pkt
= cdk_kbnode_get_packet (node
);
599 pkttype
= pkt
->pkttype
;
603 pkt
= cdk_kbnode_find_packet (node
, pkttype
);
607 return CDK_Inv_Packet
;
613 case CDK_PKT_PUBLIC_KEY
:
614 case CDK_PKT_PUBLIC_SUBKEY
:
615 _cdk_hash_pubkey (pkt
->pkt
.public_key
, md
, flags
& 1);
618 case CDK_PKT_USER_ID
:
619 _cdk_hash_userid (pkt
->pkt
.user_id
, is_v4
, md
);
622 case CDK_PKT_SIGNATURE
:
623 _cdk_hash_sig_data (pkt
->pkt
.signature
, md
);