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