PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/webview/native/Source/WTF/wtf/CryptographicallyRandomNumber.cpp

https://bitbucket.org/rbair/rbair-controls-8
C++ | 180 lines | 121 code | 30 blank | 29 comment | 5 complexity | 74a4297b39160e2674017ba61c9a20a7 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (c) 1996, David Mazieres <dm@uun.org>
  3. * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * Arc4 random number generator for OpenBSD.
  19. *
  20. * This code is derived from section 17.1 of Applied Cryptography,
  21. * second edition, which describes a stream cipher allegedly
  22. * compatible with RSA Labs "RC4" cipher (the actual description of
  23. * which is a trade secret). The same algorithm is used as a stream
  24. * cipher called "arcfour" in Tatu Ylonen's ssh package.
  25. *
  26. * RC4 is a registered trademark of RSA Laboratories.
  27. */
  28. #include "config.h"
  29. #include "CryptographicallyRandomNumber.h"
  30. #include "OSRandomSource.h"
  31. #include "StdLibExtras.h"
  32. #include "ThreadingPrimitives.h"
  33. namespace WTF {
  34. #if USE(OS_RANDOMNESS)
  35. namespace {
  36. class ARC4Stream {
  37. public:
  38. ARC4Stream();
  39. uint8_t i;
  40. uint8_t j;
  41. uint8_t s[256];
  42. };
  43. class ARC4RandomNumberGenerator {
  44. public:
  45. ARC4RandomNumberGenerator();
  46. uint32_t randomNumber();
  47. void randomValues(void* buffer, size_t length);
  48. private:
  49. inline void addRandomData(unsigned char *data, int length);
  50. void stir();
  51. void stirIfNeeded();
  52. inline uint8_t getByte();
  53. inline uint32_t getWord();
  54. ARC4Stream m_stream;
  55. int m_count;
  56. Mutex m_mutex;
  57. };
  58. ARC4Stream::ARC4Stream()
  59. {
  60. for (int n = 0; n < 256; n++)
  61. s[n] = n;
  62. i = 0;
  63. j = 0;
  64. }
  65. ARC4RandomNumberGenerator::ARC4RandomNumberGenerator()
  66. : m_count(0)
  67. {
  68. }
  69. void ARC4RandomNumberGenerator::addRandomData(unsigned char* data, int length)
  70. {
  71. m_stream.i--;
  72. for (int n = 0; n < 256; n++) {
  73. m_stream.i++;
  74. uint8_t si = m_stream.s[m_stream.i];
  75. m_stream.j += si + data[n % length];
  76. m_stream.s[m_stream.i] = m_stream.s[m_stream.j];
  77. m_stream.s[m_stream.j] = si;
  78. }
  79. m_stream.j = m_stream.i;
  80. }
  81. void ARC4RandomNumberGenerator::stir()
  82. {
  83. unsigned char randomness[128];
  84. size_t length = sizeof(randomness);
  85. cryptographicallyRandomValuesFromOS(randomness, length);
  86. addRandomData(randomness, length);
  87. // Discard early keystream, as per recommendations in:
  88. // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
  89. for (int i = 0; i < 256; i++)
  90. getByte();
  91. m_count = 1600000;
  92. }
  93. void ARC4RandomNumberGenerator::stirIfNeeded()
  94. {
  95. if (m_count <= 0)
  96. stir();
  97. }
  98. uint8_t ARC4RandomNumberGenerator::getByte()
  99. {
  100. m_stream.i++;
  101. uint8_t si = m_stream.s[m_stream.i];
  102. m_stream.j += si;
  103. uint8_t sj = m_stream.s[m_stream.j];
  104. m_stream.s[m_stream.i] = sj;
  105. m_stream.s[m_stream.j] = si;
  106. return (m_stream.s[(si + sj) & 0xff]);
  107. }
  108. uint32_t ARC4RandomNumberGenerator::getWord()
  109. {
  110. uint32_t val;
  111. val = getByte() << 24;
  112. val |= getByte() << 16;
  113. val |= getByte() << 8;
  114. val |= getByte();
  115. return val;
  116. }
  117. uint32_t ARC4RandomNumberGenerator::randomNumber()
  118. {
  119. MutexLocker locker(m_mutex);
  120. m_count -= 4;
  121. stirIfNeeded();
  122. return getWord();
  123. }
  124. void ARC4RandomNumberGenerator::randomValues(void* buffer, size_t length)
  125. {
  126. MutexLocker locker(m_mutex);
  127. unsigned char* result = reinterpret_cast<unsigned char*>(buffer);
  128. stirIfNeeded();
  129. while (length--) {
  130. m_count--;
  131. stirIfNeeded();
  132. result[length] = getByte();
  133. }
  134. }
  135. ARC4RandomNumberGenerator& sharedRandomNumberGenerator()
  136. {
  137. DEFINE_STATIC_LOCAL(ARC4RandomNumberGenerator, randomNumberGenerator, ());
  138. return randomNumberGenerator;
  139. }
  140. }
  141. uint32_t cryptographicallyRandomNumber()
  142. {
  143. return sharedRandomNumberGenerator().randomNumber();
  144. }
  145. void cryptographicallyRandomValues(void* buffer, size_t length)
  146. {
  147. sharedRandomNumberGenerator().randomValues(buffer, length);
  148. }
  149. #endif
  150. }