Merge "Fix build break by removing TIZEN_RECORDING_SURFACE_SET" into tizen_2.1
[framework/web/webkit-efl.git] / Source / WTF / wtf / CryptographicallyRandomNumber.cpp
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 /*
19  * Arc4 random number generator for OpenBSD.
20  *
21  * This code is derived from section 17.1 of Applied Cryptography,
22  * second edition, which describes a stream cipher allegedly
23  * compatible with RSA Labs "RC4" cipher (the actual description of
24  * which is a trade secret).  The same algorithm is used as a stream
25  * cipher called "arcfour" in Tatu Ylonen's ssh package.
26  *
27  * RC4 is a registered trademark of RSA Laboratories.
28  */
29
30 #include "config.h"
31 #include "CryptographicallyRandomNumber.h"
32
33 #include "OSRandomSource.h"
34 #include "StdLibExtras.h"
35 #include "ThreadingPrimitives.h"
36
37 namespace WTF {
38
39 #if USE(OS_RANDOMNESS)
40
41 namespace {
42
43 class ARC4Stream {
44 public:
45     ARC4Stream();
46
47     uint8_t i;
48     uint8_t j;
49     uint8_t s[256];
50 };
51
52 class ARC4RandomNumberGenerator {
53 public:
54     ARC4RandomNumberGenerator();
55
56     uint32_t randomNumber();
57     void randomValues(void* buffer, size_t length);
58
59 private:
60     inline void addRandomData(unsigned char *data, int length);
61     void stir();
62     void stirIfNeeded();
63     inline uint8_t getByte();
64     inline uint32_t getWord();
65
66     ARC4Stream m_stream;
67     int m_count;
68     Mutex m_mutex;
69 };
70
71 ARC4Stream::ARC4Stream()
72 {
73     for (int n = 0; n < 256; n++)
74         s[n] = n;
75     i = 0;
76     j = 0;
77 }
78
79 ARC4RandomNumberGenerator::ARC4RandomNumberGenerator()
80     : m_count(0)
81 {
82 }
83
84 void ARC4RandomNumberGenerator::addRandomData(unsigned char* data, int length)
85 {
86     m_stream.i--;
87     for (int n = 0; n < 256; n++) {
88         m_stream.i++;
89         uint8_t si = m_stream.s[m_stream.i];
90         m_stream.j += si + data[n % length];
91         m_stream.s[m_stream.i] = m_stream.s[m_stream.j];
92         m_stream.s[m_stream.j] = si;
93     }
94     m_stream.j = m_stream.i;
95 }
96
97 void ARC4RandomNumberGenerator::stir()
98 {
99     unsigned char randomness[128];
100     size_t length = sizeof(randomness);
101     cryptographicallyRandomValuesFromOS(randomness, length);
102     addRandomData(randomness, length);
103
104     // Discard early keystream, as per recommendations in:
105     // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
106     for (int i = 0; i < 256; i++)
107         getByte();
108     m_count = 1600000;
109 }
110
111 void ARC4RandomNumberGenerator::stirIfNeeded()
112 {
113     if (m_count <= 0)
114         stir();
115 }
116
117 uint8_t ARC4RandomNumberGenerator::getByte()
118 {
119     m_stream.i++;
120     uint8_t si = m_stream.s[m_stream.i];
121     m_stream.j += si;
122     uint8_t sj = m_stream.s[m_stream.j];
123     m_stream.s[m_stream.i] = sj;
124     m_stream.s[m_stream.j] = si;
125     return (m_stream.s[(si + sj) & 0xff]);
126 }
127
128 uint32_t ARC4RandomNumberGenerator::getWord()
129 {
130     uint32_t val;
131     val = getByte() << 24;
132     val |= getByte() << 16;
133     val |= getByte() << 8;
134     val |= getByte();
135     return val;
136 }
137
138 uint32_t ARC4RandomNumberGenerator::randomNumber()
139 {
140     MutexLocker locker(m_mutex);
141
142     m_count -= 4;
143     stirIfNeeded();
144     return getWord();
145 }
146
147 void ARC4RandomNumberGenerator::randomValues(void* buffer, size_t length)
148 {
149     MutexLocker locker(m_mutex);
150
151     unsigned char* result = reinterpret_cast<unsigned char*>(buffer);
152     stirIfNeeded();
153     while (length--) {
154         m_count--;
155         stirIfNeeded();
156         result[length] = getByte();
157     }
158 }
159
160 ARC4RandomNumberGenerator& sharedRandomNumberGenerator()
161 {
162     DEFINE_STATIC_LOCAL(ARC4RandomNumberGenerator, randomNumberGenerator, ());
163     return randomNumberGenerator;
164 }
165
166 }
167
168 uint32_t cryptographicallyRandomNumber()
169 {
170     return sharedRandomNumberGenerator().randomNumber();
171 }
172
173 void cryptographicallyRandomValues(void* buffer, size_t length)
174 {
175     sharedRandomNumberGenerator().randomValues(buffer, length);
176 }
177
178 #endif
179
180 }