paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / util / crypto_mpi.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013 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 /**
20  * @file util/crypto_mpi.c
21  * @brief Helper functions for libgcrypt MPIs
22  * @author Christian Grothoff
23  * @author Florian Dold
24  */
25 #include "platform.h"
26 #include <gcrypt.h>
27 #include "gnunet_crypto_lib.h"
28
29
30 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-mpi", __VA_ARGS__)
31
32 /**
33  * Log an error message at log-level 'level' that indicates
34  * a failure of the command 'cmd' with the message given
35  * by gcry_strerror(rc).
36  */
37 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
38
39
40 /**
41  * If target != size, move @a target bytes to the end of the size-sized
42  * buffer and zero out the first @a target - @a size bytes.
43  *
44  * @param buf original buffer
45  * @param size number of bytes in @a buf
46  * @param target target size of the buffer
47  */
48 static void
49 adjust (void *buf,
50         size_t size,
51         size_t target)
52 {
53   char *p = buf;
54
55   if (size < target)
56   {
57     memmove (&p[target - size], buf, size);
58     memset (buf, 0, target - size);
59   }
60 }
61
62
63 /**
64  * Output the given MPI value to the given buffer in
65  * network byte order.
66  * The MPI @a val may not be negative.
67  *
68  * @param buf where to output to
69  * @param size number of bytes in @a buf
70  * @param val value to write to @a buf
71  */
72 void
73 GNUNET_CRYPTO_mpi_print_unsigned (void *buf,
74                                   size_t size,
75                                   gcry_mpi_t val)
76 {
77   size_t rsize;
78   int rc;
79
80   if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE))
81   {
82     /* Store opaque MPIs left aligned into the buffer.  */
83     unsigned int nbits;
84     const void *p;
85
86     p = gcry_mpi_get_opaque (val, &nbits);
87     GNUNET_assert (p);
88     rsize = (nbits+7)/8;
89     if (rsize > size)
90       rsize = size;
91     GNUNET_memcpy (buf, p, rsize);
92     if (rsize < size)
93       memset (buf+rsize, 0, size - rsize);
94   }
95   else
96   {
97     /* Store regular MPIs as unsigned integers right aligned into
98        the buffer.  */
99     rsize = size;
100     if (0 !=
101         (rc = gcry_mpi_print (GCRYMPI_FMT_USG,
102                               buf,
103                               rsize, &rsize,
104                               val)))
105     {
106       LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
107                 "gcry_mpi_print",
108                 rc);
109       GNUNET_assert (0);
110     }
111     adjust (buf, rsize, size);
112   }
113 }
114
115
116 /**
117  * Convert data buffer into MPI value.
118  * The buffer is interpreted as network
119  * byte order, unsigned integer.
120  *
121  * @param result where to store MPI value (allocated)
122  * @param data raw data (GCRYMPI_FMT_USG)
123  * @param size number of bytes in @a data
124  */
125 void
126 GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
127                                  const void *data,
128                                  size_t size)
129 {
130   int rc;
131
132   if (0 != (rc = gcry_mpi_scan (result,
133                                 GCRYMPI_FMT_USG,
134                                 data, size, &size)))
135   {
136     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
137               "gcry_mpi_scan",
138               rc);
139     GNUNET_assert (0);
140   }
141 }
142
143 /* end of crypto_mpi.c */