wolfssljni/src/java/com/wolfssl/provider/jsse/WolfSSLKeyManager.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;
}
}