Skip to content
Commits on Source (46)
......@@ -6,5 +6,8 @@
<classpathentry kind="lib" path="/usr/share/java/slf4j/slf4j-api.jar"/>
<classpathentry kind="lib" path="/usr/share/java/commons-lang.jar"/>
<classpathentry kind="lib" path="/usr/share/java/commons-codec.jar"/>
<classpathentry kind="lib" path="/usr/share/java/junit.jar"/>
<classpathentry kind="lib" path="/usr/share/java/hamcrest/core.jar"/>
<classpathentry kind="lib" path="/usr/share/java/slf4j/slf4j-simple.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
srpm:
./build.sh srpm
if [[ "${outdir}" != "" ]]; then \
mv ${HOME}/build/jss/SRPMS/* ${outdir}; \
fi
......@@ -9,7 +9,6 @@ services:
- docker
stages:
- validate
- test
- extra
......@@ -23,8 +22,6 @@ script:
matrix:
fast_finish: true
include:
- stage: validate
env: BASE_IMAGE="stylecheck"
- stage: extra
env: BASE_IMAGE="pkcs11check"
- stage: extra
......
......@@ -23,6 +23,7 @@ This project has the following dependencies:
- [NSPR](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR)
- [NSS](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS)
- Minimum version: 3.30
- A c and c++ compiler such as [gcc](ttps://gcc.gnu.org/)
- [zlib](https://zlib.net/)
- [OpenJDK 1.8.0](https://openjdk.java.net/)
......@@ -31,19 +32,23 @@ This project has the following dependencies:
- [Apache Commons Codec](https://commons.apache.org/proper/commons-codec/)
- [JavaEE JAXB](https://github.com/eclipse-ee4j/jaxb-ri)
- [SLF4J](https://www.slf4j.org/)
- [JUnit 4](https://junit.org/junit4/)
- [Hamcrest](http://hamcrest.org/)
To install these dependencies on Fedora, execute the following:
sudo dnf install apache-commons-codec apache-commons-lang gcc-c++ \
java-devel jpackage-utils slf4j zlib-devel \
glassfish-jaxb-api nss-tools nss-devel cmake
glassfish-jaxb-api nss-tools nss-devel cmake \
hamcrest junit
To install these dependencies on Debian, execute the following:
sudo apt-get install build-essential libcommons-codec-java \
libcommons-lang-java libnss3-dev libslf4j-java \
openjdk-8-jdk pkg-config zlib1g-dev \
libjaxb-api-java libnss3-tools cmake zip unzip
libjaxb-api-java libnss3-tools cmake zip unzip \
libhamcrest-java junit4
Building
......@@ -53,7 +58,7 @@ To build JSS and make a best effort to detect environment variables:
git clone https://github.com/dogtagpki/jss
cd jss/build && cmake ..
make all check
make all test
Alternatively, to build a RPM distribution of JSS:
......
......@@ -83,7 +83,7 @@ macro(jss_build_java)
add_custom_command(
OUTPUT "${TESTS_JNI_OUTPUTS}"
COMMAND ${Java_JAVAC_EXECUTABLE} ${JSS_JAVAC_FLAGS} -d ${TESTS_CLASSES_OUTPUT_DIR} -h ${TESTS_JNI_OUTPUT_DIR} ${JAVA_TEST_SOURCES}
COMMAND ${Java_JAVAC_EXECUTABLE} ${JSS_TEST_JAVAC_FLAGS} -d ${TESTS_CLASSES_OUTPUT_DIR} -h ${TESTS_JNI_OUTPUT_DIR} ${JAVA_TEST_SOURCES}
COMMAND touch "${TESTS_JNI_OUTPUTS}"
DEPENDS ${JAVA_TEST_SOURCES}
)
......
......@@ -2,7 +2,7 @@ macro(jss_config)
# Set the current JSS release number. Arguments are:
# MAJOR MINOR PATCH BETA
# When BETA is zero, it isn't a beta release.
jss_config_version(4 5 1 0)
jss_config_version(4 5 3 0)
# Configure output directories
jss_config_outputs()
......@@ -70,8 +70,9 @@ macro(jss_config_outputs)
set(TARGETS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/.targets")
# These folders are for the NSS DBs created during testing
set(RESULTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/tests")
set(RESULTS_FIPS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/fips")
set(RESULTS_DATA_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/data")
set(RESULTS_NSSDB_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/nssdb")
set(RESULTS_NSSDB_FIPS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/fips")
# This is a temporary location for building the reproducible jar
set(REPRODUCIBLE_TEMP_DIR "${CMAKE_BINARY_DIR}/reproducible")
......@@ -123,6 +124,8 @@ macro(jss_config_cflags)
endif()
list(APPEND JSS_RAW_C_FLAGS "-Wall")
list(APPEND JSS_RAW_C_FLAGS "-Wno-cast-function-type")
list(APPEND JSS_RAW_C_FLAGS "-Wno-unused-parameter")
list(APPEND JSS_RAW_C_FLAGS "-Werror-implicit-function-declaration")
list(APPEND JSS_RAW_C_FLAGS "-Wno-switch")
list(APPEND JSS_RAW_C_FLAGS "-I${NSPR_INCLUDE_DIR}")
......@@ -196,6 +199,14 @@ macro(jss_config_java)
SLF4J_JDK14_JAR
NAMES jdk14 slf4j/jdk14 slf4j-jdk14
)
find_jar(
JUNIT4_JAR
NAMES junit4 junit
)
find_jar(
HAMCREST_JAR
NAMES hamcrest/core
)
# Validate that we've found the required JARs
if(SLF4J_API_JAR STREQUAL "SLF4J_API_JAR-NOTFOUND")
......@@ -218,10 +229,22 @@ macro(jss_config_java)
message(WARNING "Test dependency sfl4j-jdk14.jar not found by find_jar! Tests might not run properly.")
endif()
if(JUINT4_JAR STREQUAL "JUNIT4_JAR-NOTFOUND")
message(FATAL_ERROR "Test dependency junit4.jar not found by find_jar! Tests will not compile.")
endif()
if(HAMCREST_JAR STREQUAL "HAMCREST_JAR-NOTFOUND")
message(WARNING "Test dependency hamcrest/core.jar not found by find_jar! Tests might not run properly.")
endif()
# Set class paths
set(JAVAC_CLASSPATH "${SLF4J_API_JAR}:${CODEC_JAR}:${LANG_JAR}:${JAXB_JAR}")
set(TEST_CLASSPATH "${JSS_JAR_PATH}:${JSS_TESTS_JAR_PATH}:${JAVAC_CLASSPATH}:${SLF4J_JDK14_JAR}")
set(TEST_CLASSPATH "${JSS_JAR_PATH}:${JSS_TESTS_JAR_PATH}:${JAVAC_CLASSPATH}:${SLF4J_JDK14_JAR}:${JUNIT4_JAR}:${HAMCREST_JAR}")
message(STATUS "javac classpath: ${JAVAC_CLASSPATH}")
message(STATUS "tests classpath: ${TEST_CLASSPATH}")
# Set compile flags for JSS
list(APPEND JSS_JAVAC_FLAGS "-classpath")
list(APPEND JSS_JAVAC_FLAGS "${JAVAC_CLASSPATH}")
list(APPEND JSS_JAVAC_FLAGS "-sourcepath")
......@@ -232,6 +255,17 @@ macro(jss_config_java)
list(APPEND JSS_JAVAC_FLAGS "-O")
endif()
# Set compile flags for JSS test suite
list(APPEND JSS_TEST_JAVAC_FLAGS "-classpath")
list(APPEND JSS_TEST_JAVAC_FLAGS "${JAVAC_CLASSPATH}:${JUNIT4_JAR}")
list(APPEND JSS_TEST_JAVAC_FLAGS "-sourcepath")
list(APPEND JSS_TEST_JAVAC_FLAGS "${PROJECT_SOURCE_DIR}")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
list(APPEND JSS_TEST_JAVAC_FLAGS "-g")
else()
list(APPEND JSS_TEST_JAVAC_FLAGS "-O")
endif()
# Variables for javadoc building. Note that JSS_PACKAGES needs to be
# updated whenever a new package is created.
set(JSS_WINDOW_TITLE "JSS: Java Security Services")
......
......@@ -6,6 +6,56 @@ macro(jss_tests)
set(PASSWORD_FILE "${JSS_TEST_DIR}/passwords")
set(DB_PWD "m1oZilla")
# Create directories for test cases:
# - results/data
# - results/nssdb
# - results/fips
jss_test_exec(
NAME "Clean_Data_Dir"
COMMAND "cmake" "-E" "remove_directory" "${RESULTS_DATA_OUTPUT_DIR}"
)
jss_test_exec(
NAME "Create_Data_Dir"
COMMAND "cmake" "-E" "make_directory" "${RESULTS_DATA_OUTPUT_DIR}"
DEPENDS "Clean_Data_Dir"
)
# Rather than creating our results directories earlier in JSSConfig,
# create them here so that the test suite can be rerun multiple times.
jss_test_exec(
NAME "Clean_Setup_DBs"
COMMAND "cmake" "-E" "remove_directory" "${RESULTS_NSSDB_OUTPUT_DIR}"
)
jss_test_exec(
NAME "Create_Setup_DBs"
COMMAND "cmake" "-E" "make_directory" "${RESULTS_NSSDB_OUTPUT_DIR}"
DEPENDS "Clean_Setup_DBs"
)
jss_test_java(
NAME "Setup_DBs"
COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Create_Setup_DBs"
)
# Various FIPS related tests depend on FIPS being enabled; since this
# affects the entire NSS DB, create a separate database for them.
jss_test_exec(
NAME "Clean_FIPS_Setup_DBs"
COMMAND "cmake" "-E" "remove_directory" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}"
)
jss_test_exec(
NAME "Create_FIPS_Setup_DBs"
COMMAND "cmake" "-E" "make_directory" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}"
DEPENDS "Clean_FIPS_Setup_DBs"
)
jss_test_java(
NAME "Setup_FIPS_DBs"
COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Create_FIPS_Setup_DBs"
)
jss_test_java(
NAME "Test_UTF-8_Converter"
COMMAND "org.mozilla.jss.tests.UTF8ConverterTest"
......@@ -22,190 +72,189 @@ macro(jss_tests)
NAME "JSS_Test_Empty_DER_Value"
COMMAND "org.mozilla.jss.tests.EmptyDerValue"
)
jss_test_java(
NAME "BigObjectIdentifier"
COMMAND "org.mozilla.jss.tests.BigObjectIdentifier"
)
if ((${Java_VERSION_MAJOR} EQUAL 1) AND (${Java_VERSION_MINOR} LESS 9))
jss_test_java(
NAME "Test_PKCS11Constants.java_for_Sun_compatibility"
COMMAND "org.mozilla.jss.tests.TestPKCS11Constants"
)
endif()
# Rather than creating our results directories earlier in JSSConfig,
# create them here so that the test suite can be rerun multiple times.
jss_test_exec(
NAME "Clean_Setup_DBs"
COMMAND "cmake" "-E" "remove_directory" "${RESULTS_OUTPUT_DIR}"
jss_test_java(
NAME "JUnit_BMPStringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.BMPStringTest"
)
jss_test_exec(
NAME "Create_Setup_DBs"
COMMAND "cmake" "-E" "make_directory" "${RESULTS_OUTPUT_DIR}"
DEPENDS "Clean_Setup_DBs"
jss_test_java(
NAME "JUnit_IA5StringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.IA5StringTest"
)
jss_test_java(
NAME "Setup_DBs"
COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Create_Setup_DBs"
NAME "JUnit_PrintableStringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.PrintableStringTest"
)
# Various FIPS related tests depend on FIPS being enabled; since this
# affects the entire NSS DB, create a separate database for them.
jss_test_exec(
NAME "Clean_FIPS_Setup_DBs"
COMMAND "cmake" "-E" "remove_directory" "${RESULTS_FIPS_OUTPUT_DIR}"
jss_test_java(
NAME "JUnit_TeletexStringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.TeletexStringTest"
)
jss_test_exec(
NAME "Create_FIPS_Setup_DBs"
COMMAND "cmake" "-E" "make_directory" "${RESULTS_FIPS_OUTPUT_DIR}"
DEPENDS "Clean_FIPS_Setup_DBs"
jss_test_java(
NAME "JUnit_UniversalStringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UniversalStringTest"
)
jss_test_java(
NAME "Setup_FIPS_DBs"
COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Clean_FIPS_Setup_DBs"
NAME "JUnit_UTF8StringTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UTF8StringTest"
)
jss_test_java(
NAME "JUnit_ChainSortingTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.ChainSortingTest"
)
jss_test_java(
NAME "Generate_known_RSA_cert_pair"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}" "20" "localhost" "SHA-256/RSA" "CA_RSA" "Server_RSA" "Client_RSA"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "20" "localhost" "SHA-256/RSA" "CA_RSA" "Server_RSA" "Client_RSA"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Generate_known_ECDSA_cert_pair"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}" "30" "localhost" "SHA-256/EC" "CA_ECDSA" "Server_ECDSA" "Client_ECDSA"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "30" "localhost" "SHA-256/EC" "CA_ECDSA" "Server_ECDSA" "Client_ECDSA"
DEPENDS "Generate_known_RSA_cert_pair"
)
jss_test_java(
NAME "Generate_known_DSS_cert_pair"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}" "40" "localhost" "SHA-1/DSA" "CA_DSS" "Server_DSS" "Client_DSS"
COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "40" "localhost" "SHA-1/DSA" "CA_DSS" "Server_DSS" "Client_DSS"
DEPENDS "Generate_known_ECDSA_cert_pair"
)
jss_test_exec(
NAME "Create_PKCS11_cert_to_PKCS12_rsa.pfx"
COMMAND "pk12util" "-o" "${RESULTS_OUTPUT_DIR}/rsa.pfx" "-n" "CA_RSA" "-d" "${RESULTS_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/rsa.pfx" "-n" "CA_RSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
DEPENDS "Generate_known_RSA_cert_pair"
)
jss_test_exec(
NAME "Create_PKCS11_cert_to_PKCS12_ecdsa.pfx"
COMMAND "pk12util" "-o" "${RESULTS_OUTPUT_DIR}/ecdsa.pfx" "-n" "CA_ECDSA" "-d" "${RESULTS_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/ecdsa.pfx" "-n" "CA_ECDSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
DEPENDS "Generate_known_ECDSA_cert_pair"
)
jss_test_exec(
NAME "Create_PKCS11_cert_to_PKCS12_dss.pfx"
COMMAND "pk12util" "-o" "${RESULTS_OUTPUT_DIR}/dss.pfx" "-n" "CA_DSS" "-d" "${RESULTS_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/dss.pfx" "-n" "CA_DSS" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
DEPENDS "Generate_known_DSS_cert_pair"
)
jss_test_java(
NAME "List_CA_certs"
COMMAND "org.mozilla.jss.tests.ListCACerts" "${RESULTS_OUTPUT_DIR}"
COMMAND "org.mozilla.jss.tests.ListCACerts" "${RESULTS_NSSDB_OUTPUT_DIR}"
DEPENDS "Generate_known_DSS_cert_pair"
)
jss_test_java(
NAME "SSLClientAuth"
COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH}" "50"
COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH}" "50"
DEPENDS "List_CA_certs"
)
jss_test_java(
NAME "Key_Generation"
COMMAND "org.mozilla.jss.tests.TestKeyGen" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.TestKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Key_Factory"
COMMAND "org.mozilla.jss.tests.KeyFactoryTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.KeyFactoryTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Digest"
COMMAND "org.mozilla.jss.tests.DigestTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.DigestTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "HMAC"
COMMAND "org.mozilla.jss.tests.HMACTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.HMACTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "HMAC_Unwrap"
COMMAND "org.mozilla.jss.tests.HmacTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.HmacTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "KeyWrapping"
COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Mozilla_JSS_JCA_Signature"
COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Mozilla_JSS_NSS_Signature"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "JSS_Signature_test"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Secret_Decoder_Ring"
COMMAND "org.mozilla.jss.tests.TestSDR" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.TestSDR" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "List_cert_by_certnick"
COMMAND "org.mozilla.jss.tests.ListCerts" "${RESULTS_OUTPUT_DIR}" "Server_RSA"
COMMAND "org.mozilla.jss.tests.ListCerts" "${RESULTS_NSSDB_OUTPUT_DIR}" "Server_RSA"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Verify_cert_by_certnick"
COMMAND "org.mozilla.jss.tests.VerifyCert" "${RESULTS_OUTPUT_DIR}" "${PASSWORD_FILE}" "Server_RSA"
COMMAND "org.mozilla.jss.tests.VerifyCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "Server_RSA"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Secret_Key_Generation"
COMMAND "org.mozilla.jss.tests.SymKeyGen" "${RESULTS_OUTPUT_DIR}"
COMMAND "org.mozilla.jss.tests.SymKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}"
DEPENDS "Setup_DBs"
)
jss_test_java(
NAME "Mozilla_JSS_Secret_Key_Generation"
COMMAND "org.mozilla.jss.tests.JCASymKeyGen" "${RESULTS_OUTPUT_DIR}"
COMMAND "org.mozilla.jss.tests.JCASymKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}"
DEPENDS "Setup_DBs"
)
# FIPS-related tests
jss_test_java(
NAME "Enable_FipsMODE"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_FIPS_OUTPUT_DIR}" "enable"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "enable"
DEPENDS "Setup_FIPS_DBs"
)
jss_test_java(
NAME "check_FipsMODE"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_FIPS_OUTPUT_DIR}" "chkfips"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "chkfips"
DEPENDS "Enable_FipsMODE"
)
jss_test_java(
NAME "SSLClientAuth_FIPSMODE"
COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH_FIPS}" "60"
COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH_FIPS}" "60"
DEPENDS "Enable_FipsMODE"
)
jss_test_java(
NAME "HMAC_FIPSMODE"
COMMAND "org.mozilla.jss.tests.HMACTest" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.HMACTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Enable_FipsMODE"
)
jss_test_java(
NAME "KeyWrapping_FIPSMODE"
COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Enable_FipsMODE"
)
jss_test_java(
NAME "Mozilla_JSS_JCA_Signature_FIPSMODE"
COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Enable_FipsMODE"
)
jss_test_java(
NAME "JSS_Signature_test_FipsMODE"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}"
DEPENDS "Enable_FipsMODE"
)
......@@ -214,10 +263,27 @@ macro(jss_tests)
# FIPS-related checks.
jss_test_java(
NAME "Disable_FipsMODE"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_FIPS_OUTPUT_DIR}" "disable"
COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "disable"
DEPENDS "check_FipsMODE" "SSLClientAuth_FIPSMODE" "HMAC_FIPSMODE" "KeyWrapping_FIPSMODE" "Mozilla_JSS_JCA_Signature_FIPSMODE" "JSS_Signature_test_FipsMODE"
)
jss_test_java(
NAME "JUnit_GenericValueConverterTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.GenericValueConverterTest"
DEPENDS "Disable_FipsMODE"
)
jss_test_java(
NAME "JUnit_IA5StringConverterTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.IA5StringConverterTest"
DEPENDS "Disable_FipsMODE"
)
jss_test_java(
NAME "JUnit_PrintableConverterTest"
COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.PrintableConverterTest"
DEPENDS "Disable_FipsMODE"
)
# For compliance with several
add_custom_target(
check
......
......@@ -38,14 +38,17 @@ additional packages:
- [SLF4J's JDK14 package](https://www.slf4j.org/api/org/slf4j/impl/JDK14LoggerAdapter.html)
- [NSS's pk12util](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_pk12util)
- [JUnit 4](https://junit.org/junit4/)
- [Hamcrest](http://hamcrest.org/)
To install these dependencies on Fedora, execute the following:
sudo dnf install nss nss-tools slf4j-jdk14
sudo dnf install nss nss-tools slf4j-jdk14 hamcrest junit
To install these dependencies on Debian, execute the following:
sudo apt-get install libnss3 libnss3-tools libslf4j-java
sudo apt-get install libnss3 libnss3-tools libslf4j-java \
libhamcrest-java junit4
## Run-time Dependencies
......
......@@ -6,7 +6,7 @@ Summary: Java Security Services (JSS)
URL: http://www.dogtagpki.org/wiki/JSS
License: MPLv1.1 or GPLv2+ or LGPLv2+
Version: 4.5.1
Version: 4.5.3
Release: 1%{?_timestamp}%{?_commit_id}%{?dist}
# global _phase -a1
......@@ -38,8 +38,8 @@ BuildRequires: cmake
BuildRequires: gcc-c++
BuildRequires: nspr-devel >= 4.13.1
BuildRequires: nss-devel >= 3.28.4-6
BuildRequires: nss-tools >= 3.28.4-6
BuildRequires: nss-devel >= 3.30
BuildRequires: nss-tools >= 3.30
BuildRequires: java-devel
BuildRequires: jpackage-utils
BuildRequires: slf4j
......@@ -56,7 +56,10 @@ BuildRequires: apache-commons-codec
BuildRequires: perl-interpreter
%endif
Requires: nss >= 3.28.4-6
BuildRequires: junit
BuildRequires: hamcrest
Requires: nss >= 3.30
Requires: java-headless
Requires: jpackage-utils
Requires: slf4j
......@@ -116,7 +119,8 @@ rm -rf build && mkdir -p build && cd build
-DJAVA_LIB_INSTALL_DIR=%{_jnidir} \
..
%{__make} all test javadoc
%{__make} all javadoc
ctest --output-on-failure
################################################################################
%install
......
......@@ -7,7 +7,7 @@
#include <secmod.h>
#include <cert.h>
#include <certt.h>
#include <key.h>
#include <keyhi.h>
#include <ocsp.h>
#include <pk11func.h>
#include <nspr.h>
......
......@@ -10,7 +10,7 @@
#include <nspr.h>
#include <cert.h>
#include <certdb.h>
#include <key.h>
#include <keyhi.h>
#include <secpkcs7.h>
#include <jssutil.h>
......@@ -597,12 +597,12 @@ data_start(unsigned char *buf, int length, unsigned int *data_length,
*data_length = 0;
while (len_count-- > 0) {
while (len_count-- > 0 && used_length < length) {
*data_length = (*data_length << 8) | buf[used_length++];
}
}
if (*data_length > (length-used_length) ) {
if (*data_length > (unsigned)(length-used_length) ) {
*data_length = length-used_length;
return NULL;
}
......
......@@ -37,7 +37,7 @@
#include <pk11func.h>
#include <nspr.h>
#include <seccomon.h>
#include <key.h>
#include <keyhi.h>
#include <secitem.h>
#include <jssutil.h>
......
......@@ -10,6 +10,8 @@ import java.util.Hashtable;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
*
*/
......@@ -120,4 +122,31 @@ public class KeyWrapAlgorithm extends Algorithm {
public static final KeyWrapAlgorithm
AES_KEY_WRAP_PAD = new KeyWrapAlgorithm(CKM_NSS_AES_KEY_WRAP_PAD, "AES KeyWrap/Padding",
(Class<?>) null, true, 8);
// Known OIDs; copied from the CertUtil class from the
// com.netscape.cmsutil.crypto package of PKI.
public static final OBJECT_IDENTIFIER AES_KEY_WRAP_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.8");
public static final OBJECT_IDENTIFIER AES_CBC_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.2");
public static final OBJECT_IDENTIFIER DES3_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.2.840.113549.3.7");
// This OID does not come from CertUtil; it was added for completeness.
public static final OBJECT_IDENTIFIER DES_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.3.14.3.2.7");
public static KeyWrapAlgorithm fromOID(String wrapOID) throws NoSuchAlgorithmException {
OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER(wrapOID);
if (oid.equals(AES_KEY_WRAP_PAD_OID))
return AES_KEY_WRAP_PAD;
if (oid.equals(AES_CBC_PAD_OID))
return AES_CBC_PAD;
if (oid.equals(DES3_CBC_PAD_OID))
return DES3_CBC_PAD;
if (oid.equals(DES_CBC_PAD_OID))
return DES_CBC_PAD;
throw new NoSuchAlgorithmException("Unknown Algorithm for OID: " + wrapOID);
}
}
......@@ -9,7 +9,7 @@
#include <plarena.h>
#include <secitem.h>
#include <secoidt.h>
#include <keyt.h> /* for PQGParams */
#include <keythi.h> /* for PQGParams */
#include <pk11pqg.h>
#include <jss_bigint.h>
......
......@@ -26,16 +26,19 @@ import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.mozilla.jss.netscape.security.util.Cert;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.X500Name;
import org.mozilla.jss.netscape.security.x509.X500Signer;
import org.mozilla.jss.netscape.security.x509.X509Key;
import org.mozilla.jss.netscape.security.util.Utils;
/**
* PKCS #10 certificate requests are created and sent to Certificate
* Authorities, which then create X.509 certificates and return them to
......@@ -70,6 +73,9 @@ import org.mozilla.jss.netscape.security.util.Utils;
* @version 1.28
*/
public class PKCS10 {
public static Logger logger = LoggerFactory.getLogger(PKCS10.class);
/**
* Constructs an unsigned PKCS #10 certificate request. Before this
* request may be used, it must be encoded and signed. Then it
......@@ -122,12 +128,11 @@ public class PKCS10 {
byte sigData[];
Signature sig;
String method = "PKCS10: PKCS10: ";
String msg = "";
System.out.println(method + "begins");
logger.debug("PKCS10: begins");
if (data == null) {
throw new IllegalArgumentException(method + "param data cann't be null");
throw new IllegalArgumentException("Missing PKCS #10 data");
}
certificateRequest = data;
......@@ -138,11 +143,12 @@ public class PKCS10 {
in = new DerInputStream(data);
seq = in.getSequence(3);
if (seq == null) {
throw new IllegalArgumentException(method + "in.getSequence null");
throw new IllegalArgumentException("in.getSequence null");
}
if (seq.length != 3)
throw new IllegalArgumentException(method + "not a PKCS #10 request");
if (seq.length != 3) {
throw new IllegalArgumentException("Invalid PKCS #10 request");
}
data = seq[0].toByteArray(); // reusing this variable
certRequestInfo = seq[0].toByteArray(); // make a copy
......@@ -167,8 +173,8 @@ public class PKCS10 {
subjectPublicKeyInfo = X509Key.parse(new DerValue(val1));
PublicKey publicKey = X509Key.parsePublicKey(new DerValue(val1));
if (publicKey == null) {
System.out.println(method + msg + "publicKey null");
throw new SignatureException (method + msg + "publicKey null");
logger.error("PKCS10: " + msg + "publicKey null");
throw new SignatureException(msg + "publicKey null");
}
// Cope with a somewhat common illegal PKCS #10 format
......@@ -213,15 +219,15 @@ public class PKCS10 {
sig.initVerify(publicKey);
sig.update(data);
if (!sig.verify(sigData)) {
System.out.println(method + msg + "sig.verify() failed");
throw new SignatureException(method + msg + "Invalid PKCS #10 signature");
logger.error("PKCS10: " + msg + "sig.verify() failed");
throw new SignatureException(msg + "Invalid PKCS #10 signature");
}
}
} catch (InvalidKeyException e) {
System.out.println(method + msg + e.toString());
throw new SignatureException(method + msg + "invalid key");
logger.error("PKCS10: " + msg + e.getMessage());
throw new SignatureException(msg + "invalid key", e);
}
System.out.println(method + "ends");
logger.debug("PKCS10: ends");
}
public PKCS10(byte data[])
......@@ -336,9 +342,9 @@ public class PKCS10 {
if (certificateRequest == null)
throw new SignatureException("Cert request was not signed");
out.println("-----BEGIN NEW CERTIFICATE REQUEST-----");
out.println(Cert.REQUEST_HEADER);
out.println(Utils.base64encode(certificateRequest, true));
out.println("-----END NEW CERTIFICATE REQUEST-----");
out.println(Cert.REQUEST_FOOTER);
}
/**
......
......@@ -143,6 +143,7 @@ public class PKCS12 {
Map<BigInteger, PKCS12KeyInfo> keyInfosByID = new LinkedHashMap<BigInteger, PKCS12KeyInfo>();
Map<BigInteger, PKCS12CertInfo> certInfosByID = new LinkedHashMap<BigInteger, PKCS12CertInfo>();
Map<BigInteger, PKCS12CertInfo> certInfosByKeyID = new LinkedHashMap<BigInteger, PKCS12CertInfo>();
public PKCS12() {
}
......@@ -152,15 +153,15 @@ public class PKCS12 {
}
public void addKeyInfo(PKCS12KeyInfo keyInfo) {
keyInfosByID.put(keyInfo.id, keyInfo);
keyInfosByID.put(new BigInteger(1, keyInfo.getID()), keyInfo);
}
public PKCS12KeyInfo getKeyInfoByID(BigInteger id) {
return keyInfosByID.get(id);
public PKCS12KeyInfo getKeyInfoByID(byte[] id) {
return keyInfosByID.get(new BigInteger(1, id));
}
public PKCS12KeyInfo removeKeyInfoByID(BigInteger id) {
return keyInfosByID.remove(id);
public PKCS12KeyInfo removeKeyInfoByID(byte[] id) {
return keyInfosByID.remove(new BigInteger(1, id));
}
public Collection<PKCS12CertInfo> getCertInfos() {
......@@ -168,42 +169,57 @@ public class PKCS12 {
}
public void addCertInfo(PKCS12CertInfo certInfo, boolean replace) {
BigInteger id = certInfo.getID();
BigInteger id = new BigInteger(1, certInfo.getID());
if (!replace && certInfosByID.containsKey(id))
return;
certInfosByID.put(id, certInfo);
byte[] keyID = certInfo.getKeyID();
if (keyID == null) return;
certInfosByKeyID.put(new BigInteger(1, keyID), certInfo);
}
public PKCS12CertInfo getCertInfoByID(byte[] id) {
return certInfosByID.get(new BigInteger(1, id));
}
public PKCS12CertInfo getCertInfoByID(BigInteger id) {
return certInfosByID.get(id);
public PKCS12CertInfo getCertInfoByKeyID(byte[] keyID) {
return certInfosByKeyID.get(new BigInteger(1, keyID));
}
public Collection<PKCS12CertInfo> getCertInfosByNickname(String nickname) {
public Collection<PKCS12CertInfo> getCertInfosByFriendlyName(String friendlyName) {
Collection<PKCS12CertInfo> result = new ArrayList<PKCS12CertInfo>();
for (PKCS12CertInfo certInfo : certInfosByID.values()) {
if (!nickname.equals(certInfo.getNickname())) continue;
if (!friendlyName.equals(certInfo.getFriendlyName())) continue;
result.add(certInfo);
}
return result;
}
public void removeCertInfoByNickname(String nickname) throws Exception {
public void removeCertInfoByFriendlyName(String friendlyName) throws Exception {
Collection<PKCS12CertInfo> result = getCertInfosByNickname(nickname);
Collection<PKCS12CertInfo> result = getCertInfosByFriendlyName(friendlyName);
if (result.isEmpty()) {
throw new Exception("Certificate not found: " + nickname);
throw new Exception("Certificate not found: " + friendlyName);
}
for (PKCS12CertInfo certInfo : result) {
// remove cert and key
certInfosByID.remove(certInfo.getID());
keyInfosByID.remove(certInfo.getID());
BigInteger id = new BigInteger(1, certInfo.getID());
certInfosByID.remove(id);
byte[] keyID = certInfo.getKeyID();
if (keyID == null) continue;
certInfosByKeyID.remove(new BigInteger(1, keyID));
keyInfosByID.remove(new BigInteger(1, keyID));
}
}
}
......@@ -17,25 +17,24 @@
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.math.BigInteger;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
public class PKCS12CertInfo {
BigInteger id;
X509CertImpl cert;
String nickname;
String trustFlags;
private byte[] id;
private X509CertImpl cert;
private String friendlyName;
private String trustFlags;
private byte[] keyID;
public PKCS12CertInfo() {
}
public BigInteger getID() {
public byte[] getID() {
return id;
}
public void setID(BigInteger id) {
public void setID(byte[] id) {
this.id = id;
}
......@@ -47,12 +46,12 @@ public class PKCS12CertInfo {
this.cert = cert;
}
public String getNickname() {
return nickname;
public String getFriendlyName() {
return friendlyName;
}
public void setNickname(String nickname) {
this.nickname = nickname;
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
public String getTrustFlags() {
......@@ -62,4 +61,12 @@ public class PKCS12CertInfo {
public void setTrustFlags(String trustFlags) {
this.trustFlags = trustFlags;
}
public byte[] getKeyID() {
return keyID;
}
public void setKeyID(byte[] keyID) {
this.keyID = keyID;
}
}
......@@ -17,8 +17,6 @@
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.math.BigInteger;
import org.mozilla.jss.crypto.PrivateKey;
/**
......@@ -36,8 +34,8 @@ public class PKCS12KeyInfo {
private PrivateKey privateKey;
private byte[] epkiBytes;
BigInteger id;
String subjectDN;
private byte[] id;
private String friendlyName;
public PKCS12KeyInfo() {
}
......@@ -66,19 +64,19 @@ public class PKCS12KeyInfo {
return epkiBytes;
}
public BigInteger getID() {
public byte[] getID() {
return id;
}
public void setID(BigInteger id) {
public void setID(byte[] id) {
this.id = id;
}
public String getSubjectDN() {
return subjectDN;
public String getFriendlyName() {
return friendlyName;
}
public void setSubjectDN(String subjectDN) {
this.subjectDN = subjectDN;
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
}
......@@ -21,18 +21,31 @@ import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.netscape.security.pkcs.PKCS7;
import org.mozilla.jss.netscape.security.x509.X509CRLImpl;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Cert {
private static Logger logger = LoggerFactory.getLogger(Cert.class);
public static final String HEADER = "-----BEGIN CERTIFICATE-----";
public static final String FOOTER = "-----END CERTIFICATE-----";
public static final String PKCS7_HEADER = "-----BEGIN PKCS7-----";
public static final String PKCS7_FOOTER = "-----END PKCS7-----";
// From https://www.rfc-editor.org/rfc/rfc7468.txt
public static final String REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
public static final String REQUEST_FOOTER = "-----END CERTIFICATE REQUEST-----";
......@@ -68,9 +81,12 @@ public class Cert {
return s;
}
if ((s.startsWith(HEADER)) &&
(s.endsWith(FOOTER))) {
return (s.substring(27, (s.length() - 25)));
if (s.startsWith(HEADER) && s.endsWith(FOOTER)) {
return s.substring(HEADER.length(), s.length() - FOOTER.length());
}
if (s.startsWith(PKCS7_HEADER) && s.endsWith(PKCS7_FOOTER)) {
return s.substring(PKCS7_HEADER.length(), s.length() - PKCS7_FOOTER.length());
}
// To support Thawte's header and footer
......@@ -198,4 +214,131 @@ public class Cert {
String b64 = stripBrackets(encoded);
return Utils.base64decode(b64);
}
/**
* Sorts certificate chain from root to leaf.
*
* This method sorts an array of certificates (e.g. from a PKCS #7
* data) that represents a certificate chain from root to leaf
* according to the subject DNs and issuer DNs.
*
* The input array is a set of certificates that are part of a
* chain but not in specific order.
*
* The result is a new array that contains the certificate chain
* sorted from root to leaf. The input array is unchanged.
*
* @param certs input array of certificates
* @return new array containing sorted certificates
*/
public static java.security.cert.X509Certificate[] sortCertificateChain(java.security.cert.X509Certificate[] certs) throws Exception {
if (certs == null) {
return null;
}
if (certs.length == 0) {
return certs;
}
// lookup map: subject DN -> cert
Map<String, java.security.cert.X509Certificate> certMap = new LinkedHashMap<>();
// hierarchy map: subject DN -> issuer DN
Map<String, String> parentMap = new HashMap<>();
// reverse hierarchy map: issuer DN -> subject DN
Map<String, String> childMap = new HashMap<>();
// build maps
for (java.security.cert.X509Certificate cert : certs) {
String subjectDN = cert.getSubjectDN().toString();
String issuerDN = cert.getIssuerDN().toString();
if (certMap.containsKey(subjectDN)) {
throw new Exception("Duplicate certificate: " + subjectDN);
}
certMap.put(subjectDN, cert);
// ignore self-signed certificate
if (subjectDN.equals(issuerDN)) continue;
if (childMap.containsKey(issuerDN)) {
throw new Exception("Branched chain: " + issuerDN);
}
parentMap.put(subjectDN, issuerDN);
childMap.put(issuerDN, subjectDN);
}
if (logger.isDebugEnabled()) {
logger.debug("Certificates:");
for (String subjectDN : certMap.keySet()) {
logger.debug(" - " + subjectDN);
String parent = parentMap.get(subjectDN);
if (parent != null) logger.debug(" parent: " + parent);
String child = childMap.get(subjectDN);
if (child != null) logger.debug(" child: " + child);
}
}
// find leaf cert by removing certs that has a child
List<String> leafCerts = new ArrayList<>();
leafCerts.addAll(certMap.keySet());
leafCerts.removeAll(childMap.keySet());
if (leafCerts.isEmpty()) {
throw new Exception("Unable to find leaf certificate");
}
if (leafCerts.size() > 1) {
StringBuilder sb = new StringBuilder();
for (String subjectDN : leafCerts) {
if (sb.length() > 0) sb.append(", ");
sb.append("[" + subjectDN + "]");
}
throw new Exception("Multiple leaf certificates: " + sb);
}
// build sorted chain
LinkedList<java.security.cert.X509Certificate> chain = new LinkedList<>();
// start from leaf
String current = leafCerts.get(0);
while (current != null) {
java.security.cert.X509Certificate cert = certMap.get(current);
if (cert == null) {
// incomplete chain
break;
}
// add to the beginning of chain
chain.addFirst(cert);
// follow parent to root
current = parentMap.get(current);
}
return chain.toArray(new java.security.cert.X509Certificate[chain.size()]);
}
public static java.security.cert.X509Certificate[] sortCertificateChain(
java.security.cert.X509Certificate[] certs,
boolean reverse) throws Exception {
certs = sortCertificateChain(certs);
if (reverse) {
ArrayUtils.reverse(certs);
}
return certs;
}
}