MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
random.cpp
1 /*
2  Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 
20 /* random.cpp implements a crypto secure Random Number Generator using an OS
21  specific seed, switch to /dev/random for more security but may block
22 */
23 
24 #include "runtime.hpp"
25 #include "random.hpp"
26 #include <string.h>
27 #include <time.h>
28 
29 #if defined(_WIN32)
30  #include <windows.h>
31  #include <wincrypt.h>
32 #else
33  #include <errno.h>
34  #include <fcntl.h>
35  #include <unistd.h>
36 #endif // _WIN32
37 
38 namespace TaoCrypt {
39 
40 
41 // Get seed and key cipher
42 RandomNumberGenerator::RandomNumberGenerator()
43 {
44  byte key[32];
45  byte junk[256];
46 
47  seed_.GenerateSeed(key, sizeof(key));
48  cipher_.SetKey(key, sizeof(key));
49  GenerateBlock(junk, sizeof(junk)); // rid initial state
50 }
51 
52 
53 // place a generated block in output
54 void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz)
55 {
56  memset(output, 0, sz);
57  cipher_.Process(output, output, sz);
58 }
59 
60 
61 byte RandomNumberGenerator::GenerateByte()
62 {
63  byte b;
64  GenerateBlock(&b, 1);
65 
66  return b;
67 }
68 
69 
70 #if defined(_WIN32)
71 
72 /* The OS_Seed implementation for windows */
73 
74 OS_Seed::OS_Seed()
75 {
76  if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL,
77  CRYPT_VERIFYCONTEXT))
78  error_.SetError(WINCRYPT_E);
79 }
80 
81 
82 OS_Seed::~OS_Seed()
83 {
84  CryptReleaseContext(handle_, 0);
85 }
86 
87 
88 void OS_Seed::GenerateSeed(byte* output, word32 sz)
89 {
90  if (!CryptGenRandom(handle_, sz, output))
91  error_.SetError(CRYPTGEN_E);
92 }
93 
94 
95 #else
96 
97 /* The default OS_Seed implementation */
98 
99 OS_Seed::OS_Seed()
100 {
101  fd_ = open("/dev/urandom",O_RDONLY);
102  if (fd_ == -1) {
103  fd_ = open("/dev/random",O_RDONLY);
104  if (fd_ == -1)
105  error_.SetError(OPEN_RAN_E);
106  }
107 }
108 
109 
110 OS_Seed::~OS_Seed()
111 {
112  close(fd_);
113 }
114 
115 
116 // may block
117 void OS_Seed::GenerateSeed(byte* output, word32 sz)
118 {
119  while (sz) {
120  int len = read(fd_, output, sz);
121  if (len == -1) {
122  error_.SetError(READ_RAN_E);
123  return;
124  }
125 
126  sz -= len;
127  output += len;
128 
129  if (sz)
130  sleep(1);
131  }
132 }
133 
134 #endif // _WIN32
135 
136 
137 
138 } // namespace