2 * Copyright (c) 1996, David Mazieres <dm@uun.org>
3 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
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.
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.
19 * Arc4 random number generator for OpenBSD.
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.
27 * RC4 is a registered trademark of RSA Laboratories.
31 #include "wtf/CryptographicallyRandomNumber.h"
33 #include "wtf/StdLibExtras.h"
34 #include "wtf/Threading.h"
35 #include "wtf/ThreadingPrimitives.h"
39 static RandomNumberSource sourceFunction
;
41 void setRandomSource(RandomNumberSource source
)
43 sourceFunction
= source
;
57 class ARC4RandomNumberGenerator
{
58 WTF_MAKE_FAST_ALLOCATED(ARC4RandomNumberGenerator
);
60 ARC4RandomNumberGenerator();
62 uint32_t randomNumber();
63 void randomValues(void* buffer
, size_t length
);
66 inline void addRandomData(unsigned char *data
, int length
);
69 inline uint8_t getByte();
70 inline uint32_t getWord();
77 ARC4Stream::ARC4Stream()
79 for (int n
= 0; n
< 256; n
++)
80 s
[n
] = static_cast<uint8_t>(n
);
85 ARC4RandomNumberGenerator::ARC4RandomNumberGenerator()
90 void ARC4RandomNumberGenerator::addRandomData(unsigned char* data
, int length
)
93 for (int n
= 0; n
< 256; n
++) {
95 uint8_t si
= m_stream
.s
[m_stream
.i
];
96 m_stream
.j
+= si
+ data
[n
% length
];
97 m_stream
.s
[m_stream
.i
] = m_stream
.s
[m_stream
.j
];
98 m_stream
.s
[m_stream
.j
] = si
;
100 m_stream
.j
= m_stream
.i
;
103 void ARC4RandomNumberGenerator::stir()
105 unsigned char randomness
[128];
106 size_t length
= sizeof(randomness
);
107 (*sourceFunction
)(randomness
, length
);
108 addRandomData(randomness
, length
);
110 // Discard early keystream, as per recommendations in:
111 // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
112 for (int i
= 0; i
< 256; i
++)
117 void ARC4RandomNumberGenerator::stirIfNeeded()
123 uint8_t ARC4RandomNumberGenerator::getByte()
126 uint8_t si
= m_stream
.s
[m_stream
.i
];
128 uint8_t sj
= m_stream
.s
[m_stream
.j
];
129 m_stream
.s
[m_stream
.i
] = sj
;
130 m_stream
.s
[m_stream
.j
] = si
;
131 return (m_stream
.s
[(si
+ sj
) & 0xff]);
134 uint32_t ARC4RandomNumberGenerator::getWord()
137 val
= getByte() << 24;
138 val
|= getByte() << 16;
139 val
|= getByte() << 8;
144 uint32_t ARC4RandomNumberGenerator::randomNumber()
146 MutexLocker
locker(m_mutex
);
153 void ARC4RandomNumberGenerator::randomValues(void* buffer
, size_t length
)
155 MutexLocker
locker(m_mutex
);
157 unsigned char* result
= reinterpret_cast<unsigned char*>(buffer
);
162 result
[length
] = getByte();
166 ARC4RandomNumberGenerator
& sharedRandomNumberGenerator()
168 AtomicallyInitializedStaticReference(ARC4RandomNumberGenerator
, randomNumberGenerator
, new ARC4RandomNumberGenerator
);
169 return randomNumberGenerator
;
175 uint32_t cryptographicallyRandomNumber()
177 return sharedRandomNumberGenerator().randomNumber();
180 void cryptographicallyRandomValues(void* buffer
, size_t length
)
182 sharedRandomNumberGenerator().randomValues(buffer
, length
);