PageRenderTime 50ms CodeModel.GetById 46ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

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