/mordor/streams/random.cpp

http://github.com/mozy/mordor · C++ · 51 lines · 44 code · 7 blank · 0 comment · 10 complexity · 7b62db54f2c0018e8bc0d118c654413e MD5 · raw file

  1. #include "random.h"
  2. #ifndef WINDOWS
  3. #include <openssl/rand.h>
  4. #include "ssl.h"
  5. #endif
  6. #include "mordor/endian.h"
  7. #include "mordor/exception.h"
  8. namespace Mordor {
  9. RandomStream::RandomStream()
  10. {
  11. #ifdef WINDOWS
  12. BOOL ret = ::CryptAcquireContext(&m_hCP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  13. if(!ret || !m_hCP) {
  14. if(lastError() == NTE_BAD_KEYSET) {
  15. ret = ::CryptAcquireContext(&m_hCP, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT);
  16. if(!ret || !m_hCP) {
  17. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptAcquireContext");
  18. }
  19. } else {
  20. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptAcquireContext");
  21. }
  22. }
  23. #endif
  24. }
  25. RandomStream::~RandomStream()
  26. {
  27. #ifdef WINDOWS
  28. ::CryptReleaseContext(m_hCP, 0);
  29. #endif
  30. }
  31. size_t RandomStream::read(void *buffer, size_t length)
  32. {
  33. #ifdef WINDOWS
  34. if (length >= 0xffffffffu)
  35. length = 0xffffffffu;
  36. if (!::CryptGenRandom(m_hCP, static_cast<DWORD>(length), static_cast<BYTE *>(buffer)))
  37. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptGenRandom");
  38. #else
  39. if (!RAND_bytes(static_cast<unsigned char *>(buffer), length))
  40. MORDOR_THROW_EXCEPTION(OpenSSLException());
  41. #endif
  42. return length;
  43. }
  44. }