d5699d76e3ade8507e8c6b9c6fbab09d42f43be0
[oweals/gnunet.git] / src / secretsharing / secretsharing_common.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2014 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "secretsharing.h"
20
21 /**
22  * Read a share from its binary representation.
23  *
24  * @param data Binary representation of the share.
25  * @param len Length of @a data.
26  * @param[out] readlen Number of bytes read,
27  *             ignored if NULL.
28  * @return The share, or NULL on error.
29  */
30 struct GNUNET_SECRETSHARING_Share *
31 GNUNET_SECRETSHARING_share_read (const void *data,
32                                  size_t len,
33                                  size_t *readlen)
34 {
35   struct GNUNET_SECRETSHARING_Share *share;
36   const struct GNUNET_SECRETSHARING_ShareHeaderNBO *sh = data;
37   const char *p;
38   size_t n;
39   uint16_t payload_size;
40
41   payload_size = ntohs (sh->num_peers) *
42       (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) +
43        sizeof (struct GNUNET_PeerIdentity));
44
45   if (NULL != readlen)
46     *readlen = payload_size + sizeof *sh;
47
48   share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
49
50   share->threshold = ntohs (sh->threshold);
51   share->num_peers = ntohs (sh->num_peers);
52   share->my_peer = ntohs (sh->my_peer);
53
54   share->my_share = sh->my_share;
55   share->public_key = sh->public_key;
56
57   p = (const char *) &sh[1];
58
59   n = share->num_peers * sizeof (struct GNUNET_PeerIdentity);
60   share->peers = GNUNET_new_array (share->num_peers,
61                                    struct GNUNET_PeerIdentity);
62   GNUNET_memcpy (share->peers, p, n);
63   p += n;
64
65   n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement);
66   share->sigmas = GNUNET_new_array (share->num_peers,
67                                     struct GNUNET_SECRETSHARING_FieldElement);
68   GNUNET_memcpy (share->sigmas, p, n);
69   p += n;
70
71   n = share->num_peers * sizeof (uint16_t);
72   share->original_indices = GNUNET_new_array (share->num_peers,
73                                               uint16_t);
74   GNUNET_memcpy (share->original_indices, p, n);
75
76   return share;
77 }
78
79
80 /**
81  * Convert a share to its binary representation.
82  * Can be called with a NULL @a buf to get the size of the share.
83  *
84  * @param share Share to write.
85  * @param buf Buffer to write to.
86  * @param buflen Number of writable bytes in @a buf.
87  * @param[out] writelen Pointer to store number of bytes written,
88  *             ignored if NULL.
89  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure.
90  */
91 int
92 GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share,
93                                   void *buf, size_t buflen, size_t *writelen)
94 {
95   uint16_t payload_size;
96   struct GNUNET_SECRETSHARING_ShareHeaderNBO *sh;
97   char *p;
98   int n;
99
100   payload_size = share->num_peers *
101       (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) +
102        sizeof (struct GNUNET_PeerIdentity));
103
104   if (NULL != writelen)
105     *writelen = payload_size + sizeof (struct GNUNET_SECRETSHARING_ShareHeaderNBO);
106
107   /* just a query for the writelen */
108   if (buf == NULL)
109     return GNUNET_OK;
110
111   /* wrong buffer size */
112   if (buflen < payload_size + sizeof (struct GNUNET_SECRETSHARING_ShareHeaderNBO))
113     return GNUNET_SYSERR;
114
115   sh = buf;
116
117   sh->threshold = htons (share->threshold);
118   sh->num_peers = htons (share->num_peers);
119   sh->my_peer = htons (share->my_peer);
120
121   sh->my_share = share->my_share;
122   sh->public_key = share->public_key;
123
124   p = (void *) &sh[1];
125
126   n = share->num_peers * sizeof (struct GNUNET_PeerIdentity);
127   GNUNET_memcpy (p, share->peers, n);
128   p += n;
129
130   n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement);
131   GNUNET_memcpy (p, share->sigmas, n);
132   p += n;
133
134   n = share->num_peers * sizeof (uint16_t);
135   GNUNET_memcpy (p, share->original_indices, n);
136
137   return GNUNET_OK;
138 }
139
140
141 void
142 GNUNET_SECRETSHARING_share_destroy (struct GNUNET_SECRETSHARING_Share *share)
143 {
144   GNUNET_free (share->original_indices);
145   share->original_indices = NULL;
146   GNUNET_free (share->sigmas);
147   share->sigmas = NULL;
148   GNUNET_free (share->peers);
149   share->peers = NULL;
150   GNUNET_free (share);
151 }