bytes.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.] */
  56. #include <openssl/bn.h>
  57. #include <assert.h>
  58. #include <limits.h>
  59. #include "internal.h"
  60. BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
  61. size_t num_words;
  62. unsigned m;
  63. BN_ULONG word = 0;
  64. BIGNUM *bn = NULL;
  65. if (ret == NULL) {
  66. ret = bn = BN_new();
  67. }
  68. if (ret == NULL) {
  69. return NULL;
  70. }
  71. if (len == 0) {
  72. ret->top = 0;
  73. return ret;
  74. }
  75. num_words = ((len - 1) / BN_BYTES) + 1;
  76. m = (len - 1) % BN_BYTES;
  77. if (!bn_wexpand(ret, num_words)) {
  78. if (bn) {
  79. BN_free(bn);
  80. }
  81. return NULL;
  82. }
  83. // |bn_wexpand| must check bounds on |num_words| to write it into
  84. // |ret->dmax|.
  85. assert(num_words <= INT_MAX);
  86. ret->top = (int)num_words;
  87. ret->neg = 0;
  88. while (len--) {
  89. word = (word << 8) | *(in++);
  90. if (m-- == 0) {
  91. ret->d[--num_words] = word;
  92. word = 0;
  93. m = BN_BYTES - 1;
  94. }
  95. }
  96. // need to call this due to clear byte at top if avoiding having the top bit
  97. // set (-ve number)
  98. bn_correct_top(ret);
  99. return ret;
  100. }
  101. BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
  102. BIGNUM *bn = NULL;
  103. if (ret == NULL) {
  104. bn = BN_new();
  105. ret = bn;
  106. }
  107. if (ret == NULL) {
  108. return NULL;
  109. }
  110. if (len == 0) {
  111. ret->top = 0;
  112. ret->neg = 0;
  113. return ret;
  114. }
  115. // Reserve enough space in |ret|.
  116. size_t num_words = ((len - 1) / BN_BYTES) + 1;
  117. if (!bn_wexpand(ret, num_words)) {
  118. BN_free(bn);
  119. return NULL;
  120. }
  121. ret->top = num_words;
  122. // Make sure the top bytes will be zeroed.
  123. ret->d[num_words - 1] = 0;
  124. // We only support little-endian platforms, so we can simply memcpy the
  125. // internal representation.
  126. OPENSSL_memcpy(ret->d, in, len);
  127. bn_correct_top(ret);
  128. return ret;
  129. }
  130. size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
  131. size_t n, i;
  132. BN_ULONG l;
  133. n = i = BN_num_bytes(in);
  134. while (i--) {
  135. l = in->d[i / BN_BYTES];
  136. *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
  137. }
  138. return n;
  139. }
  140. int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
  141. // If we don't have enough space, fail out.
  142. size_t num_bytes = BN_num_bytes(in);
  143. if (len < num_bytes) {
  144. return 0;
  145. }
  146. // We only support little-endian platforms, so we can simply memcpy into the
  147. // internal representation.
  148. OPENSSL_memcpy(out, in->d, num_bytes);
  149. // Pad out the rest of the buffer with zeroes.
  150. OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
  151. return 1;
  152. }
  153. // constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
  154. // behavior is undefined if |v| takes any other value.
  155. static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
  156. BN_ULONG mask = v;
  157. mask--;
  158. return (~mask & x) | (mask & y);
  159. }
  160. // constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
  161. // must not have their MSBs set.
  162. static int constant_time_le_size_t(size_t x, size_t y) {
  163. return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
  164. }
  165. // read_word_padded returns the |i|'th word of |in|, if it is not out of
  166. // bounds. Otherwise, it returns 0. It does so without branches on the size of
  167. // |in|, however it necessarily does not have the same memory access pattern. If
  168. // the access would be out of bounds, it reads the last word of |in|. |in| must
  169. // not be zero.
  170. static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
  171. // Read |in->d[i]| if valid. Otherwise, read the last word.
  172. BN_ULONG l = in->d[constant_time_select_ulong(
  173. constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
  174. // Clamp to zero if above |d->top|.
  175. return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
  176. }
  177. int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
  178. // Special case for |in| = 0. Just branch as the probability is negligible.
  179. if (BN_is_zero(in)) {
  180. OPENSSL_memset(out, 0, len);
  181. return 1;
  182. }
  183. // Check if the integer is too big. This case can exit early in non-constant
  184. // time.
  185. if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
  186. return 0;
  187. }
  188. if ((len % BN_BYTES) != 0) {
  189. BN_ULONG l = read_word_padded(in, len / BN_BYTES);
  190. if (l >> (8 * (len % BN_BYTES)) != 0) {
  191. return 0;
  192. }
  193. }
  194. // Write the bytes out one by one. Serialization is done without branching on
  195. // the bits of |in| or on |in->top|, but if the routine would otherwise read
  196. // out of bounds, the memory access pattern can't be fixed. However, for an
  197. // RSA key of size a multiple of the word size, the probability of BN_BYTES
  198. // leading zero octets is low.
  199. //
  200. // See Falko Stenzke, "Manger's Attack revisited", ICICS 2010.
  201. size_t i = len;
  202. while (i--) {
  203. BN_ULONG l = read_word_padded(in, i / BN_BYTES);
  204. *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
  205. }
  206. return 1;
  207. }
  208. BN_ULONG BN_get_word(const BIGNUM *bn) {
  209. switch (bn->top) {
  210. case 0:
  211. return 0;
  212. case 1:
  213. return bn->d[0];
  214. default:
  215. return BN_MASK2;
  216. }
  217. }
  218. int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
  219. switch (bn->top) {
  220. case 0:
  221. *out = 0;
  222. return 1;
  223. case 1:
  224. *out = bn->d[0];
  225. return 1;
  226. #if defined(OPENSSL_32_BIT)
  227. case 2:
  228. *out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
  229. return 1;
  230. #endif
  231. default:
  232. return 0;
  233. }
  234. }