1a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root/*
2a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * Copyright (C) 2012 The Android Open Source Project
3a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root *
4a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * you may not use this file except in compliance with the License.
6a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * You may obtain a copy of the License at
7a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root *
8a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root *
10a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * Unless required by applicable law or agreed to in writing, software
11a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * See the License for the specific language governing permissions and
14a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root * limitations under the License.
15a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root */
16a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
18a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
19a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Rootimport java.io.Serializable;
20a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Rootimport java.security.SecureRandomSpi;
21a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
22a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Rootpublic class OpenSSLRandom extends SecureRandomSpi implements Serializable {
23a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    private static final long serialVersionUID = 8506210602917522860L;
24a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
2549336618a762eff280621cf7474021e06e8521faAlex Klyubin    private boolean mSeeded;
2649336618a762eff280621cf7474021e06e8521faAlex Klyubin
27a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    @Override
28a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    protected void engineSetSeed(byte[] seed) {
2949336618a762eff280621cf7474021e06e8521faAlex Klyubin        // NOTE: The contract of the SecureRandomSpi does not appear to prohibit self-seeding here
3049336618a762eff280621cf7474021e06e8521faAlex Klyubin        // (in addition to using the provided seed).
3149336618a762eff280621cf7474021e06e8521faAlex Klyubin        selfSeedIfNotSeeded();
32a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root        NativeCrypto.RAND_seed(seed);
33a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    }
34a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
35a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    @Override
36a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    protected void engineNextBytes(byte[] bytes) {
3749336618a762eff280621cf7474021e06e8521faAlex Klyubin        selfSeedIfNotSeeded();
38a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root        NativeCrypto.RAND_bytes(bytes);
39a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    }
40a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root
41a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    @Override
42a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    protected byte[] engineGenerateSeed(int numBytes) {
4349336618a762eff280621cf7474021e06e8521faAlex Klyubin        selfSeedIfNotSeeded();
44a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root        byte[] output = new byte[numBytes];
45a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root        NativeCrypto.RAND_bytes(output);
46a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root        return output;
47a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root    }
4849336618a762eff280621cf7474021e06e8521faAlex Klyubin
4949336618a762eff280621cf7474021e06e8521faAlex Klyubin    /**
5049336618a762eff280621cf7474021e06e8521faAlex Klyubin     * Self-seeds this instance from the Linux RNG. Does nothing if this instance has already been
5149336618a762eff280621cf7474021e06e8521faAlex Klyubin     * seeded.
5249336618a762eff280621cf7474021e06e8521faAlex Klyubin     */
5349336618a762eff280621cf7474021e06e8521faAlex Klyubin    private void selfSeedIfNotSeeded() {
5449336618a762eff280621cf7474021e06e8521faAlex Klyubin        // NOTE: No need to worry about concurrent access to this field because the worst case is
5549336618a762eff280621cf7474021e06e8521faAlex Klyubin        // that the code below is executed multiple times (by different threads), which may only
5649336618a762eff280621cf7474021e06e8521faAlex Klyubin        // increase the entropy of the OpenSSL PRNG.
5749336618a762eff280621cf7474021e06e8521faAlex Klyubin        if (mSeeded) {
5849336618a762eff280621cf7474021e06e8521faAlex Klyubin            return;
5949336618a762eff280621cf7474021e06e8521faAlex Klyubin        }
6049336618a762eff280621cf7474021e06e8521faAlex Klyubin
6149336618a762eff280621cf7474021e06e8521faAlex Klyubin        seedOpenSSLPRNGFromLinuxRNG();
6249336618a762eff280621cf7474021e06e8521faAlex Klyubin        mSeeded = true;
6349336618a762eff280621cf7474021e06e8521faAlex Klyubin    }
6449336618a762eff280621cf7474021e06e8521faAlex Klyubin
6549336618a762eff280621cf7474021e06e8521faAlex Klyubin    /**
6649336618a762eff280621cf7474021e06e8521faAlex Klyubin     * Obtains a seed from the Linux RNG and mixes it into the OpenSSL PRNG (default RAND engine).
6749336618a762eff280621cf7474021e06e8521faAlex Klyubin     *
6849336618a762eff280621cf7474021e06e8521faAlex Klyubin     * <p>NOTE: This modifies the OpenSSL PRNG shared by all instances of OpenSSLRandom and other
6949336618a762eff280621cf7474021e06e8521faAlex Klyubin     * crypto primitives offered by or built on top of OpenSSL.
7049336618a762eff280621cf7474021e06e8521faAlex Klyubin     */
7149336618a762eff280621cf7474021e06e8521faAlex Klyubin    public static void seedOpenSSLPRNGFromLinuxRNG() {
7249336618a762eff280621cf7474021e06e8521faAlex Klyubin        int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
7349336618a762eff280621cf7474021e06e8521faAlex Klyubin        int bytesRead = NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
7449336618a762eff280621cf7474021e06e8521faAlex Klyubin        if (bytesRead != seedLengthInBytes) {
7549336618a762eff280621cf7474021e06e8521faAlex Klyubin            throw new SecurityException("Failed to read sufficient bytes from /dev/urandom."
7649336618a762eff280621cf7474021e06e8521faAlex Klyubin                    + " Expected: " + seedLengthInBytes + ", actual: " + bytesRead);
7749336618a762eff280621cf7474021e06e8521faAlex Klyubin        }
7849336618a762eff280621cf7474021e06e8521faAlex Klyubin    }
79a0fbe0d37aca24e828c5c0ec4d4bca7a008c1d57Kenny Root}
80