|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.provider; |
|
|
|
import java.io.IOException; |
|
import java.security.AccessController; |
|
import java.security.DrbgParameters; |
|
import java.security.PrivilegedAction; |
|
import java.security.SecureRandomParameters; |
|
import java.security.SecureRandomSpi; |
|
import java.security.Security; |
|
import java.util.Locale; |
|
import static java.security.DrbgParameters.Capability.*; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class DRBG extends SecureRandomSpi { |
|
|
|
private static final String PROP_NAME = "securerandom.drbg.config"; |
|
|
|
private static final long serialVersionUID = 9L; |
|
|
|
private transient AbstractDrbg impl; |
|
|
|
|
|
|
|
*/ |
|
private final MoreDrbgParameters mdp; |
|
|
|
public DRBG(SecureRandomParameters params) { |
|
|
|
// All parameters at unset status (null or -1). |
|
|
|
|
|
String mech = null; |
|
Boolean usedf = null; |
|
String algorithm = null; |
|
|
|
// Default instantiate parameters also configurable with |
|
// "securerandom.drbg.config", and can be changed with params |
|
|
|
int strength = -1; |
|
DrbgParameters.Capability cap = null; |
|
byte[] ps = null; |
|
|
|
// Not configurable with public interfaces, but is a part of |
|
|
|
EntropySource es = null; |
|
byte[] nonce = null; |
|
|
|
// Can be configured with a security property |
|
|
|
String config = AccessController.doPrivileged((PrivilegedAction<String>) |
|
() -> Security.getProperty(PROP_NAME)); |
|
|
|
if (config != null && !config.isEmpty()) { |
|
for (String part : config.split(",")) { |
|
part = part.trim(); |
|
switch (part.toLowerCase(Locale.ROOT)) { |
|
case "": |
|
throw new IllegalArgumentException( |
|
"aspect in " + PROP_NAME + " cannot be empty"); |
|
case "pr_and_reseed": |
|
checkTwice(cap != null, "capability"); |
|
cap = PR_AND_RESEED; |
|
break; |
|
case "reseed_only": |
|
checkTwice(cap != null, "capability"); |
|
cap = RESEED_ONLY; |
|
break; |
|
case "none": |
|
checkTwice(cap != null, "capability"); |
|
cap = NONE; |
|
break; |
|
case "hash_drbg": |
|
case "hmac_drbg": |
|
case "ctr_drbg": |
|
checkTwice(mech != null, "mechanism name"); |
|
mech = part; |
|
break; |
|
case "no_df": |
|
checkTwice(usedf != null, "usedf flag"); |
|
usedf = false; |
|
break; |
|
case "use_df": |
|
checkTwice(usedf != null, "usedf flag"); |
|
usedf = true; |
|
break; |
|
default: |
|
// For all other parts of the property, it is |
|
|
|
try { |
|
int tmp = Integer.parseInt(part); |
|
if (tmp < 0) { |
|
throw new IllegalArgumentException( |
|
"strength in " + PROP_NAME + |
|
" cannot be negative: " + part); |
|
} |
|
checkTwice(strength >= 0, "strength"); |
|
strength = tmp; |
|
} catch (NumberFormatException e) { |
|
checkTwice(algorithm != null, "algorithm name"); |
|
algorithm = part; |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Can be updated by params |
|
|
|
if (params != null) { |
|
|
|
if (params instanceof MoreDrbgParameters) { |
|
MoreDrbgParameters m = (MoreDrbgParameters) params; |
|
params = DrbgParameters.instantiation(m.strength, |
|
m.capability, m.personalizationString); |
|
|
|
|
|
es = m.es; |
|
nonce = m.nonce; |
|
|
|
if (m.mech != null) { |
|
mech = m.mech; |
|
} |
|
if (m.algorithm != null) { |
|
algorithm = m.algorithm; |
|
} |
|
usedf = m.usedf; |
|
} |
|
if (params instanceof DrbgParameters.Instantiation) { |
|
DrbgParameters.Instantiation dp = |
|
(DrbgParameters.Instantiation) params; |
|
|
|
|
|
ps = dp.getPersonalizationString(); |
|
|
|
int tmp = dp.getStrength(); |
|
if (tmp != -1) { |
|
strength = tmp; |
|
} |
|
cap = dp.getCapability(); |
|
} else { |
|
throw new IllegalArgumentException("Unsupported params: " |
|
+ params.getClass()); |
|
} |
|
} |
|
|
|
// Hardcoded defaults. |
|
// Remember to sync with "securerandom.drbg.config" in java.security. |
|
|
|
if (cap == null) { |
|
cap = NONE; |
|
} |
|
if (mech == null) { |
|
mech = "Hash_DRBG"; |
|
} |
|
if (usedf == null) { |
|
usedf = true; |
|
} |
|
|
|
mdp = new MoreDrbgParameters( |
|
es, mech, algorithm, nonce, usedf, |
|
DrbgParameters.instantiation(strength, cap, ps)); |
|
|
|
createImpl(); |
|
} |
|
|
|
private void createImpl() { |
|
switch (mdp.mech.toLowerCase(Locale.ROOT)) { |
|
case "hash_drbg": |
|
impl = new HashDrbg(mdp); |
|
break; |
|
case "hmac_drbg": |
|
impl = new HmacDrbg(mdp); |
|
break; |
|
case "ctr_drbg": |
|
impl = new CtrDrbg(mdp); |
|
break; |
|
default: |
|
throw new IllegalArgumentException("Unsupported mech: " + mdp.mech); |
|
} |
|
} |
|
|
|
@Override |
|
protected void engineSetSeed(byte[] seed) { |
|
impl.engineSetSeed(seed); |
|
} |
|
|
|
@Override |
|
protected void engineNextBytes(byte[] bytes) { |
|
impl.engineNextBytes(bytes); |
|
} |
|
|
|
@Override |
|
protected byte[] engineGenerateSeed(int numBytes) { |
|
return impl.engineGenerateSeed(numBytes); |
|
} |
|
|
|
@Override |
|
protected void engineNextBytes( |
|
byte[] bytes, SecureRandomParameters params) { |
|
impl.engineNextBytes(bytes, params); |
|
} |
|
|
|
@Override |
|
protected void engineReseed(SecureRandomParameters params) { |
|
impl.engineReseed(params); |
|
} |
|
|
|
@Override |
|
protected SecureRandomParameters engineGetParameters() { |
|
return impl.engineGetParameters(); |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return impl.toString(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static void checkTwice(boolean flag, String name) { |
|
if (flag) { |
|
throw new IllegalArgumentException(name |
|
+ " cannot be provided more than once in " + PROP_NAME); |
|
} |
|
} |
|
|
|
private void readObject(java.io.ObjectInputStream s) |
|
throws IOException, ClassNotFoundException { |
|
s.defaultReadObject(); |
|
if (mdp.mech == null) { |
|
throw new IllegalArgumentException("Input data is corrupted"); |
|
} |
|
createImpl(); |
|
} |
|
} |