-
Couldn't load subscription status.
- Fork 98
Add support for FIPS for TlsKeyGenerator #289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,20 @@ | |
| package org.apache.directory.server.core.security; | ||
|
|
||
|
|
||
| import org.apache.directory.api.ldap.model.constants.SchemaConstants; | ||
| import org.apache.directory.api.ldap.model.entry.Attribute; | ||
| import org.apache.directory.api.ldap.model.entry.Entry; | ||
| import org.apache.directory.api.ldap.model.exception.LdapException; | ||
| import org.apache.directory.server.i18n.I18n; | ||
| import org.bouncycastle.asn1.x500.X500Name; | ||
| import org.bouncycastle.cert.X509v1CertificateBuilder; | ||
| import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; | ||
| import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder; | ||
| import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider; | ||
| import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.io.ByteArrayInputStream; | ||
| import java.io.InputStream; | ||
| import java.math.BigInteger; | ||
|
|
@@ -40,26 +54,20 @@ | |
| import java.security.spec.X509EncodedKeySpec; | ||
| import java.util.Date; | ||
|
|
||
| import javax.security.auth.x500.X500Principal; | ||
|
|
||
| import org.apache.directory.api.ldap.model.constants.SchemaConstants; | ||
| import org.apache.directory.api.ldap.model.entry.Attribute; | ||
| import org.apache.directory.api.ldap.model.entry.Entry; | ||
| import org.apache.directory.api.ldap.model.exception.LdapException; | ||
| import org.apache.directory.server.i18n.I18n; | ||
| import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||
| import org.bouncycastle.x509.X509V1CertificateGenerator; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
|
|
||
| /** | ||
| * Generates the default RSA key pair for the server. | ||
| * | ||
| * @see https://github.com/apache/directory-server/blob/2.0.0-M20/core/src/main/java/org/apache/directory/server/core/security/TlsKeyGenerator.java | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is a bit superfluous I think, please remove this. |
||
| * @author <a href="mailto:[email protected]">Apache Directory Project</a> | ||
| * @author Farid Zakaria <[email protected]> | ||
| */ | ||
| public class TlsKeyGenerator | ||
| @SuppressWarnings("all") | ||
| public final class TlsKeyGenerator | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to make this a final class? |
||
| { | ||
| private TlsKeyGenerator() | ||
| { | ||
| } | ||
|
|
||
| private static final Logger LOG = LoggerFactory.getLogger( TlsKeyGenerator.class ); | ||
|
|
||
| public static final String TLS_KEY_INFO_OC = "tlsKeyInfo"; | ||
|
|
@@ -79,7 +87,7 @@ public class TlsKeyGenerator | |
| /* | ||
| * Eventually we have to make several of these parameters configurable, | ||
| * however note to pass export restrictions we must use a key size of | ||
| * 512 or less here as the default. Users can configure this setting | ||
| * 1024 or less here as the default. Users can configure this setting | ||
| * later based on their own legal situations. This is required to | ||
| * classify ApacheDS in the ECCN 5D002 category. Please see the following | ||
| * page for more information: | ||
|
|
@@ -90,12 +98,13 @@ public class TlsKeyGenerator | |
| * | ||
| * http://www.apache.org/licenses/exports | ||
| */ | ||
| private static final int KEY_SIZE = 512; | ||
| private static final int KEY_SIZE = 1024; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this change required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes FIPS requires 1024+ key size |
||
| private static final long YEAR_MILLIS = 365L * 24L * 3600L * 1000L; | ||
|
|
||
| static | ||
| { | ||
| Security.addProvider( new BouncyCastleProvider() ); | ||
| System.out.println("Using a modified version of TlsKeyGenerator to ensure Bouncy Castle FIPS provider is used."); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use |
||
| Security.addProvider( new BouncyCastleFipsProvider() ); | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -256,33 +265,36 @@ else if ( !objectClass.contains( TLS_KEY_INFO_OC ) ) | |
| Date expiryDate = new Date( System.currentTimeMillis() + YEAR_MILLIS ); | ||
| BigInteger serialNumber = BigInteger.valueOf( System.currentTimeMillis() ); | ||
|
|
||
| X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); | ||
| X500Principal issuerDn = new X500Principal( CERTIFICATE_PRINCIPAL_DN ); | ||
|
|
||
| X500Principal subjectDn = null; | ||
| X500Name issuerDn = new X500Name( CERTIFICATE_PRINCIPAL_DN ); | ||
| X500Name subjectDn = null; | ||
|
|
||
| try | ||
| { | ||
| String hostName = InetAddress.getLocalHost().getHostName(); | ||
| subjectDn = new X500Principal( "CN=" + hostName + "," + BASE_DN ); | ||
| subjectDn = new X500Name( "CN=" + hostName + "," + BASE_DN ); | ||
| } | ||
| catch ( Exception e ) | ||
| { | ||
| LOG.warn( "failed to create certificate subject name from host name", e ); | ||
| subjectDn = issuerDn; | ||
| } | ||
|
|
||
| certGen.setSerialNumber( serialNumber ); | ||
| certGen.setIssuerDN( issuerDn ); | ||
| certGen.setNotBefore( startDate ); | ||
| certGen.setNotAfter( expiryDate ); | ||
| certGen.setSubjectDN( subjectDn ); | ||
| certGen.setPublicKey( publicKey ); | ||
| certGen.setSignatureAlgorithm( "SHA1With" + ALGORITHM ); | ||
| X509v1CertificateBuilder certGen = new JcaX509v1CertificateBuilder( | ||
| issuerDn, | ||
| serialNumber, | ||
| startDate, | ||
| expiryDate, | ||
| subjectDn, | ||
| publicKey | ||
| ); | ||
|
|
||
| final JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA384withRSA") | ||
| .setProvider("BCFIPS"); | ||
|
|
||
| try | ||
| { | ||
| X509Certificate cert = certGen.generate( privateKey, "BC" ); | ||
| X509Certificate cert = new JcaX509CertificateConverter().setProvider("BCFIPS") | ||
| .getCertificate(certGen.build(signerBuilder.build(privateKey))); | ||
| entry.put( USER_CERTIFICATE_AT, cert.getEncoded() ); | ||
| LOG.debug( "X509 Certificate: {}", cert ); | ||
| } | ||
|
|
@@ -297,13 +309,19 @@ else if ( !objectClass.contains( TLS_KEY_INFO_OC ) ) | |
| } | ||
|
|
||
|
|
||
| public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, String keyAlgo ) throws LdapException | ||
| { | ||
| addKeyPair( entry, issuerDN, subjectDN, keyAlgo, KEY_SIZE ); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * @see #addKeyPair(org.apache.directory.api.ldap.model.entry.Entry) | ||
| * | ||
| * TODO the code is duplicate atm, will eliminate this redundancy after finding | ||
| * a better thought (an instant one is to call this method from the aboveaddKeyPair(entry) and remove the impl there) | ||
| */ | ||
| public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, String keyAlgo ) | ||
| public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, String keyAlgo, int keySize ) | ||
| throws LdapException | ||
| { | ||
| Attribute objectClass = entry.get( SchemaConstants.OBJECT_CLASS_AT ); | ||
|
|
@@ -329,7 +347,7 @@ public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, S | |
| throw ne; | ||
| } | ||
|
|
||
| generator.initialize( KEY_SIZE ); | ||
| generator.initialize( keySize ); | ||
| KeyPair keypair = generator.genKeyPair(); | ||
| entry.put( KEY_ALGORITHM_AT, keyAlgo ); | ||
|
|
||
|
|
@@ -349,21 +367,25 @@ public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, S | |
| Date expiryDate = new Date( System.currentTimeMillis() + YEAR_MILLIS ); | ||
| BigInteger serialNumber = BigInteger.valueOf( System.currentTimeMillis() ); | ||
|
|
||
| X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); | ||
| X500Principal issuerName = new X500Principal( issuerDN ); | ||
| X500Principal subjectName = new X500Principal( subjectDN ); | ||
| X500Name issuerName = new X500Name( issuerDN ); | ||
| X500Name subjectName = new X500Name( subjectDN ); | ||
|
|
||
| X509v1CertificateBuilder certGen = new JcaX509v1CertificateBuilder( | ||
| issuerName, | ||
| serialNumber, | ||
| startDate, | ||
| expiryDate, | ||
| subjectName, | ||
| publicKey | ||
| ); | ||
|
|
||
| certGen.setSerialNumber( serialNumber ); | ||
| certGen.setIssuerDN( issuerName ); | ||
| certGen.setNotBefore( startDate ); | ||
| certGen.setNotAfter( expiryDate ); | ||
| certGen.setSubjectDN( subjectName ); | ||
| certGen.setPublicKey( publicKey ); | ||
| certGen.setSignatureAlgorithm( "SHA1With" + keyAlgo ); | ||
| final JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA384withRSA") | ||
| .setProvider("BCFIPS"); | ||
|
|
||
| try | ||
| { | ||
| X509Certificate cert = certGen.generate( privateKey, "BC" ); | ||
| X509Certificate cert = new JcaX509CertificateConverter().setProvider("BCFIPS") | ||
| .getCertificate(certGen.build(signerBuilder.build(privateKey))); | ||
| entry.put( USER_CERTIFICATE_AT, cert.getEncoded() ); | ||
| LOG.debug( "X509 Certificate: {}", cert ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,7 @@ | |
| <!-- Set versions for depending jars --> | ||
| <ant.version>1.9.4</ant.version> | ||
| <bcprov.version>1.52</bcprov.version> | ||
| <bcpkix-fips.version>2.0.7</bcpkix-fips.version> | ||
| <commons.cli.version>1.2</commons.cli.version> | ||
| <commons.collections.version>3.2.1</commons.collections.version> | ||
| <commons.daemon.version>1.0.15</commons.daemon.version> | ||
|
|
@@ -162,8 +163,8 @@ | |
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <configuration> | ||
| <source>1.7</source> | ||
| <target>1.7</target> | ||
| <source>1.8</source> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this ok to keep 1.7? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't compile any more unless this was set. |
||
| <target>1.8</target> | ||
| <optimize>true</optimize> | ||
| <showDeprecations>true</showDeprecations> | ||
| <encoding>ISO-8859-1</encoding> | ||
|
|
@@ -1203,6 +1204,12 @@ | |
| <version>${bcprov.version}</version> | ||
| </dependency> | ||
|
|
||
| <dependency> | ||
| <groupId>org.bouncycastle</groupId> | ||
| <artifactId>bcpkix-fips</artifactId> | ||
| <version>${bcpkix-fips.version}</version> | ||
| </dependency> | ||
|
|
||
| <dependency> | ||
| <groupId>org.mortbay.jetty</groupId> | ||
| <artifactId>jetty</artifactId> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep the order of import as is (to conform with the code style of this repo)