230 lines
8.7 KiB
Java
230 lines
8.7 KiB
Java
/* WolfSSLKeyManager.java
|
|
*
|
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
|
|
package com.wolfssl.provider.jsse;
|
|
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
import java.security.KeyStore;
|
|
import java.security.KeyStoreException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.UnrecoverableKeyException;
|
|
import javax.net.ssl.KeyManager;
|
|
import javax.net.ssl.KeyManagerFactorySpi;
|
|
import javax.net.ssl.ManagerFactoryParameters;
|
|
import com.wolfssl.WolfSSLDebug;
|
|
|
|
/**
|
|
* WolfSSL KeyManagerFactory implementation
|
|
*/
|
|
public class WolfSSLKeyManager extends KeyManagerFactorySpi {
|
|
private char[] pswd = null;
|
|
private KeyStore store = null;
|
|
private boolean initialized = false;
|
|
|
|
/** Default WolfSSLKeyManager constructor */
|
|
public WolfSSLKeyManager() { }
|
|
|
|
/**
|
|
* Try to load KeyStore from System properties if set.
|
|
*
|
|
* If a KeyStore file has been specified in the javax.net.ssl.keyStore
|
|
* System property, then we try to load it in the following ways:
|
|
*
|
|
* 1. Using type specified in javax.net.ssl.keyStoreType. If not given:
|
|
* 2. Using wolfJCE WKS type, if available
|
|
* 3. Using BKS type if on Android
|
|
* 4. Using JKS type if above all fail
|
|
*
|
|
* @param requiredType KeyStore type required by user through
|
|
* java.security if wolfjsse.keystore.type.required property
|
|
* has been set.
|
|
*
|
|
* @return new KeyStore object that has been created and loaded using
|
|
* details specified in System properties.
|
|
*
|
|
* @throws KeyStoreException if javax.net.ssl.keyStore property is
|
|
* set but KeyStore fails to load
|
|
*/
|
|
private KeyStore LoadKeyStoreFromSystemProperties(String requiredType)
|
|
throws KeyStoreException {
|
|
|
|
KeyStore sysStore = null;
|
|
String pass = System.getProperty("javax.net.ssl.keyStorePassword");
|
|
String file = System.getProperty("javax.net.ssl.keyStore");
|
|
String type = System.getProperty("javax.net.ssl.keyStoreType");
|
|
final boolean wksAvailable;
|
|
|
|
if (file != null) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "Loading certs from: " + file);
|
|
|
|
/* Check if wolfJCE WKS KeyStore is registered and available */
|
|
wksAvailable = WolfSSLUtil.WKSAvailable();
|
|
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "wolfJCE WKS KeyStore type available: " + wksAvailable);
|
|
|
|
/* Set KeyStore password if javax.net.ssl.keyStorePassword set */
|
|
if (pass != null) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "javax.net.ssl.keyStorePassword system property " +
|
|
"set, using password");
|
|
this.pswd = pass.toCharArray();
|
|
} else {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "javax.net.ssl.keyStorePassword system property " +
|
|
"not set");
|
|
}
|
|
|
|
/* Keystore type given in property, try loading using it */
|
|
if (type != null && !type.trim().isEmpty()) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "javax.net.ssl.keyStoreType set: " + type);
|
|
|
|
if (requiredType != null && !requiredType.equals(type)) {
|
|
throw new KeyStoreException(
|
|
"javax.net.ssl.keyStoreType conflicts with required " +
|
|
"KeyStore type from wolfjsse.keystore.type.required");
|
|
}
|
|
|
|
sysStore = WolfSSLUtil.LoadKeyStoreFileByType(
|
|
file, this.pswd, type);
|
|
}
|
|
else {
|
|
/* Try with wolfJCE WKS type first, in case wolfCrypt
|
|
* FIPS is being used */
|
|
if (wksAvailable &&
|
|
(requiredType == null || requiredType.equals("WKS"))) {
|
|
sysStore = WolfSSLUtil.LoadKeyStoreFileByType(
|
|
file, this.pswd, "WKS");
|
|
}
|
|
|
|
/* Try with BKS, if we're running on Android */
|
|
if ((sysStore == null) && WolfSSLUtil.isAndroid() &&
|
|
(requiredType == null || requiredType.equals("BKS"))) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "Detected Android VM, trying BKS KeyStore type");
|
|
sysStore = WolfSSLUtil.LoadKeyStoreFileByType(
|
|
file, this.pswd, "BKS");
|
|
}
|
|
|
|
/* Try falling back to JKS */
|
|
if (sysStore == null &&
|
|
(requiredType == null || requiredType.equals("JKS"))) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "javax.net.ssl.keyStoreType system property " +
|
|
"not set, trying type: JKS");
|
|
sysStore = WolfSSLUtil.LoadKeyStoreFileByType(
|
|
file, this.pswd, "JKS");
|
|
}
|
|
}
|
|
|
|
if (sysStore == null) {
|
|
throw new KeyStoreException(
|
|
"Failed to load KeyStore from System properties, " +
|
|
"please double check settings");
|
|
}
|
|
else {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "Loaded certs from KeyStore via System properties");
|
|
}
|
|
}
|
|
|
|
return sysStore;
|
|
}
|
|
|
|
@Override
|
|
protected void engineInit(KeyStore store, char[] password)
|
|
throws KeyStoreException, NoSuchAlgorithmException,
|
|
UnrecoverableKeyException {
|
|
|
|
this.pswd = password;
|
|
KeyStore certs = store;
|
|
final String requiredType;
|
|
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "entering engineInit(KeyStore store, char[] password)");
|
|
|
|
requiredType = WolfSSLUtil.getRequiredKeyStoreType();
|
|
if (requiredType != null) {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "java.security has restricted KeyStore type");
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "wolfjsse.keystore.type.required = " + requiredType);
|
|
}
|
|
|
|
/* If no KeyStore passed in, try to load from system property values
|
|
* if they have been set */
|
|
if (store == null) {
|
|
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "input KeyStore null, trying to load KeyStore from " +
|
|
"system properties");
|
|
|
|
certs = LoadKeyStoreFromSystemProperties(requiredType);
|
|
}
|
|
else {
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "input KeyStore provided, using inside KeyManager");
|
|
}
|
|
|
|
/* Verify KeyStore we got matches our requirements, for example
|
|
* type may be restricted by users trying to conform to FIPS
|
|
* requirements */
|
|
if (certs != null) {
|
|
WolfSSLUtil.checkKeyStoreRequirements(certs);
|
|
}
|
|
|
|
this.store = certs;
|
|
this.initialized = true;
|
|
}
|
|
|
|
@Override
|
|
protected void engineInit(ManagerFactoryParameters arg0)
|
|
throws InvalidAlgorithmParameterException {
|
|
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "entering engineInit(ManagerFactoryParameters arg0)");
|
|
|
|
throw new UnsupportedOperationException(
|
|
"KeyManagerFactory.init(ManagerFactoryParameters) not " +
|
|
"supported yet");
|
|
}
|
|
|
|
@Override
|
|
protected KeyManager[] engineGetKeyManagers()
|
|
throws IllegalStateException {
|
|
|
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
|
() -> "entered engineGetKeyManagers()");
|
|
|
|
if (!this.initialized) {
|
|
throw new IllegalStateException("KeyManagerFactory must be " +
|
|
"initialized before use, please call init()");
|
|
}
|
|
|
|
KeyManager[] km = {new WolfSSLKeyX509(this.store, this.pswd)};
|
|
return km;
|
|
}
|
|
}
|
|
|