/* This file is part of GNUnet. Copyright (C) 2012, 2013 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file util/crypto_mpi.c * @brief Helper functions for libgcrypt MPIs * @author Christian Grothoff * @author Florian Dold */ #include "platform.h" #include #include "gnunet_crypto_lib.h" #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-mpi", __VA_ARGS__) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). */ #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) /** * If target != size, move @a target bytes to the end of the size-sized * buffer and zero out the first @a target - @a size bytes. * * @param buf original buffer * @param size number of bytes in @a buf * @param target target size of the buffer */ static void adjust (void *buf, size_t size, size_t target) { char *p = buf; if (size < target) { memmove (&p[target - size], buf, size); memset (buf, 0, target - size); } } /** * Output the given MPI value to the given buffer in * network byte order. * The MPI @a val may not be negative. * * @param buf where to output to * @param size number of bytes in @a buf * @param val value to write to @a buf */ void GNUNET_CRYPTO_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val) { size_t rsize; int rc; if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE)) { /* Store opaque MPIs left aligned into the buffer. */ unsigned int nbits; const void *p; p = gcry_mpi_get_opaque (val, &nbits); GNUNET_assert (p); rsize = (nbits + 7) / 8; if (rsize > size) rsize = size; GNUNET_memcpy (buf, p, rsize); if (rsize < size) memset (buf + rsize, 0, size - rsize); } else { /* Store regular MPIs as unsigned integers right aligned into the buffer. */ rsize = size; if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize, val))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); GNUNET_assert (0); } adjust (buf, rsize, size); } } /** * Convert data buffer into MPI value. * The buffer is interpreted as network * byte order, unsigned integer. * * @param result where to store MPI value (allocated) * @param data raw data (GCRYMPI_FMT_USG) * @param size number of bytes in @a data */ void GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size) { int rc; if (0 != (rc = gcry_mpi_scan (result, GCRYMPI_FMT_USG, data, size, &size))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); GNUNET_assert (0); } } /* end of crypto_mpi.c */