parent
3af1134975
commit
47340e9318
5 changed files with 151 additions and 10 deletions
44
.github/workflows/ci.yml
vendored
44
.github/workflows/ci.yml
vendored
|
@ -100,6 +100,50 @@ jobs:
|
||||||
path: reports-unit-tests.zip
|
path: reports-unit-tests.zip
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
|
crypto-tests:
|
||||||
|
name: Crypto Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: ${{ env.DEFAULT_JDK_VERSION }}
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Update maven settings
|
||||||
|
run: mkdir -p ~/.m2 ; cp .github/settings.xml ~/.m2/
|
||||||
|
- name: Cleanup org.keycloak artifacts
|
||||||
|
run: rm -rf ~/.m2/repository/org/keycloak >/dev/null || true
|
||||||
|
- name: Download built keycloak
|
||||||
|
id: download-keycloak
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository/org/keycloak/
|
||||||
|
name: keycloak-artifacts.zip
|
||||||
|
- name: Run crypto tests (BCFIPS non-approved mode)
|
||||||
|
run: |
|
||||||
|
if ! ./mvnw install -nsu -B -f crypto/pom.xml -Dcom.redhat.fips=true; then
|
||||||
|
find . -path 'crypto/target/surefire-reports/*.xml' | zip -q reports-crypto-tests.zip -@
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Run crypto tests (BCFIPS approved mode)
|
||||||
|
run: |
|
||||||
|
if ! ./mvnw install -nsu -B -f crypto/pom.xml -Dcom.redhat.fips=true -Dorg.bouncycastle.fips.approved_only=true; then
|
||||||
|
find . -path 'crypto/target/surefire-reports/*.xml' | zip -q reports-crypto-tests.zip -@
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Crypto test reports
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: reports-crypto-tests
|
||||||
|
retention-days: 14
|
||||||
|
path: reports-crypto-tests.zip
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
model-tests:
|
model-tests:
|
||||||
name: Model Tests
|
name: Model Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -57,12 +57,17 @@ public abstract class KeyPairVerifierTest {
|
||||||
+ "PEuQrsfWRXm9/dTEavbfNkv5E53zWXjWyf93ezkVhBX0YoXmf6UO7PAlvsrjno3T\n" + "uwIDAQAB\n" + "-----END PUBLIC KEY-----";
|
+ "PEuQrsfWRXm9/dTEavbfNkv5E53zWXjWyf93ezkVhBX0YoXmf6UO7PAlvsrjno3T\n" + "uwIDAQAB\n" + "-----END PUBLIC KEY-----";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyWithPrivateKeysInTraditionalRSAFormat() throws Exception {
|
public void verifyWith1024PrivateKeyInTraditionalRSAFormat() throws Exception {
|
||||||
verifyImpl(this.privateKey1, this.privateKey2048);
|
verifyImplRsa1024Key(this.privateKey1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyWithPrivateKeysInPKCS8Format() throws Exception {
|
public void verifyWith2048PrivateKeyInTraditionalRSAFormat() throws Exception {
|
||||||
|
verifyImplRsa2048Key(this.privateKey2048);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith1024PrivateKeyInPKCS8Format() throws Exception {
|
||||||
String privateKey1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtWsK5O0CtuBpnM" +
|
String privateKey1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtWsK5O0CtuBpnM" +
|
||||||
"vWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfd" +
|
"vWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfd" +
|
||||||
"Q2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5" +
|
"Q2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5" +
|
||||||
|
@ -78,6 +83,11 @@ public abstract class KeyPairVerifierTest {
|
||||||
"7KQ6+vVqJlQwVPvYdTSOeZB7YVV6S4b4slS3ZObsa0yNMWgal/QnCtW5k3f185gC" +
|
"7KQ6+vVqJlQwVPvYdTSOeZB7YVV6S4b4slS3ZObsa0yNMWgal/QnCtW5k3f185gC" +
|
||||||
"Wj6dOLGB5btfxg==";
|
"Wj6dOLGB5btfxg==";
|
||||||
|
|
||||||
|
verifyImplRsa1024Key(privateKey1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith2048PrivateKeyInPKCS8Format() throws Exception {
|
||||||
String privateKey2048 = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhXcyk6e4qx0Ft" +
|
String privateKey2048 = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhXcyk6e4qx0Ft" +
|
||||||
"HVTM2Mr2jmZ4QxDizlWnKSG/UOmpOKUo6IQftVD9e2M3HDTKOcUGKUKekrrI32YM" +
|
"HVTM2Mr2jmZ4QxDizlWnKSG/UOmpOKUo6IQftVD9e2M3HDTKOcUGKUKekrrI32YM" +
|
||||||
"QdsETNpGO12uBWGQh6OJpcUE/kwGFRDmX27wTchkLcTynAONUXRn27RHiUZ5SDaT" +
|
"QdsETNpGO12uBWGQh6OJpcUE/kwGFRDmX27wTchkLcTynAONUXRn27RHiUZ5SDaT" +
|
||||||
|
@ -105,21 +115,22 @@ public abstract class KeyPairVerifierTest {
|
||||||
"Zer7cRS4Vsn4uNvxhYGB4+NIcOhL/r7/7OoHVvm5Cn+NgVthCXnRQ9E9MX66XV5C" +
|
"Zer7cRS4Vsn4uNvxhYGB4+NIcOhL/r7/7OoHVvm5Cn+NgVthCXnRQ9E9MX66XV5C" +
|
||||||
"jLsXjc2CPf/lwNFqsVl7dlPNmg==";
|
"jLsXjc2CPf/lwNFqsVl7dlPNmg==";
|
||||||
|
|
||||||
verifyImpl(privateKey1, privateKey2048);
|
verifyImplRsa2048Key(privateKey2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void verifyImpl(String privateKey1, String privateKey2048) throws Exception {
|
protected void verifyImplRsa1024Key(String rsaPrivateKey1024) throws Exception {
|
||||||
KeyPairVerifier.verify(privateKey1, publicKey1);
|
KeyPairVerifier.verify(rsaPrivateKey1024, publicKey1);
|
||||||
KeyPairVerifier.verify(privateKey2048, publicKey2048);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeyPairVerifier.verify(privateKey1, publicKey2048);
|
KeyPairVerifier.verify(rsaPrivateKey1024, publicKey2048);
|
||||||
Assert.fail("Expected VerificationException");
|
Assert.fail("Expected VerificationException");
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void verifyImplRsa2048Key(String rsaPrivateKey2048) throws Exception {
|
||||||
|
KeyPairVerifier.verify(rsaPrivateKey2048, publicKey2048);
|
||||||
try {
|
try {
|
||||||
KeyPairVerifier.verify(privateKey2048, publicKey1);
|
KeyPairVerifier.verify(rsaPrivateKey2048, publicKey1);
|
||||||
Assert.fail("Expected VerificationException");
|
Assert.fail("Expected VerificationException");
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,4 +85,19 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<java.security.properties>${basedir}/target/test-classes/kc.java.security</java.security.properties>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -1,7 +1,11 @@
|
||||||
package org.keycloak.crypto.fips.test;
|
package org.keycloak.crypto.fips.test;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.CryptoServicesRegistrar;
|
||||||
|
import org.bouncycastle.crypto.fips.FipsUnapprovedOperationError;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
|
import org.junit.Test;
|
||||||
import org.keycloak.KeyPairVerifierTest;
|
import org.keycloak.KeyPairVerifierTest;
|
||||||
import org.keycloak.common.util.Environment;
|
import org.keycloak.common.util.Environment;
|
||||||
|
|
||||||
|
@ -17,4 +21,42 @@ public class FIPS1402KeyPairVerifierTest extends KeyPairVerifierTest {
|
||||||
// Run this test just if java is in FIPS mode
|
// Run this test just if java is in FIPS mode
|
||||||
Assume.assumeTrue("Java is not in FIPS mode. Skipping the test.", Environment.isJavaInFipsMode());
|
Assume.assumeTrue("Java is not in FIPS mode. Skipping the test.", Environment.isJavaInFipsMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith1024PrivateKeyInTraditionalRSAFormat() throws Exception {
|
||||||
|
// Signature generation with RSA 1024 key works just in non-approved mode
|
||||||
|
Assume.assumeFalse(CryptoServicesRegistrar.isInApprovedOnlyMode());
|
||||||
|
super.verifyWith1024PrivateKeyInTraditionalRSAFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith1024PrivateKeyInPKCS8Format() throws Exception {
|
||||||
|
// Signature generation with RSA 1024 key works just in non-approved mode
|
||||||
|
Assume.assumeFalse(CryptoServicesRegistrar.isInApprovedOnlyMode());
|
||||||
|
super.verifyWith1024PrivateKeyInPKCS8Format();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith1024PrivateKeyInTraditionalRSAFormatShouldFail() throws Exception {
|
||||||
|
// Signature generation with RSA 1024 key works just in non-approved mode
|
||||||
|
Assume.assumeTrue(CryptoServicesRegistrar.isInApprovedOnlyMode());
|
||||||
|
try {
|
||||||
|
super.verifyWith1024PrivateKeyInTraditionalRSAFormat();
|
||||||
|
Assert.fail("Should not successfully generate signature with RSA 1024 key in BC approved mode");
|
||||||
|
} catch (FipsUnapprovedOperationError fipsError) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyWith1024PrivateKeyInPKCS8FormatShouldFail() throws Exception {
|
||||||
|
// Signature generation with RSA 1024 key works just in non-approved mode
|
||||||
|
Assume.assumeTrue(CryptoServicesRegistrar.isInApprovedOnlyMode());
|
||||||
|
try {
|
||||||
|
super.verifyWith1024PrivateKeyInPKCS8Format();
|
||||||
|
Assert.fail("Should not successfully generate signature with RSA 1024 key in BC approved mode");
|
||||||
|
} catch (FipsUnapprovedOperationError fipsError) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
29
crypto/fips1402/src/test/resources/kc.java.security
Normal file
29
crypto/fips1402/src/test/resources/kc.java.security
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Configuration file just with the security properties, which are supposed to be overriden. The properties, which are not mentioned in this file,
|
||||||
|
# are inherited from the default java.security file bundled within the distribution.
|
||||||
|
#
|
||||||
|
# NOTE: Each property is specified 2 times. This is so the same file can be used on both FIPS based RHEL host (which uses "fips" prefixed properties by default)
|
||||||
|
# and the non-fips based (EG. when running the tests on GH actions)
|
||||||
|
|
||||||
|
#
|
||||||
|
# List of providers and their preference orders (see above). Used on the host without FIPS (EG. when running the tests on GH actions)
|
||||||
|
# NOTE: List is empty for now, so we test just with BCFIPS provider, which is registered programatically
|
||||||
|
#
|
||||||
|
security.provider.1=
|
||||||
|
|
||||||
|
#
|
||||||
|
# Security providers used when global crypto-policies are set to FIPS.
|
||||||
|
# NOTE: List is empty for now, so we test just with BCFIPS provider, which is registered programatically
|
||||||
|
#
|
||||||
|
fips.provider.1=
|
||||||
|
#fips.provider.1=SunPKCS11 ${java.home}/conf/security/nss.fips.cfg
|
||||||
|
#fips.provider.2=SunEC
|
||||||
|
#fips.provider.3=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS-FIPS
|
||||||
|
|
||||||
|
# Commented this provider for now as it uses lots of non-FIPS services. See https://access.redhat.com/documentation/en-us/openjdk/11/html-single/configuring_openjdk_11_on_rhel_with_fips/index#ref_openjdk-default-fips-configuration_openjdk
|
||||||
|
# fips.provider.2=SUN
|
||||||
|
|
||||||
|
#
|
||||||
|
# Default keystore type.
|
||||||
|
#
|
||||||
|
keystore.type=PKCS11
|
||||||
|
fips.keystore.type=PKCS11
|
Loading…
Reference in a new issue