Path: blob/master/src/java.base/share/classes/sun/security/provider/DRBG.java
41159 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.provider;2627import java.io.IOException;28import java.security.AccessController;29import java.security.DrbgParameters;30import java.security.PrivilegedAction;31import java.security.SecureRandomParameters;32import java.security.SecureRandomSpi;33import java.security.Security;34import java.util.Locale;35import static java.security.DrbgParameters.Capability.*;3637/**38* Implement the "SecureRandom.DRBG" algorithm.39*40* About the default "securerandom.drbg.config" value:41*42* The default value in java.security is set to "". This is because43* the default values of different aspects are dependent (For example,44* strength depends on algorithm) and if we write a full string there45* it will be difficult to modify one and keep all others legal.46*47* When changing default values, touch all places including:48*49* 1. comments of the security property in java.security50* 2. Default mech, cap, usedf set in this class51* 3. Default algorithm set in final implementation of each mech52* 4. Default strength set in AbstractDrbg, but the effective53* value can be smaller if an algorithm does not support it.54*55* The default value is also mentioned in the @implNote part of56* {@link DrbgParameters} class.57*/58public final class DRBG extends SecureRandomSpi {5960private static final String PROP_NAME = "securerandom.drbg.config";6162@java.io.Serial63private static final long serialVersionUID = 9L;6465private transient AbstractDrbg impl;6667/**68* @serial69*/70private final MoreDrbgParameters mdp;7172public DRBG(SecureRandomParameters params) {7374// All parameters at unset status (null or -1).7576// Configurable with the "securerandom.drbg.config" security property77String mech = null;78Boolean usedf = null;79String algorithm = null;8081// Default instantiate parameters also configurable with82// "securerandom.drbg.config", and can be changed with params83// in getInstance("drbg", params)84int strength = -1;85DrbgParameters.Capability cap = null;86byte[] ps = null;8788// Not configurable with public interfaces, but is a part of89// MoreDrbgParameters90EntropySource es = null;91byte[] nonce = null;9293// Can be configured with a security property9495@SuppressWarnings("removal")96String config = AccessController.doPrivileged((PrivilegedAction<String>)97() -> Security.getProperty(PROP_NAME));9899if (config != null && !config.isEmpty()) {100for (String part : config.split(",")) {101part = part.trim();102switch (part.toLowerCase(Locale.ROOT)) {103case "":104throw new IllegalArgumentException(105"aspect in " + PROP_NAME + " cannot be empty");106case "pr_and_reseed":107checkTwice(cap != null, "capability");108cap = PR_AND_RESEED;109break;110case "reseed_only":111checkTwice(cap != null, "capability");112cap = RESEED_ONLY;113break;114case "none":115checkTwice(cap != null, "capability");116cap = NONE;117break;118case "hash_drbg":119case "hmac_drbg":120case "ctr_drbg":121checkTwice(mech != null, "mechanism name");122mech = part;123break;124case "no_df":125checkTwice(usedf != null, "usedf flag");126usedf = false;127break;128case "use_df":129checkTwice(usedf != null, "usedf flag");130usedf = true;131break;132default:133// For all other parts of the property, it is134// either an algorithm name or a strength135try {136int tmp = Integer.parseInt(part);137if (tmp < 0) {138throw new IllegalArgumentException(139"strength in " + PROP_NAME +140" cannot be negative: " + part);141}142checkTwice(strength >= 0, "strength");143strength = tmp;144} catch (NumberFormatException e) {145checkTwice(algorithm != null, "algorithm name");146algorithm = part;147}148}149}150}151152// Can be updated by params153154if (params != null) {155// MoreDrbgParameters is used for testing.156if (params instanceof MoreDrbgParameters) {157MoreDrbgParameters m = (MoreDrbgParameters) params;158params = DrbgParameters.instantiation(m.strength,159m.capability, m.personalizationString);160161// No need to check null for es and nonce, they are still null162es = m.es;163nonce = m.nonce;164165if (m.mech != null) {166mech = m.mech;167}168if (m.algorithm != null) {169algorithm = m.algorithm;170}171usedf = m.usedf;172}173if (params instanceof DrbgParameters.Instantiation) {174DrbgParameters.Instantiation dp =175(DrbgParameters.Instantiation) params;176177// ps is still null by now178ps = dp.getPersonalizationString();179180int tmp = dp.getStrength();181if (tmp != -1) {182strength = tmp;183}184cap = dp.getCapability();185} else {186throw new IllegalArgumentException("Unsupported params: "187+ params.getClass());188}189}190191// Hardcoded defaults.192// Remember to sync with "securerandom.drbg.config" in java.security.193194if (cap == null) {195cap = NONE;196}197if (mech == null) {198mech = "Hash_DRBG";199}200if (usedf == null) {201usedf = true;202}203204mdp = new MoreDrbgParameters(205es, mech, algorithm, nonce, usedf,206DrbgParameters.instantiation(strength, cap, ps));207208createImpl();209}210211private void createImpl() {212switch (mdp.mech.toLowerCase(Locale.ROOT)) {213case "hash_drbg":214impl = new HashDrbg(mdp);215break;216case "hmac_drbg":217impl = new HmacDrbg(mdp);218break;219case "ctr_drbg":220impl = new CtrDrbg(mdp);221break;222default:223throw new IllegalArgumentException("Unsupported mech: " + mdp.mech);224}225}226227@Override228protected void engineSetSeed(byte[] seed) {229impl.engineSetSeed(seed);230}231232@Override233protected void engineNextBytes(byte[] bytes) {234impl.engineNextBytes(bytes);235}236237@Override238protected byte[] engineGenerateSeed(int numBytes) {239return impl.engineGenerateSeed(numBytes);240}241242@Override243protected void engineNextBytes(244byte[] bytes, SecureRandomParameters params) {245impl.engineNextBytes(bytes, params);246}247248@Override249protected void engineReseed(SecureRandomParameters params) {250impl.engineReseed(params);251}252253@Override254protected SecureRandomParameters engineGetParameters() {255return impl.engineGetParameters();256}257258@Override259public String toString() {260return impl.toString();261}262263/**264* Ensures an aspect is not set more than once.265*266* @param flag true if set more than once267* @param name the name of aspect shown in IAE268* @throws IllegalArgumentException if it happens269*/270private static void checkTwice(boolean flag, String name) {271if (flag) {272throw new IllegalArgumentException(name273+ " cannot be provided more than once in " + PROP_NAME);274}275}276277@java.io.Serial278private void readObject(java.io.ObjectInputStream s)279throws IOException, ClassNotFoundException {280s.defaultReadObject();281if (mdp.mech == null) {282throw new IllegalArgumentException("Input data is corrupted");283}284createImpl();285}286}287288289