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