mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-03 23:18:28 +00:00
178 lines
8.3 KiB
Java
178 lines
8.3 KiB
Java
/*
|
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package sun.security.provider;
|
|
|
|
import sun.security.pkcs.NamedPKCS8Key;
|
|
import sun.security.x509.NamedX509Key;
|
|
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
import java.security.InvalidParameterException;
|
|
import java.security.KeyPair;
|
|
import java.security.KeyPairGeneratorSpi;
|
|
import java.security.ProviderException;
|
|
import java.security.SecureRandom;
|
|
import java.security.spec.AlgorithmParameterSpec;
|
|
import java.security.spec.NamedParameterSpec;
|
|
import java.util.Objects;
|
|
|
|
/// A base class for all `KeyPairGenerator` implementations that can be
|
|
/// configured with a named parameter set.
|
|
///
|
|
/// Together with [NamedKeyFactory], [NamedKEM], and [NamedSignature], these
|
|
/// classes form a compact framework designed to support any public key
|
|
/// algorithm standardized with named parameter sets. In this scenario,
|
|
/// the algorithm name is the "family name" and each standardized parameter
|
|
/// set has a "parameter set name". Implementations of these classes are able
|
|
/// to instantiate a `KeyPairGenerator`, `KeyFactory`, or `KEM` or `Signature`
|
|
/// object using either the family name or a parameter set name. All keys used
|
|
/// in this context will be of the type [NamedPKCS8Key] or [NamedX509Key],
|
|
/// with `getAlgorithm` returning the family name, and `getParams` returning
|
|
/// the parameter set name as a [NamedParameterSpec] object.
|
|
///
|
|
/// An implementation must include a zero-argument public constructor that
|
|
/// calls `super(fname, pnames)`, where `fname` is the family name of the
|
|
/// algorithm and `pnames` are its supported parameter set names. `pnames`
|
|
/// must contain at least one element. For an implementation of
|
|
/// `NamedKeyPairGenerator`, the first element becomes its default parameter
|
|
/// set, i.e. the parameter set to be used in key pair generation unless
|
|
/// [#initialize(AlgorithmParameterSpec, java.security.SecureRandom)]
|
|
/// is called on a different parameter set.
|
|
///
|
|
/// An implementation must implement all abstract methods. For all these
|
|
/// methods, the implementation must relinquish any "ownership" of any input
|
|
/// and output array argument. Precisely, the implementation must not retain
|
|
/// any reference to a returning array so that it won't be able to modify its
|
|
/// content later. Similarly, the implementation must not modify any input
|
|
/// array argument and must not retain any reference to an input array argument
|
|
/// after the call.
|
|
///
|
|
/// Also, an implementation must not keep any extra copy of a private key.
|
|
/// For key generation, the only copy is the one returned in the
|
|
/// [#implGenerateKeyPair] call. For all other methods, it must not make
|
|
/// a copy of the input private key. A `KEM` implementation also must not
|
|
/// keep a copy of the shared secret key, no matter if it's an encapsulator
|
|
/// or a decapsulator. Only the code that owns these sensitive data can
|
|
/// choose to perform cleanup when it determines they are no longer needed.
|
|
///
|
|
/// The `NamedSignature` and `NamedKEM` classes provide `implCheckPublicKey`
|
|
/// and `implCheckPrivateKey` methods that allow an implementation to validate
|
|
/// a key before using it. An implementation may return a parsed key in
|
|
/// a local type, and this parsed key will be passed to an operational method
|
|
/// (For example, `implSign`) later. An implementation must not retain
|
|
/// a reference of the parsed key.
|
|
///
|
|
/// When constructing a [NamedX509Key] or [NamedPKCS8Key] object from raw key
|
|
/// bytes, the key bytes are directly referenced within the object, so the
|
|
/// caller must not modify them afterward. Similarly, the key's `getRawBytes`
|
|
/// method returns direct references to the underlying raw key bytes, meaning
|
|
/// the caller must not alter the contents of the returned value.
|
|
///
|
|
/// Together, these measures ensure the classes are as efficient as possible,
|
|
/// preventing unnecessary array cloning and potential data leaks. While these
|
|
/// classes should not be considered immutable, strictly adhering to the rules
|
|
/// above will ensure data integrity is maintained.
|
|
///
|
|
/// Note: A limitation of `NamedKeyPairGenerator` and `NamedKeyFactory` is
|
|
/// that the keys generated by their implementations will always be of type
|
|
/// `NamedX509Key` or `NamedPKCS8Key`. Existing implementations of algorithms
|
|
/// like EdDSA and XDH have been generating keys implementing `EdECKey` or
|
|
/// `XECKey` interfaces, and they are not rewritten with this framework.
|
|
/// `NamedParameterSpec` fields not implemented with this framework include
|
|
/// Ed25519, Ed448, X25519, and X448.
|
|
public abstract class NamedKeyPairGenerator extends KeyPairGeneratorSpi {
|
|
|
|
private final String fname; // family name
|
|
private final String[] pnames; // allowed parameter set name (at least one)
|
|
|
|
protected String name; // init as
|
|
private SecureRandom secureRandom;
|
|
|
|
/// Creates a new `NamedKeyPairGenerator` object.
|
|
///
|
|
/// @param fname the family name
|
|
/// @param pnames supported parameter set names, at least one is needed.
|
|
/// If multiple, the first one becomes the default parameter set name.
|
|
protected NamedKeyPairGenerator(String fname, String... pnames) {
|
|
if (fname == null) {
|
|
throw new AssertionError("fname cannot be null");
|
|
}
|
|
if (pnames == null || pnames.length == 0) {
|
|
throw new AssertionError("pnames cannot be null or empty");
|
|
}
|
|
this.fname = fname;
|
|
this.pnames = pnames;
|
|
}
|
|
|
|
private String checkName(String name) throws InvalidAlgorithmParameterException {
|
|
for (var pname : pnames) {
|
|
if (pname.equalsIgnoreCase(name)) {
|
|
// return the stored standard name
|
|
return pname;
|
|
}
|
|
}
|
|
throw new InvalidAlgorithmParameterException(
|
|
"Unsupported parameter set name: " + name);
|
|
}
|
|
|
|
@Override
|
|
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
|
throws InvalidAlgorithmParameterException {
|
|
if (params instanceof NamedParameterSpec spec) {
|
|
name = checkName(spec.getName());
|
|
} else {
|
|
throw new InvalidAlgorithmParameterException(
|
|
"Unsupported AlgorithmParameterSpec: " + params);
|
|
}
|
|
this.secureRandom = random;
|
|
}
|
|
|
|
@Override
|
|
public void initialize(int keysize, SecureRandom random) {
|
|
if (keysize != -1) {
|
|
// User can call initialize(-1, sr) to provide a SecureRandom
|
|
// without touching the parameter set currently used
|
|
throw new InvalidParameterException("keysize not supported");
|
|
}
|
|
this.secureRandom = random;
|
|
}
|
|
|
|
@Override
|
|
public KeyPair generateKeyPair() {
|
|
String pname = name != null ? name : pnames[0];
|
|
var keys = implGenerateKeyPair(pname, secureRandom);
|
|
return new KeyPair(new NamedX509Key(fname, pname, keys[0]),
|
|
new NamedPKCS8Key(fname, pname, keys[1]));
|
|
}
|
|
|
|
/// User-defined key pair generator.
|
|
///
|
|
/// @param pname parameter set name
|
|
/// @param sr `SecureRandom` object, `null` if not initialized
|
|
/// @return public key and private key (in this order) in raw bytes
|
|
/// @throws ProviderException if there is an internal error
|
|
protected abstract byte[][] implGenerateKeyPair(String pname, SecureRandom sr);
|
|
}
|