crypto_mpi.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file util/crypto_mpi.c
  18. * @brief Helper functions for libgcrypt MPIs
  19. * @author Christian Grothoff
  20. * @author Florian Dold
  21. */
  22. #include "platform.h"
  23. #include <gcrypt.h>
  24. #include "gnunet_crypto_lib.h"
  25. #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-mpi", __VA_ARGS__)
  26. /**
  27. * Log an error message at log-level 'level' that indicates
  28. * a failure of the command 'cmd' with the message given
  29. * by gcry_strerror(rc).
  30. */
  31. #define LOG_GCRY(level, cmd, rc) do { LOG (level, _ ( \
  32. "`%s' failed at %s:%d with error: %s\n"), \
  33. cmd, __FILE__, __LINE__, \
  34. gcry_strerror (rc)); } while (0)
  35. /**
  36. * If target != size, move @a target bytes to the end of the size-sized
  37. * buffer and zero out the first @a target - @a size bytes.
  38. *
  39. * @param buf original buffer
  40. * @param size number of bytes in @a buf
  41. * @param target target size of the buffer
  42. */
  43. static void
  44. adjust (void *buf,
  45. size_t size,
  46. size_t target)
  47. {
  48. char *p = buf;
  49. if (size < target)
  50. {
  51. memmove (&p[target - size], buf, size);
  52. memset (buf, 0, target - size);
  53. }
  54. }
  55. /**
  56. * Output the given MPI value to the given buffer in
  57. * network byte order.
  58. * The MPI @a val may not be negative.
  59. *
  60. * @param buf where to output to
  61. * @param size number of bytes in @a buf
  62. * @param val value to write to @a buf
  63. */
  64. void
  65. GNUNET_CRYPTO_mpi_print_unsigned (void *buf,
  66. size_t size,
  67. gcry_mpi_t val)
  68. {
  69. size_t rsize;
  70. int rc;
  71. if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE))
  72. {
  73. /* Store opaque MPIs left aligned into the buffer. */
  74. unsigned int nbits;
  75. const void *p;
  76. p = gcry_mpi_get_opaque (val, &nbits);
  77. GNUNET_assert (p);
  78. rsize = (nbits + 7) / 8;
  79. if (rsize > size)
  80. rsize = size;
  81. GNUNET_memcpy (buf, p, rsize);
  82. if (rsize < size)
  83. memset (buf + rsize, 0, size - rsize);
  84. }
  85. else
  86. {
  87. /* Store regular MPIs as unsigned integers right aligned into
  88. the buffer. */
  89. rsize = size;
  90. if (0 !=
  91. (rc = gcry_mpi_print (GCRYMPI_FMT_USG,
  92. buf,
  93. rsize, &rsize,
  94. val)))
  95. {
  96. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  97. "gcry_mpi_print",
  98. rc);
  99. GNUNET_assert (0);
  100. }
  101. adjust (buf, rsize, size);
  102. }
  103. }
  104. /**
  105. * Convert data buffer into MPI value.
  106. * The buffer is interpreted as network
  107. * byte order, unsigned integer.
  108. *
  109. * @param result where to store MPI value (allocated)
  110. * @param data raw data (GCRYMPI_FMT_USG)
  111. * @param size number of bytes in @a data
  112. */
  113. void
  114. GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
  115. const void *data,
  116. size_t size)
  117. {
  118. int rc;
  119. if (0 != (rc = gcry_mpi_scan (result,
  120. GCRYMPI_FMT_USG,
  121. data, size, &size)))
  122. {
  123. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  124. "gcry_mpi_scan",
  125. rc);
  126. GNUNET_assert (0);
  127. }
  128. }
  129. /**
  130. * Convert little endian data buffer into MPI value.
  131. * The buffer is interpreted as network
  132. * byte order, unsigned integer.
  133. *
  134. * @param result where to store MPI value (allocated)
  135. * @param data raw data (GCRYMPI_FMT_USG)
  136. * @param size number of bytes in @a data
  137. */
  138. void
  139. GNUNET_CRYPTO_mpi_scan_unsigned_le (gcry_mpi_t *result,
  140. const void *data,
  141. size_t size)
  142. {
  143. int rc;
  144. if (0 != (rc = gcry_mpi_scan (result,
  145. GCRYMPI_FMT_USG,
  146. data, size, &size)))
  147. {
  148. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  149. "gcry_mpi_scan",
  150. rc);
  151. GNUNET_assert (0);
  152. }
  153. }
  154. /* end of crypto_mpi.c */