1//
2// RandomStream.cpp
3//
4// Library: Foundation
5// Package: Crypt
6// Module: RandomStream
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/RandomStream.h"
16#include "Poco/Random.h"
17#include "Poco/SHA1Engine.h"
18#if defined(POCO_OS_FAMILY_WINDOWS)
19#include "Poco/UnWindows.h"
20#include <wincrypt.h>
21#elif defined(POCO_OS_FAMILY_UNIX)
22#include <fcntl.h>
23#include <unistd.h>
24#endif
25#include <ctime>
26
27
28namespace Poco {
29
30
31RandomBuf::RandomBuf(): BufferedStreamBuf(256, std::ios::in)
32{
33}
34
35
36RandomBuf::~RandomBuf()
37{
38}
39
40
41int RandomBuf::readFromDevice(char* buffer, std::streamsize length)
42{
43 int n = 0;
44
45#if defined(POCO_OS_FAMILY_WINDOWS)
46 HCRYPTPROV hProvider = 0;
47 CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
48 CryptGenRandom(hProvider, (DWORD) length, (BYTE*) buffer);
49 CryptReleaseContext(hProvider, 0);
50 n = static_cast<int>(length);
51#else
52 #if defined(POCO_OS_FAMILY_UNIX)
53 int fd = open("/dev/urandom", O_RDONLY, 0);
54 if (fd >= 0)
55 {
56 n = read(fd, buffer, length);
57 close(fd);
58 }
59 #endif
60 if (n <= 0)
61 {
62 // x is here as a source of randomness, so it does not make
63 // much sense to protect it with a Mutex.
64 static UInt32 x = 0;
65 Random rnd1(256);
66 Random rnd2(64);
67 x += rnd1.next();
68
69 n = 0;
70 SHA1Engine engine;
71 UInt32 t = (UInt32) std::time(NULL);
72 engine.update(&t, sizeof(t));
73 void* p = this;
74 engine.update(&p, sizeof(p));
75 engine.update(buffer, length);
76 UInt32 junk[32];
77 engine.update(junk, sizeof(junk));
78 while (n < length)
79 {
80 for (int i = 0; i < 100; ++i)
81 {
82 UInt32 r = rnd2.next();
83 engine.update(&r, sizeof(r));
84 engine.update(&x, sizeof(x));
85 x += rnd1.next();
86 }
87 DigestEngine::Digest d = engine.digest();
88 for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end() && n < length; ++it, ++n)
89 {
90 engine.update(*it);
91 *buffer++ = *it++;
92 }
93 }
94 }
95#endif
96 return n;
97}
98
99
100RandomIOS::RandomIOS()
101{
102 poco_ios_init(&_buf);
103}
104
105
106RandomIOS::~RandomIOS()
107{
108}
109
110
111RandomBuf* RandomIOS::rdbuf()
112{
113 return &_buf;
114}
115
116
117RandomInputStream::RandomInputStream(): std::istream(&_buf)
118{
119}
120
121
122RandomInputStream::~RandomInputStream()
123{
124}
125
126
127} // namespace Poco
128