crypto_mpi.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
  32. /**
  33. * If target != size, move @a target bytes to the end of the size-sized
  34. * buffer and zero out the first @a target - @a size bytes.
  35. *
  36. * @param buf original buffer
  37. * @param size number of bytes in @a buf
  38. * @param target target size of the buffer
  39. */
  40. static void
  41. adjust (void *buf,
  42. size_t size,
  43. size_t target)
  44. {
  45. char *p = buf;
  46. if (size < target)
  47. {
  48. memmove (&p[target - size], buf, size);
  49. memset (buf, 0, target - size);
  50. }
  51. }
  52. /**
  53. * Output the given MPI value to the given buffer in
  54. * network byte order.
  55. * The MPI @a val may not be negative.
  56. *
  57. * @param buf where to output to
  58. * @param size number of bytes in @a buf
  59. * @param val value to write to @a buf
  60. */
  61. void
  62. GNUNET_CRYPTO_mpi_print_unsigned (void *buf,
  63. size_t size,
  64. gcry_mpi_t val)
  65. {
  66. size_t rsize;
  67. int rc;
  68. if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE))
  69. {
  70. /* Store opaque MPIs left aligned into the buffer. */
  71. unsigned int nbits;
  72. const void *p;
  73. p = gcry_mpi_get_opaque (val, &nbits);
  74. GNUNET_assert (p);
  75. rsize = (nbits+7)/8;
  76. if (rsize > size)
  77. rsize = size;
  78. GNUNET_memcpy (buf, p, rsize);
  79. if (rsize < size)
  80. memset (buf+rsize, 0, size - rsize);
  81. }
  82. else
  83. {
  84. /* Store regular MPIs as unsigned integers right aligned into
  85. the buffer. */
  86. rsize = size;
  87. if (0 !=
  88. (rc = gcry_mpi_print (GCRYMPI_FMT_USG,
  89. buf,
  90. rsize, &rsize,
  91. val)))
  92. {
  93. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  94. "gcry_mpi_print",
  95. rc);
  96. GNUNET_assert (0);
  97. }
  98. adjust (buf, rsize, size);
  99. }
  100. }
  101. /**
  102. * Convert data buffer into MPI value.
  103. * The buffer is interpreted as network
  104. * byte order, unsigned integer.
  105. *
  106. * @param result where to store MPI value (allocated)
  107. * @param data raw data (GCRYMPI_FMT_USG)
  108. * @param size number of bytes in @a data
  109. */
  110. void
  111. GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
  112. const void *data,
  113. size_t size)
  114. {
  115. int rc;
  116. if (0 != (rc = gcry_mpi_scan (result,
  117. GCRYMPI_FMT_USG,
  118. data, size, &size)))
  119. {
  120. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  121. "gcry_mpi_scan",
  122. rc);
  123. GNUNET_assert (0);
  124. }
  125. }
  126. /* end of crypto_mpi.c */