http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/AbstractSecurityProviderRegistrar.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/AbstractSecurityProviderRegistrar.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/AbstractSecurityProviderRegistrar.java deleted file mode 100644 index b665166..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/AbstractSecurityProviderRegistrar.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.util.security; - -import java.security.Provider; -import java.security.Security; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.logging.AbstractLoggingBean; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractSecurityProviderRegistrar - extends AbstractLoggingBean - implements SecurityProviderRegistrar { - protected final Map<String, Object> props = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - protected final Map<Class<?>, Map<String, Boolean>> supportedEntities = new HashMap<>(); - protected final AtomicReference<Provider> providerHolder = new AtomicReference<>(null); - - private final String name; - - protected AbstractSecurityProviderRegistrar(String name) { - this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No name provided"); - } - - @Override - public final String getName() { - return name; - } - - @Override - public Map<String, Object> getProperties() { - return props; - } - - @Override - public boolean isSecurityEntitySupported(Class<?> entityType, String name) { - Map<String, Boolean> supportMap; - synchronized (supportedEntities) { - supportMap = supportedEntities.computeIfAbsent( - entityType, k -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); - } - - Boolean supportFlag; - synchronized (supportMap) { - supportFlag = supportMap.computeIfAbsent( - name, k -> SecurityProviderRegistrar.super.isSecurityEntitySupported(entityType, name)); - } - - return supportFlag; - } - - /** - * Attempts to see if a provider with this name already registered. If not, - * then uses reflection API in order to load and instantiate the specified - * <tt>providerClassName</tt> - * - * @param providerClassName The fully-qualified class name to instantiate - * if a provider not already registered - * @return The resolved {@link Provider} instance - <B>Note:</B> the result - * is <U>cached</U> - i.e., successful resolution result will not cause - * the code to re-resolve the provider - * @throws ReflectiveOperationException If failed to instantiate the provider - * @throws UnsupportedOperationException If registrar not supported - * @see #isSupported() - * @see Security#getProvider(String) - * @see #createProviderInstance(String) - */ - protected Provider getOrCreateProvider(String providerClassName) throws ReflectiveOperationException { - if (!isSupported()) { - throw new UnsupportedOperationException("Provider not supported"); - } - - Provider provider; - boolean created = false; - synchronized (providerHolder) { - provider = providerHolder.get(); - if (provider != null) { - return provider; - } - - provider = Security.getProvider(getName()); - if (provider == null) { - provider = createProviderInstance(providerClassName); - created = true; - } - providerHolder.set(provider); - } - - if (created) { - log.info("getOrCreateProvider({}) created instance of {}", getName(), providerClassName); - } else { - log.info("getOrCreateProvider({}) resolved instance of {}", getName(), provider.getClass().getName()); - } - - return provider; - } - - protected Provider createProviderInstance(String providerClassName) throws ReflectiveOperationException { - return SecurityProviderChoice.createProviderInstance(getClass(), providerClassName); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + getName() + "]"; - } -}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java deleted file mode 100644 index 94b9454..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.util.security; - -import java.lang.reflect.Method; -import java.security.GeneralSecurityException; -import java.security.Provider; -import java.util.Objects; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * @param <T> Type of security entity being generated by this factory - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface SecurityEntityFactory<T> { - Class<T> getEntityType(); - - T getInstance(String algorithm) throws GeneralSecurityException; - - /** - * Uses reflection in order to wrap the {@code getInstance} method(s) - * as a security entity factory. - * - * @param <F> Type of entity being generated by the factor - * @param entityType The entity type class - * @param registrar The {@code SecurityProviderRegistrar} to use - if - * {@code null} then default provider is used (if specified). - * @param defaultProvider Default provider choice to use if no registrar - * provided. If {@code null}/empty then JCE default is used - * @return The {@link SecurityEntityFactory} for the entity - * @throws ReflectiveOperationException If failed to create the factory - * @see #toDefaultFactory(Class) - * @see #toNamedProviderFactory(Class, String) - * @see #toProviderInstanceFactory(Class, Provider) - * @see SecurityProviderChoice#isNamedProviderUsed() - * @see SecurityProviderChoice#getSecurityProvider() - */ - static <F> SecurityEntityFactory<F> toFactory( - Class<F> entityType, SecurityProviderChoice registrar, SecurityProviderChoice defaultProvider) - throws ReflectiveOperationException { - if (registrar == null) { - if ((defaultProvider == null) || (defaultProvider == SecurityProviderChoice.EMPTY)) { - return toDefaultFactory(entityType); - } else if (defaultProvider.isNamedProviderUsed()) { - return toNamedProviderFactory(entityType, defaultProvider.getName()); - } else { - return toProviderInstanceFactory(entityType, defaultProvider.getSecurityProvider()); - } - } else if (registrar.isNamedProviderUsed()) { - return toNamedProviderFactory(entityType, registrar.getName()); - } else { - return toProviderInstanceFactory(entityType, registrar.getSecurityProvider()); - } - } - - static <F> SecurityEntityFactory<F> toDefaultFactory(Class<F> entityType) - throws ReflectiveOperationException { - Method m = entityType.getDeclaredMethod("getInstance", String.class); - return new SecurityEntityFactory<F>() { - private final String s = SecurityEntityFactory.class.getSimpleName() - + "[" + entityType.getSimpleName() + "]" - + "[default]"; - - @Override - public Class<F> getEntityType() { - return entityType; - } - - @Override - public F getInstance(String algorithm) throws GeneralSecurityException { - try { - Object value = m.invoke(null, algorithm); - return entityType.cast(value); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - if (e instanceof GeneralSecurityException) { - throw (GeneralSecurityException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new GeneralSecurityException(e); - } - } - } - - @Override - public String toString() { - return s; - } - }; - } - - static <F> SecurityEntityFactory<F> toNamedProviderFactory(Class<F> entityType, String name) - throws ReflectiveOperationException { - ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified"); - Method m = entityType.getDeclaredMethod("getInstance", String.class, String.class); - return new SecurityEntityFactory<F>() { - private final String s = SecurityEntityFactory.class.getSimpleName() - + "[" + entityType.getSimpleName() + "]" - + "[" + name + "]"; - - @Override - public Class<F> getEntityType() { - return entityType; - } - - @Override - public F getInstance(String algorithm) throws GeneralSecurityException { - try { - Object value = m.invoke(null, algorithm, name); - return entityType.cast(value); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - if (e instanceof GeneralSecurityException) { - throw (GeneralSecurityException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new GeneralSecurityException(e); - } - } - } - - @Override - public String toString() { - return s; - } - }; - } - - static <F> SecurityEntityFactory<F> toProviderInstanceFactory(Class<F> entityType, Provider provider) - throws ReflectiveOperationException { - Objects.requireNonNull(provider, "No provider instance"); - Method m = entityType.getDeclaredMethod("getInstance", String.class, Provider.class); - return new SecurityEntityFactory<F>() { - private final String s = SecurityEntityFactory.class.getSimpleName() - + "[" + entityType.getSimpleName() + "]" - + "[" + Provider.class.getSimpleName() + "]" - + "[" + provider.getName() + "]"; - - @Override - public Class<F> getEntityType() { - return entityType; - } - - @Override - public F getInstance(String algorithm) throws GeneralSecurityException { - try { - Object value = m.invoke(null, algorithm, provider); - return entityType.cast(value); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - if (e instanceof GeneralSecurityException) { - throw (GeneralSecurityException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new GeneralSecurityException(e); - } - } - } - - @Override - public String toString() { - return s; - } - }; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java deleted file mode 100644 index c12e747..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.util.security; - -import java.security.Provider; -import java.util.Objects; - -import org.apache.sshd.common.NamedResource; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.threads.ThreadUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface SecurityProviderChoice extends NamedResource { - SecurityProviderChoice EMPTY = new SecurityProviderChoice() { - @Override - public String getName() { - return null; - } - - @Override - public boolean isNamedProviderUsed() { - return false; - } - - @Override - public Provider getSecurityProvider() { - return null; - } - - @Override - public String toString() { - return "EMPTY"; - } - }; - - /** - * @return {@code true} if to use the provider's name rather than its - * {@link Provider} instance - default={@code true}. - */ - default boolean isNamedProviderUsed() { - return true; - } - - /** - * @return The security {@link Provider} to use in case {@link #isNamedProviderUsed()} - * is {@code false}. Can be {@code null} if {@link #isNamedProviderUsed()} is {@code true}, - * but not recommended. - */ - Provider getSecurityProvider(); - - static SecurityProviderChoice toSecurityProviderChoice(String name) { - ValidateUtils.checkNotNullAndNotEmpty(name, "No name provided"); - return new SecurityProviderChoice() { - private final String s = SecurityProviderChoice.class.getSimpleName() + "[" + name + "]"; - - @Override - public String getName() { - return name; - } - - @Override - public boolean isNamedProviderUsed() { - return true; - } - - @Override - public Provider getSecurityProvider() { - return null; - } - - @Override - public String toString() { - return s; - } - }; - } - - static SecurityProviderChoice toSecurityProviderChoice(Provider provider) { - Objects.requireNonNull(provider, "No provider instance"); - return new SecurityProviderChoice() { - private final String s = SecurityProviderChoice.class.getSimpleName() - + "[" + Provider.class.getSimpleName() + "]" - + "[" + provider.getName() + "]"; - - @Override - public String getName() { - return provider.getName(); - } - - @Override - public boolean isNamedProviderUsed() { - return false; - } - - @Override - public Provider getSecurityProvider() { - return provider; - } - - @Override - public String toString() { - return s; - } - }; - } - - static Provider createProviderInstance(Class<?> anchor, String providerClassName) - throws ReflectiveOperationException { - return ThreadUtils.createDefaultInstance(anchor, Provider.class, providerClassName); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java deleted file mode 100644 index 31e428b..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.util.security; - -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.MessageDigest; -import java.security.Provider; -import java.security.Security; -import java.security.Signature; -import java.security.cert.CertificateFactory; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Predicate; - -import javax.crypto.Cipher; -import javax.crypto.KeyAgreement; -import javax.crypto.Mac; - -import org.apache.sshd.common.OptionalFeature; -import org.apache.sshd.common.PropertyResolver; -import org.apache.sshd.common.PropertyResolverUtils; -import org.apache.sshd.common.SyspropsMapWrapper; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.IgnoringEmptyMap; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface SecurityProviderRegistrar extends SecurityProviderChoice, OptionalFeature, PropertyResolver { - /** - * Base name for configuration properties related to security providers - */ - String CONFIG_PROP_BASE = "org.apache.sshd.security.provider"; - - /** - * Property used to configure whether the provider is enabled regardless of - * whether it is supported. - * - * @see #isEnabled() - */ - String ENABLED_PROPERTY = "enabled"; - - /** - * Property used to configure whether to use the provider's name rather than its - * {@link Provider} instance - * - * @see #isNamedProviderUsed() - */ - String NAMED_PROVIDER_PROPERTY = "useNamed"; - - String ALL_OPTIONS_VALUE = "all"; - String ALL_OPTIONS_WILDCARD = "*"; - - String NO_OPTIONS_VALUE = "none"; - - /** - * All the entities that are used in calls to {@link #isSecurityEntitySupported(Class, String)} - */ - List<Class<?>> SECURITY_ENTITIES = - Collections.unmodifiableList( - Arrays.asList( - Cipher.class, KeyFactory.class, MessageDigest.class, - KeyPairGenerator.class, KeyAgreement.class, Mac.class, - Signature.class, CertificateFactory.class)); - - default String getBasePropertyName() { - return CONFIG_PROP_BASE + "." + getName(); - } - - default String getConfigurationPropertyName(String name) { - return getBasePropertyName() + "." + name; - } - - /** - * @return {@code true} if the provider is enabled regardless of - * whether it is supported - default={@code true}. <B>Note:</B> - * checks if the provider has been <U>programmatically</U> disabled - * via {@link SecurityUtils#setAPrioriDisabledProvider(String, boolean)} - * @see #ENABLED_PROPERTY - */ - default boolean isEnabled() { - if (SecurityUtils.isAPrioriDisabledProvider(getName())) { - return false; - } - - return this.getBooleanProperty(getConfigurationPropertyName(ENABLED_PROPERTY), true); - } - - @Override - default PropertyResolver getParentPropertyResolver() { - return SyspropsMapWrapper.SYSPROPS_RESOLVER; - } - - @Override - default Map<String, Object> getProperties() { - return IgnoringEmptyMap.getInstance(); - } - - /** - * @param transformation The requested {@link Cipher} transformation - * @return {@code true} if this security provider supports the transformation - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isCipherSupported(String transformation) { - return isSecurityEntitySupported(Cipher.class, transformation); - } - - /** - * @param algorithm The {@link KeyFactory} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isKeyFactorySupported(String algorithm) { - return isSecurityEntitySupported(KeyFactory.class, algorithm); - } - - /** - * @param algorithm The {@link MessageDigest} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isMessageDigestSupported(String algorithm) { - return isSecurityEntitySupported(MessageDigest.class, algorithm); - } - - /** - * @param algorithm The {@link KeyPairGenerator} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isKeyPairGeneratorSupported(String algorithm) { - return isSecurityEntitySupported(KeyPairGenerator.class, algorithm); - } - - /** - * @param algorithm The {@link KeyAgreement} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isKeyAgreementSupported(String algorithm) { - return isSecurityEntitySupported(KeyAgreement.class, algorithm); - } - - /** - * @param algorithm The {@link Mac} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isMacSupported(String algorithm) { - return isSecurityEntitySupported(Mac.class, algorithm); - } - - /** - * @param algorithm The {@link Signature} algorithm - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isSignatureSupported(String algorithm) { - return isSecurityEntitySupported(Signature.class, algorithm); - } - - /** - * @param type The {@link CertificateFactory} type - * @return {@code true} if this security provider supports the algorithm - * @see #isSecurityEntitySupported(Class, String) - */ - default boolean isCertificateFactorySupported(String type) { - return isSecurityEntitySupported(CertificateFactory.class, type); - } - - /** - * @param entityType The requested entity type - its simple name serves to - * build the configuration property name. - * @return Configuration value to use if no specific configuration provided - * - default=empty - * @see #isSecurityEntitySupported(Class, String) - */ - default String getDefaultSecurityEntitySupportValue(Class<?> entityType) { - return ""; - } - - default boolean isSecurityEntitySupported(Class<?> entityType, String name) { - String defaultValue = getDefaultSecurityEntitySupportValue(entityType); - return isSecurityEntitySupported(this, entityType, name, defaultValue); - } - - /** - * @return {@code true} if to use the provider's name rather than its - * {@link Provider} instance - default={@code true} - * @see #NAMED_PROVIDER_PROPERTY - * @see #getSecurityProvider() - * @see #registerSecurityProvider(SecurityProviderRegistrar) - */ - @Override - default boolean isNamedProviderUsed() { - return PropertyResolverUtils.getBooleanProperty(this, - getConfigurationPropertyName(NAMED_PROVIDER_PROPERTY), - SecurityProviderChoice.super.isNamedProviderUsed()); - } - - /** - * @param v Value to be examined - * @return {@code true} if the value equals (case insensitive) to - * either {@link #ALL_OPTIONS_VALUE} or {@link #ALL_OPTIONS_WILDCARD} - */ - static boolean isAllOptionsValue(String v) { - return ALL_OPTIONS_VALUE.equalsIgnoreCase(v) - || ALL_OPTIONS_WILDCARD.equalsIgnoreCase(v); - } - - /** - * Checks whether the requested entity type algorithm/name is listed - * as supported by the registrar's configuration - * - * @param registrar The {@link SecurityProviderRegistrar} - * @param entityType The requested entity type - its simple name serves to - * build the configuration property name. - * @param name The requested algorithm/name - <B>Note:</B> if the requested - * entity is a {@link Cipher} then the argument is assumed to be a possible - * "/" separated transformation and parsed as such in order to - * retrieve the pure cipher name - * @param defaultValue Configuration value to use if no specific configuration provided - * @return {@code true} registrar is supported and the value is listed - * (case <U>insensitive</U>) or * the property is one of the "all" markers - * @see SecurityProviderRegistrar#isSupported() - * @see #isAllOptionsValue(String) - */ - static boolean isSecurityEntitySupported(SecurityProviderRegistrar registrar, Class<?> entityType, String name, String defaultValue) { - return Objects.requireNonNull(registrar, "No registrar instance").isSupported() - && isSecurityEntitySupported(registrar, registrar.getConfigurationPropertyName(entityType.getSimpleName()), entityType, name, defaultValue); - } - - static boolean isSecurityEntitySupported(PropertyResolver resolver, String propName, Class<?> entityType, String name, String defaultValue) { - if (GenericUtils.isEmpty(name)) { - return false; - } - - String propValue = resolver.getString(propName); - if (GenericUtils.isEmpty(propValue)) { - propValue = defaultValue; - } - - if (NO_OPTIONS_VALUE.equalsIgnoreCase(propValue)) { - return false; - } - - String[] values = GenericUtils.split(propValue, ','); - if (GenericUtils.isEmpty(values)) { - return false; - } - - if ((values.length == 1) && isAllOptionsValue(values[0])) { - return true; - } - - String effectiveName = getEffectiveSecurityEntityName(entityType, name); - int index = Arrays.binarySearch(values, effectiveName, String.CASE_INSENSITIVE_ORDER); - return index >= 0; - } - - /** - * Determines the "pure" security entity name - e.g., for {@link Cipher}s - * it strips the trailing transformation specification in order to extract the - * base cipher name - e.g., "AES/CBC/NoPadding" => "AES" - * - * @param entityType The security entity type - ignored if {@code null} - * @param name The effective name - ignored if {@code null}/empty - * @return The resolved name - */ - static String getEffectiveSecurityEntityName(Class<?> entityType, String name) { - if ((entityType == null) || GenericUtils.isEmpty(name) || (!Cipher.class.isAssignableFrom(entityType))) { - return name; - } - - int pos = name.indexOf('/'); - return (pos > 0) ? name.substring(0, pos) : name; - } - - /** - * Attempts to register the security provider represented by the registrar - * if not already registered. <B>Note:</B> if {@link SecurityProviderRegistrar#isNamedProviderUsed()} - * is {@code true} then the generated provider will be added to the system's - * list of known providers. - * - * @param registrar The {@link SecurityProviderRegistrar} - * @return {@code true} if no provider was previously registered - * @see Security#getProvider(String) - * @see SecurityProviderRegistrar#getSecurityProvider() - * @see Security#addProvider(Provider) - */ - static boolean registerSecurityProvider(SecurityProviderRegistrar registrar) { - String name = ValidateUtils.checkNotNullAndNotEmpty( - (registrar == null) ? null : registrar.getName(), "No name for registrar=%s", registrar); - Provider p = Security.getProvider(name); - if (p != null) { - return false; - } - - p = ValidateUtils.checkNotNull( - registrar.getSecurityProvider(), "No provider created for registrar of %s", name); - if (registrar.isNamedProviderUsed()) { - Security.addProvider(p); - } - - return true; - } - - static SecurityProviderRegistrar findSecurityProviderRegistrarBySecurityEntity( - Predicate<? super SecurityProviderRegistrar> entitySelector, - Collection<? extends SecurityProviderRegistrar> registrars) { - return GenericUtils.findFirstMatchingMember( - r -> r.isEnabled() && r.isSupported() && entitySelector.test(r), registrars); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java deleted file mode 100644 index ee755e6..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java +++ /dev/null @@ -1,759 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.util.security; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertificateFactory; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; - -import javax.crypto.Cipher; -import javax.crypto.KeyAgreement; -import javax.crypto.Mac; -import javax.crypto.spec.DHParameterSpec; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.config.keys.KeyUtils; -import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder; -import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; -import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser; -import org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKeyPairResourceParser; -import org.apache.sshd.common.config.keys.loader.pem.PEMResourceParserUtils; -import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.random.JceRandomFactory; -import org.apache.sshd.common.random.RandomFactory; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.buffer.Buffer; -import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleGeneratorHostKeyProvider; -import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleKeyPairResourceParser; -import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleRandomFactory; -import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils; -import org.apache.sshd.common.util.threads.ThreadUtils; -import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Specific security providers related code - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public final class SecurityUtils { - /** - * Bouncycastle JCE provider name - */ - public static final String BOUNCY_CASTLE = "BC"; - - /** - * EDDSA support - should match {@code EdDSAKey.KEY_ALGORITHM} - */ - public static final String EDDSA = "EdDSA"; - - // A copy-paste from the original, but we don't want to drag the classes into the classpath - // See EdDSAEngine.SIGNATURE_ALGORITHM - public static final String CURVE_ED25519_SHA512 = "NONEwithEdDSA"; - - /** - * System property used to configure the value for the maximum supported Diffie-Hellman - * Group Exchange key size. If not set, then an internal auto-discovery mechanism is employed. - * If set to negative value then Diffie-Hellman Group Exchange is disabled. If set to a - * negative value then Diffie-Hellman Group Exchange is disabled - */ - public static final String MAX_DHGEX_KEY_SIZE_PROP = "org.apache.sshd.maxDHGexKeySize"; - - /** - * The min. key size value used for testing whether Diffie-Hellman Group Exchange - * is supported or not. According to <A HREF="https://tools.ietf.org/html/rfc4419">RFC 4419</A> - * section 3: "Servers and clients SHOULD support groups with a modulus length of k - * bits, where 1024 <= k <= 8192". - * </code> - */ - public static final int MIN_DHGEX_KEY_SIZE = 1024; - // Keys of size > 1024 are not support by default with JCE - public static final int DEFAULT_DHGEX_KEY_SIZE = MIN_DHGEX_KEY_SIZE; - public static final int PREFERRED_DHGEX_KEY_SIZE = 4096; - public static final int MAX_DHGEX_KEY_SIZE = 8192; - - /** - * Comma separated list of fully qualified {@link SecurityProviderRegistrar}s - * to automatically register - */ - public static final String SECURITY_PROVIDER_REGISTRARS = "org.apache.sshd.security.registrars"; - public static final List<String> DEFAULT_SECURITY_PROVIDER_REGISTRARS = - Collections.unmodifiableList( - Arrays.asList( - "org.apache.sshd.common.util.security.bouncycastle.BouncyCastleSecurityProviderRegistrar", - "org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar")); - - - /** - * System property used to control whether to automatically register the - * {@code Bouncyastle} JCE provider - * @deprecated Please use "org.apache.sshd.security.provider.BC.enabled" - */ - @Deprecated - public static final String REGISTER_BOUNCY_CASTLE_PROP = "org.apache.sshd.registerBouncyCastle"; - - /** - * System property used to control whether Elliptic Curves are supported or not. - * If not set then the support is auto-detected. <B>Note:</B> if set to {@code true} - * it is up to the user to make sure that indeed there is a provider for them - */ - public static final String ECC_SUPPORTED_PROP = "org.apache.sshd.eccSupport"; - - /** - * System property used to decide whether EDDSA curves are supported or not - * (in addition or even in spite of {@link #isEDDSACurveSupported()}). If not - * set or set to {@code true}, then the existence of the optional support classes - * determines the support. - * @deprecated Please use "org.apache.sshd.security.provider.EdDSA.enabled&qupt; - */ - @Deprecated - public static final String EDDSA_SUPPORTED_PROP = "org.apache.sshd.eddsaSupport"; - - public static final String PROP_DEFAULT_SECURITY_PROVIDER = "org.apache.sshd.security.defaultProvider"; - - private static final AtomicInteger MAX_DHG_KEY_SIZE_HOLDER = new AtomicInteger(0); - - /* - * NOTE: we use a LinkedHashMap in order to preserve registration order - * in case several providers support the same security entity - */ - private static final Map<String, SecurityProviderRegistrar> REGISTERED_PROVIDERS = new LinkedHashMap<>(); - private static final AtomicReference<KeyPairResourceParser> KEYPAIRS_PARSER_HODLER = new AtomicReference<>(); - // If an entry already exists for the named provider, then it overrides its SecurityProviderRegistrar#isEnabled() - private static final Set<String> APRIORI_DISABLED_PROVIDERS = new TreeSet<>(); - private static final AtomicBoolean REGISTRATION_STATE_HOLDER = new AtomicBoolean(false); - private static final Map<Class<?>, Map<String, SecurityEntityFactory<?>>> SECURITY_ENTITY_FACTORIES = new HashMap<>(); - - private static final AtomicReference<SecurityProviderChoice> DEFAULT_PROVIDER_HOLDER = new AtomicReference<>(); - - private static Boolean hasEcc; - - private SecurityUtils() { - throw new UnsupportedOperationException("No instance"); - } - - /** - * @param name The provider's name - never {@code null}/empty - * @return {@code true} if the provider is marked as disabled a-priori - * @see #setAPrioriDisabledProvider(String, boolean) - */ - public static boolean isAPrioriDisabledProvider(String name) { - ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified"); - synchronized (APRIORI_DISABLED_PROVIDERS) { - return APRIORI_DISABLED_PROVIDERS.contains(name); - } - } - - /** - * Marks a provider's registrar as "a-priori" <U>programatically</U> - * so that when its {@link SecurityProviderRegistrar#isEnabled()} is eventually - * consulted it will return {@code false} regardless of the configured value for - * the specific provider registrar instance. <B>Note:</B> has no effect if the - * provider has already been registered. - * - * @param name The provider's name - never {@code null}/empty - * @param disabled {@code true} whether to disable it a-priori - * @see #isAPrioriDisabledProvider(String) - */ - public static void setAPrioriDisabledProvider(String name, boolean disabled) { - ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified"); - synchronized (APRIORI_DISABLED_PROVIDERS) { - if (disabled) { - APRIORI_DISABLED_PROVIDERS.add(name); - } else { - APRIORI_DISABLED_PROVIDERS.remove(name); - } - } - } - - /** - * @return A <U>copy</U> if the current a-priori disabled providers names - */ - public static Set<String> getAPrioriDisabledProviders() { - synchronized (APRIORI_DISABLED_PROVIDERS) { - return new TreeSet<>(APRIORI_DISABLED_PROVIDERS); - } - } - - /** - * @return {@code true} if Elliptic Curve Cryptography is supported - * @see #ECC_SUPPORTED_PROP - */ - public static boolean isECCSupported() { - if (hasEcc == null) { - String propValue = System.getProperty(ECC_SUPPORTED_PROP); - if (GenericUtils.isEmpty(propValue)) { - try { - getKeyPairGenerator(KeyUtils.EC_ALGORITHM); - hasEcc = Boolean.TRUE; - } catch (Throwable t) { - hasEcc = Boolean.FALSE; - } - } else { - Logger logger = LoggerFactory.getLogger(SecurityUtils.class); - logger.info("Override ECC support value: " + propValue); - hasEcc = Boolean.valueOf(propValue); - } - } - - return hasEcc; - } - - /** - * @return {@code true} if Diffie-Hellman Group Exchange is supported - * @see #getMaxDHGroupExchangeKeySize() - */ - public static boolean isDHGroupExchangeSupported() { - return getMaxDHGroupExchangeKeySize() > 0; - } - - /** - * @param keySize The expected key size - * @return {@code true} if Oakely Diffie-Hellman Group Exchange is supported - * for the specified key size - * @see #getMaxDHGroupExchangeKeySize() - */ - public static boolean isDHOakelyGroupSupported(int keySize) { - return getMaxDHGroupExchangeKeySize() >= keySize; - } - - /** - * @return The maximum supported Diffie-Hellman Group Exchange key size, - * or non-positive if not supported - */ - public static int getMaxDHGroupExchangeKeySize() { - int maxSupportedKeySize; - synchronized (MAX_DHG_KEY_SIZE_HOLDER) { - maxSupportedKeySize = MAX_DHG_KEY_SIZE_HOLDER.get(); - if (maxSupportedKeySize != 0) { // 1st time we are called ? - return maxSupportedKeySize; - } - - String propValue = System.getProperty(MAX_DHGEX_KEY_SIZE_PROP); - if (GenericUtils.isEmpty(propValue)) { - maxSupportedKeySize = -1; - // Go down from max. to min. to ensure we stop at 1st maximum value success - for (int testKeySize = MAX_DHGEX_KEY_SIZE; testKeySize >= MIN_DHGEX_KEY_SIZE; testKeySize -= 1024) { - if (isDHGroupExchangeSupported(testKeySize)) { - maxSupportedKeySize = testKeySize; - break; - } - } - } else { - Logger logger = LoggerFactory.getLogger(SecurityUtils.class); - logger.info("Override max. DH group exchange key size: " + propValue); - maxSupportedKeySize = Integer.parseInt(propValue); - // negative is OK - means user wants to disable DH group exchange - ValidateUtils.checkTrue(maxSupportedKeySize != 0, - "Configured " + MAX_DHGEX_KEY_SIZE_PROP + " value must be non-zero: %d", maxSupportedKeySize); - } - - MAX_DHG_KEY_SIZE_HOLDER.set(maxSupportedKeySize); - } - - return maxSupportedKeySize; - } - - /** - * Set programmatically the reported value for {@link #getMaxDHGroupExchangeKeySize()} - * @param keySize The reported key size - if zero, then it will be auto-detected, if - * negative then DH group exchange will be disabled - */ - public static void setMaxDHGroupExchangeKeySize(int keySize) { - synchronized (MAX_DHG_KEY_SIZE_HOLDER) { - MAX_DHG_KEY_SIZE_HOLDER.set(keySize); - } - } - - public static boolean isDHGroupExchangeSupported(int maxKeySize) { - ValidateUtils.checkTrue(maxKeySize > Byte.SIZE, "Invalid max. key size: %d", maxKeySize); - - try { - BigInteger r = new BigInteger("0").setBit(maxKeySize - 1); - DHParameterSpec dhSkipParamSpec = new DHParameterSpec(r, r); - KeyPairGenerator kpg = getKeyPairGenerator("DH"); - kpg.initialize(dhSkipParamSpec); - return true; - } catch (GeneralSecurityException t) { - return false; - } - } - - public static SecurityProviderChoice getDefaultProviderChoice() { - SecurityProviderChoice choice; - synchronized (DEFAULT_PROVIDER_HOLDER) { - choice = DEFAULT_PROVIDER_HOLDER.get(); - if (choice != null) { - return choice; - } - - String name = System.getProperty(PROP_DEFAULT_SECURITY_PROVIDER); - choice = (GenericUtils.isEmpty(name) || "none".equalsIgnoreCase(name)) - ? SecurityProviderChoice.EMPTY - : SecurityProviderChoice.toSecurityProviderChoice(name); - DEFAULT_PROVIDER_HOLDER.set(choice); - } - - return choice; - } - - public static void setDefaultProviderChoice(SecurityProviderChoice choice) { - DEFAULT_PROVIDER_HOLDER.set(choice); - } - - /** - * @return A <U>copy</U> of the currently registered security providers - */ - public static Set<String> getRegisteredProviders() { - // returns a COPY of the providers in order to avoid modifications - synchronized (REGISTERED_PROVIDERS) { - return new TreeSet<>(REGISTERED_PROVIDERS.keySet()); - } - } - - public static boolean isBouncyCastleRegistered() { - register(); - return isProviderRegistered(BOUNCY_CASTLE); - } - - public static boolean isProviderRegistered(String provider) { - return getRegisteredProvider(provider) != null; - } - - public static SecurityProviderRegistrar getRegisteredProvider(String provider) { - ValidateUtils.checkNotNullAndNotEmpty(provider, "No provider name specified"); - synchronized (REGISTERED_PROVIDERS) { - return REGISTERED_PROVIDERS.get(provider); - } - } - - public static boolean isRegistrationCompleted() { - return REGISTRATION_STATE_HOLDER.get(); - } - - private static void register() { - synchronized (REGISTRATION_STATE_HOLDER) { - if (REGISTRATION_STATE_HOLDER.get()) { - return; - } - - String regsList = System.getProperty(SECURITY_PROVIDER_REGISTRARS, - GenericUtils.join(DEFAULT_SECURITY_PROVIDER_REGISTRARS, ',')); - boolean bouncyCastleRegistered = false; - if ((GenericUtils.length(regsList) > 0) && (!"none".equalsIgnoreCase(regsList))) { - String[] classes = GenericUtils.split(regsList, ','); - Logger logger = LoggerFactory.getLogger(SecurityUtils.class); - boolean debugEnabled = logger.isDebugEnabled(); - for (String registrarClass : classes) { - SecurityProviderRegistrar r; - try { - r = ThreadUtils.createDefaultInstance(SecurityUtils.class, SecurityProviderRegistrar.class, registrarClass); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - logger.error("Failed ({}) to create default {} registrar instance: {}", - e.getClass().getSimpleName(), registrarClass, e.getMessage()); - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new RuntimeException(e); - } - } - - String name = r.getName(); - SecurityProviderRegistrar registeredInstance = registerSecurityProvider(r); - if (registeredInstance == null) { - if (debugEnabled) { - logger.debug("register({}) not registered - enabled={}, supported={}", - name, r.isEnabled(), r.isSupported()); - } - continue; // provider not registered - e.g., disabled, not supported - } - - if (BOUNCY_CASTLE.equalsIgnoreCase(name)) { - bouncyCastleRegistered = true; - } - } - } - - SecurityProviderChoice choice = getDefaultProviderChoice(); - if (((choice == null) || (choice == SecurityProviderChoice.EMPTY)) && bouncyCastleRegistered) { - setDefaultProviderChoice(SecurityProviderChoice.toSecurityProviderChoice(BOUNCY_CASTLE)); - } - - REGISTRATION_STATE_HOLDER.set(true); - } - } - - /** - * @param registrar The registrar instance to register - * @return The registered instance - may be different than required - * if already registered. Returns {@code null} if not already registered - * and not enabled or not supported registrar. - */ - public static SecurityProviderRegistrar registerSecurityProvider(SecurityProviderRegistrar registrar) { - Objects.requireNonNull(registrar, "No registrar instance to register"); - String name = registrar.getName(); - SecurityProviderRegistrar registeredInstance = getRegisteredProvider(name); - if ((registeredInstance == null) && registrar.isEnabled() && registrar.isSupported()) { - try { - SecurityProviderRegistrar.registerSecurityProvider(registrar); - synchronized (REGISTERED_PROVIDERS) { - REGISTERED_PROVIDERS.put(name, registrar); - } - - return registrar; - } catch (Throwable t) { - Logger logger = LoggerFactory.getLogger(SecurityUtils.class); - logger.error("Failed {} to register {} as a JCE provider: {}", - t.getClass().getSimpleName(), name, t.getMessage()); - throw new RuntimeException("Failed to register " + name + " as a JCE provider", t); - } - } - - return registeredInstance; - } - - ///////////////// Bouncycastle specific implementations ////////////////// - - /* -------------------------------------------------------------------- */ - - /** - * @param resourceKey An identifier of the key being loaded - used as - * argument to the {@link FilePasswordProvider#getPassword(String)} - * invocation - * @param inputStream The {@link InputStream} for the <U>private</U> key - * @param provider A {@link FilePasswordProvider} - may be {@code null} - * if the loaded key is <U>guaranteed</U> not to be encrypted - * @return The loaded {@link KeyPair} - * @throws IOException If failed to read/parse the input stream - * @throws GeneralSecurityException If failed to generate the keys - */ - public static KeyPair loadKeyPairIdentity(String resourceKey, InputStream inputStream, FilePasswordProvider provider) - throws IOException, GeneralSecurityException { - KeyPairResourceParser parser = getKeyPairResourceParser(); - if (parser == null) { - throw new NoSuchProviderException("No registered key-pair resource parser"); - } - - Collection<KeyPair> ids = parser.loadKeyPairs(resourceKey, provider, inputStream); - int numLoaded = GenericUtils.size(ids); - if (numLoaded <= 0) { - throw new InvalidKeyException("Unsupported private key file format: " + resourceKey); - } - if (numLoaded != 1) { - throw new InvalidKeySpecException("Multiple private key pairs N/A: " + resourceKey); - } - - return ids.iterator().next(); - } - - /* -------------------------------------------------------------------- */ - - public static AbstractGeneratorHostKeyProvider createGeneratorHostKeyProvider(Path path) { - ValidateUtils.checkTrue(isBouncyCastleRegistered(), "BouncyCastle not registered"); - return new BouncyCastleGeneratorHostKeyProvider(path); - } - - public static KeyPairResourceParser getBouncycastleKeyPairResourceParser() { - ValidateUtils.checkTrue(isBouncyCastleRegistered(), "BouncyCastle not registered"); - return BouncyCastleKeyPairResourceParser.INSTANCE; - } - - /** - * @return If {@link #isBouncyCastleRegistered()} then a {@link BouncyCastleRandomFactory} - * instance, otherwise a {@link JceRandomFactory} one - */ - public static RandomFactory getRandomFactory() { - if (isBouncyCastleRegistered()) { - return BouncyCastleRandomFactory.INSTANCE; - } else { - return JceRandomFactory.INSTANCE; - } - } - - ///////////////////////////// ED25519 support /////////////////////////////// - - /** - * @return {@code true} if EDDSA curves (e.g., {@code ed25519}) are supported - */ - public static boolean isEDDSACurveSupported() { - register(); - - SecurityProviderRegistrar r = getRegisteredProvider(EDDSA); - return (r != null) && r.isEnabled() && r.isSupported(); - } - - /* -------------------------------------------------------------------- */ - - public static PublicKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getEDDSAPublicKeyEntryDecoder() { - if (!isEDDSACurveSupported()) { - throw new UnsupportedOperationException(EDDSA + " provider N/A"); - } - - return EdDSASecurityProviderUtils.getEDDSAPublicKeyEntryDecoder(); - } - - public static PrivateKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getOpenSSHEDDSAPrivateKeyEntryDecoder() { - if (!isEDDSACurveSupported()) { - throw new UnsupportedOperationException(EDDSA + " provider N/A"); - } - - return EdDSASecurityProviderUtils.getOpenSSHEDDSAPrivateKeyEntryDecoder(); - } - - public static org.apache.sshd.common.signature.Signature getEDDSASigner() { - if (isEDDSACurveSupported()) { - return EdDSASecurityProviderUtils.getEDDSASignature(); - } - - throw new UnsupportedOperationException(EDDSA + " Signer not available"); - } - - public static int getEDDSAKeySize(Key key) { - return EdDSASecurityProviderUtils.getEDDSAKeySize(key); - } - - public static Class<? extends PublicKey> getEDDSAPublicKeyType() { - return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.getEDDSAPublicKeyType() : PublicKey.class; - } - - public static Class<? extends PrivateKey> getEDDSAPrivateKeyType() { - return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.getEDDSAPrivateKeyType() : PrivateKey.class; - } - - public static boolean compareEDDSAPPublicKeys(PublicKey k1, PublicKey k2) { - return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.compareEDDSAPPublicKeys(k1, k2) : false; - } - - public static boolean compareEDDSAPrivateKeys(PrivateKey k1, PrivateKey k2) { - return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.compareEDDSAPrivateKeys(k1, k2) : false; - } - - public static PublicKey recoverEDDSAPublicKey(PrivateKey key) throws GeneralSecurityException { - if (!isEDDSACurveSupported()) { - throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); - } - - return EdDSASecurityProviderUtils.recoverEDDSAPublicKey(key); - } - - public static PublicKey generateEDDSAPublicKey(String keyType, byte[] seed) throws GeneralSecurityException { - if (!KeyPairProvider.SSH_ED25519.equals(keyType)) { - throw new InvalidKeyException("Unsupported key type: " + keyType); - } - - if (!isEDDSACurveSupported()) { - throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); - } - - return EdDSASecurityProviderUtils.generateEDDSAPublicKey(seed); - } - - public static <B extends Buffer> B putRawEDDSAPublicKey(B buffer, PublicKey key) { - if (!isEDDSACurveSupported()) { - throw new UnsupportedOperationException(EDDSA + " provider not supported"); - } - - return EdDSASecurityProviderUtils.putRawEDDSAPublicKey(buffer, key); - } - - public static <B extends Buffer> B putEDDSAKeyPair(B buffer, KeyPair kp) { - return putEDDSAKeyPair(buffer, Objects.requireNonNull(kp, "No key pair").getPublic(), kp.getPrivate()); - } - - public static <B extends Buffer> B putEDDSAKeyPair(B buffer, PublicKey pubKey, PrivateKey prvKey) { - if (!isEDDSACurveSupported()) { - throw new UnsupportedOperationException(EDDSA + " provider not supported"); - } - - return EdDSASecurityProviderUtils.putEDDSAKeyPair(buffer, pubKey, prvKey); - } - - public static KeyPair extractEDDSAKeyPair(Buffer buffer, String keyType) throws GeneralSecurityException { - if (!KeyPairProvider.SSH_ED25519.equals(keyType)) { - throw new InvalidKeyException("Unsupported key type: " + keyType); - } - - if (!isEDDSACurveSupported()) { - throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); - } - - throw new GeneralSecurityException("Full SSHD-440 implementation N/A"); - } - - ////////////////////////////////////////////////////////////////////////// - - public static KeyPairResourceParser getKeyPairResourceParser() { - KeyPairResourceParser parser; - synchronized (KEYPAIRS_PARSER_HODLER) { - parser = KEYPAIRS_PARSER_HODLER.get(); - if (parser != null) { - return parser; - } - - parser = KeyPairResourceParser.aggregate( - PEMResourceParserUtils.PROXY, - OpenSSHKeyPairResourceParser.INSTANCE); - KEYPAIRS_PARSER_HODLER.set(parser); - } - - return parser; - } - - /** - * @param parser The system-wide {@code KeyPairResourceParser} to use. - * If set to {@code null}, then the default parser will be re-constructed - * on next call to {@link #getKeyPairResourceParser()} - */ - public static void setKeyPairResourceParser(KeyPairResourceParser parser) { - synchronized (KEYPAIRS_PARSER_HODLER) { - KEYPAIRS_PARSER_HODLER.set(parser); - } - } - - //////////////////////////// Security entities factories ///////////////////////////// - - @SuppressWarnings("unchecked") - public static <T> SecurityEntityFactory<T> resolveSecurityEntityFactory( - Class<T> entityType, String algorithm, Predicate<? super SecurityProviderRegistrar> entitySelector) { - Map<String, SecurityEntityFactory<?>> factoriesMap; - synchronized (SECURITY_ENTITY_FACTORIES) { - factoriesMap = - SECURITY_ENTITY_FACTORIES.computeIfAbsent( - entityType, k -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); - } - - String effectiveName = SecurityProviderRegistrar.getEffectiveSecurityEntityName(entityType, algorithm); - SecurityEntityFactory<?> factoryEntry; - synchronized (factoriesMap) { - factoryEntry = - factoriesMap.computeIfAbsent( - effectiveName, k -> createSecurityEntityFactory(entityType, entitySelector)); - } - - return (SecurityEntityFactory<T>) factoryEntry; - } - - public static <T> SecurityEntityFactory<T> createSecurityEntityFactory( - Class<T> entityType, Predicate<? super SecurityProviderRegistrar> entitySelector) { - register(); - - SecurityProviderRegistrar registrar; - synchronized (REGISTERED_PROVIDERS) { - registrar = - SecurityProviderRegistrar.findSecurityProviderRegistrarBySecurityEntity( - entitySelector, REGISTERED_PROVIDERS.values()); - } - - try { - return SecurityEntityFactory.toFactory(entityType, registrar, getDefaultProviderChoice()); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new RuntimeException(e); - } - } - } - - public static KeyFactory getKeyFactory(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<KeyFactory> factory = - resolveSecurityEntityFactory(KeyFactory.class, algorithm, r -> r.isKeyFactorySupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static Cipher getCipher(String transformation) throws GeneralSecurityException { - SecurityEntityFactory<Cipher> factory = - resolveSecurityEntityFactory(Cipher.class, transformation, r -> r.isCipherSupported(transformation)); - return factory.getInstance(transformation); - } - - public static MessageDigest getMessageDigest(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<MessageDigest> factory = - resolveSecurityEntityFactory(MessageDigest.class, algorithm, r -> r.isMessageDigestSupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static KeyPairGenerator getKeyPairGenerator(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<KeyPairGenerator> factory = - resolveSecurityEntityFactory(KeyPairGenerator.class, algorithm, r -> r.isKeyPairGeneratorSupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static KeyAgreement getKeyAgreement(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<KeyAgreement> factory = - resolveSecurityEntityFactory(KeyAgreement.class, algorithm, r -> r.isKeyAgreementSupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static Mac getMac(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<Mac> factory = - resolveSecurityEntityFactory(Mac.class, algorithm, r -> r.isMacSupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static Signature getSignature(String algorithm) throws GeneralSecurityException { - SecurityEntityFactory<Signature> factory = - resolveSecurityEntityFactory(Signature.class, algorithm, r -> r.isSignatureSupported(algorithm)); - return factory.getInstance(algorithm); - } - - public static CertificateFactory getCertificateFactory(String type) throws GeneralSecurityException { - SecurityEntityFactory<CertificateFactory> factory = - resolveSecurityEntityFactory(CertificateFactory.class, type, r -> r.isCertificateFactorySupported(type)); - return factory.getInstance(type); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java deleted file mode 100644 index 3716719..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.util.security.bouncycastle; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.KeyPair; - -import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class BouncyCastleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProvider { - public BouncyCastleGeneratorHostKeyProvider(Path path) { - setPath(path); - } - - @SuppressWarnings("deprecation") - @Override - protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException { - try (org.bouncycastle.openssl.PEMWriter w = - new org.bouncycastle.openssl.PEMWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) { - w.writeObject(kp); - w.flush(); - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java deleted file mode 100644 index 4c8722a..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleKeyPairResourceParser.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.util.security.bouncycastle; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.NoSuchProviderException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.config.keys.loader.AbstractKeyPairResourceParser; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.io.IoUtils; -import org.apache.sshd.common.util.security.SecurityProviderRegistrar; -import org.apache.sshd.common.util.security.SecurityUtils; -import org.bouncycastle.openssl.PEMDecryptorProvider; -import org.bouncycastle.openssl.PEMEncryptedKeyPair; -import org.bouncycastle.openssl.PEMKeyPair; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class BouncyCastleKeyPairResourceParser extends AbstractKeyPairResourceParser { - public static final List<String> BEGINNERS = - Collections.unmodifiableList( - Arrays.asList( - "BEGIN RSA PRIVATE KEY", - "BEGIN DSA PRIVATE KEY", - "BEGIN EC PRIVATE KEY")); - - public static final List<String> ENDERS = - Collections.unmodifiableList( - Arrays.asList( - "END RSA PRIVATE KEY", - "END DSA PRIVATE KEY", - "END EC PRIVATE KEY")); - - public static final BouncyCastleKeyPairResourceParser INSTANCE = new BouncyCastleKeyPairResourceParser(); - - public BouncyCastleKeyPairResourceParser() { - super(BEGINNERS, ENDERS); - } - - @Override - public Collection<KeyPair> extractKeyPairs( - String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException { - StringBuilder writer = new StringBuilder(beginMarker.length() + endMarker.length() + lines.size() * 80); - writer.append(beginMarker).append(IoUtils.EOL); - lines.forEach(l -> writer.append(l).append(IoUtils.EOL)); - writer.append(endMarker).append(IoUtils.EOL); - - String data = writer.toString(); - byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); - try (InputStream bais = new ByteArrayInputStream(dataBytes)) { - return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, bais); - } - } - - @Override - public Collection<KeyPair> extractKeyPairs( - String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream) - throws IOException, GeneralSecurityException { - KeyPair kp = loadKeyPair(resourceKey, stream, passwordProvider); - return (kp == null) ? Collections.emptyList() : Collections.singletonList(kp); - } - - public static KeyPair loadKeyPair(String resourceKey, InputStream inputStream, FilePasswordProvider provider) - throws IOException, GeneralSecurityException { - try (PEMParser r = new PEMParser(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - Object o = r.readObject(); - - SecurityProviderRegistrar registrar = SecurityUtils.getRegisteredProvider(SecurityUtils.BOUNCY_CASTLE); - if (registrar == null) { - throw new NoSuchProviderException(SecurityUtils.BOUNCY_CASTLE + " registrar not available"); - } - - JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter(); - if (registrar.isNamedProviderUsed()) { - pemConverter.setProvider(registrar.getName()); - } else { - pemConverter.setProvider(registrar.getSecurityProvider()); - } - if (o instanceof PEMEncryptedKeyPair) { - ValidateUtils.checkNotNull(provider, "No password provider for resource=%s", resourceKey); - - String password = ValidateUtils.checkNotNullAndNotEmpty(provider.getPassword(resourceKey), "No password provided for resource=%s", resourceKey); - JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder(); - PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(password.toCharArray()); - o = ((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor); - } - - if (o instanceof PEMKeyPair) { - return pemConverter.getKeyPair((PEMKeyPair) o); - } else if (o instanceof KeyPair) { - return (KeyPair) o; - } else { - throw new IOException("Failed to read " + resourceKey + " - unknown result object: " + o); - } - } - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java deleted file mode 100644 index 36c23e7..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.util.security.bouncycastle; - -import java.security.SecureRandom; - -import org.apache.sshd.common.random.AbstractRandom; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.security.SecurityUtils; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.crypto.prng.VMPCRandomGenerator; - -/** - * BouncyCastle <code>Random</code>. - * This pseudo random number generator uses the a very fast PRNG from BouncyCastle. - * The JRE random will be used when creating a new generator to add some random - * data to the seed. - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public final class BouncyCastleRandom extends AbstractRandom { - public static final String NAME = SecurityUtils.BOUNCY_CASTLE; - private final RandomGenerator random; - - public BouncyCastleRandom() { - ValidateUtils.checkTrue(SecurityUtils.isBouncyCastleRegistered(), "BouncyCastle not registered"); - this.random = new VMPCRandomGenerator(); - byte[] seed = new SecureRandom().generateSeed(8); - this.random.addSeedMaterial(seed); - } - - @Override - public String getName() { - return NAME; - } - - @Override - public void fill(byte[] bytes, int start, int len) { - this.random.nextBytes(bytes, start, len); - } - - /** - * Returns a pseudo-random uniformly distributed {@code int} - * in the half-open range [0, n). - */ - @Override - public int random(int n) { - ValidateUtils.checkTrue(n > 0, "Limit must be positive: %d", n); - if ((n & -n) == n) { - return (int) ((n * (long) next(31)) >> 31); - } - - int bits; - int val; - do { - bits = next(31); - val = bits % n; - } while (bits - val + (n - 1) < 0); - return val; - } - - private int next(int numBits) { - int bytes = (numBits + 7) / 8; - byte next[] = new byte[bytes]; - int ret = 0; - random.nextBytes(next); - for (int i = 0; i < bytes; i++) { - ret = (next[i] & 0xFF) | (ret << 8); - } - return ret >>> (bytes * 8 - numBits); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java deleted file mode 100644 index 720c7a5..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.util.security.bouncycastle; - -import org.apache.sshd.common.random.AbstractRandomFactory; -import org.apache.sshd.common.random.Random; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * Named factory for the BouncyCastle <code>Random</code> - */ -public final class BouncyCastleRandomFactory extends AbstractRandomFactory { - public static final String NAME = "bouncycastle"; - public static final BouncyCastleRandomFactory INSTANCE = new BouncyCastleRandomFactory(); - - public BouncyCastleRandomFactory() { - super(NAME); - } - - @Override - public boolean isSupported() { - return SecurityUtils.isBouncyCastleRegistered(); - } - - @Override - public Random create() { - return new BouncyCastleRandom(); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java deleted file mode 100644 index b47ca80..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.util.security.bouncycastle; - -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.Provider; -import java.security.Signature; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ReflectionUtils; -import org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar; -import org.apache.sshd.common.util.security.SecurityUtils; -import org.apache.sshd.common.util.threads.ThreadUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class BouncyCastleSecurityProviderRegistrar extends AbstractSecurityProviderRegistrar { - // We want to use reflection API so as not to require BouncyCastle to be present in the classpath - public static final String PROVIDER_CLASS = "org.bouncycastle.jce.provider.BouncyCastleProvider"; - // Do not define a static registrar instance to minimize class loading issues - private final AtomicReference<Boolean> supportHolder = new AtomicReference<>(null); - private final AtomicReference<String> allSupportHolder = new AtomicReference<>(); - - public BouncyCastleSecurityProviderRegistrar() { - super(SecurityUtils.BOUNCY_CASTLE); - } - - @Override - public boolean isEnabled() { - if (!super.isEnabled()) { - return false; - } - - // For backward compatibility - return this.getBooleanProperty(SecurityUtils.REGISTER_BOUNCY_CASTLE_PROP, true); - } - - @Override - public Provider getSecurityProvider() { - try { - return getOrCreateProvider(PROVIDER_CLASS); - } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); - log.error("getSecurityProvider({}) failed ({}) to instantiate {}: {}", - getName(), e.getClass().getSimpleName(), PROVIDER_CLASS, e.getMessage()); - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } - - throw new RuntimeException(e); - } - } - - @Override - public String getDefaultSecurityEntitySupportValue(Class<?> entityType) { - String allValue = allSupportHolder.get(); - if (GenericUtils.length(allValue) > 0) { - return allValue; - } - - String propName = getConfigurationPropertyName("supportAll"); - allValue = this.getStringProperty(propName, ALL_OPTIONS_VALUE); - if (GenericUtils.isEmpty(allValue)) { - allValue = NO_OPTIONS_VALUE; - } - - allSupportHolder.set(allValue); - return allValue; - } - - @Override - public boolean isSecurityEntitySupported(Class<?> entityType, String name) { - if (!isSupported()) { - return false; - } - - // Some known values it does not support - if (KeyPairGenerator.class.isAssignableFrom(entityType) - || KeyFactory.class.isAssignableFrom(entityType)) { - if (Objects.compare(name, SecurityUtils.EDDSA, String.CASE_INSENSITIVE_ORDER) == 0) { - return false; - } - } else if (Signature.class.isAssignableFrom(entityType)) { - if (Objects.compare(name, SecurityUtils.CURVE_ED25519_SHA512, String.CASE_INSENSITIVE_ORDER) == 0) { - return false; - } - } - - return super.isSecurityEntitySupported(entityType, name); - } - - @Override - public boolean isSupported() { - Boolean supported; - synchronized (supportHolder) { - supported = supportHolder.get(); - if (supported != null) { - return supported.booleanValue(); - } - - ClassLoader cl = ThreadUtils.resolveDefaultClassLoader(getClass()); - supported = ReflectionUtils.isClassAvailable(cl, PROVIDER_CLASS); - supportHolder.set(supported); - } - - return supported.booleanValue(); - } -}
