Skip to content
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

Add fake mapping from JKS/PKCS12 KeyStore to WKS for FIPS Compliance #83

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected void onCreate(Bundle savedInstanceState) {
public void testFindProvider(TextView tv)
throws NoSuchProviderException, NoSuchAlgorithmException {

Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
if (p == null) {
Expand Down
34 changes: 34 additions & 0 deletions README_JCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,40 @@ file for JCE provider customization:
| --- | --- | --- | --- |
| wolfjce.wks.iterationCount | 210,000 | Numeric | PBKDF2 iteration count (10,000 minimum) |
| wolfjce.wks.maxCertChainLength | 100 | Integer | Max cert chain length |
| wolfjce.mapJKStoWKS | UNSET | true | Register fake JKS KeyStore service mapped to WKS |
| wolfjce.mapPKCS12toWKS | UNSET | true | Register fake PKCS12 KeyStore service mapped to WKS |

**wolfjce.mapJKStoWKS** - this Security property should be used with caution.
When enabled, this will register a "JKS" KeyStore type in wolfJCE, which means
calling applications using `KeyStore.getInstance("JKS")` will get a KeyStore
implementation from wolfJCE. BUT, this KeyStore type will actually be a
WolfSSLKeyStore (WKS) type internally. Loading actual JKS files will fail.
This can be helpful when FIPS compliance is required, but existing code gets
a JKS KeyStore instance - and this assumes the caller has the flexibility to
actually load a real WKS KeyStore file into this KeyStore object. If this
property is being set at runtime programatically, the wolfJCE provider services
will need to be refreshed / reloaded, by doing:

```
WolfCryptProvider prov = (WolfCryptProvider)Security.getProvider("wolfJCE");
prov.refreshServices();
```

**wolfjce.mapPKCS12toWKS** - this Security property should be used with caution.
When enabled, this will register a "PKCS12" KeyStore type in wolfJCE, which
means calling applications using `KeyStore.getInstance("PKCS12")` will get a
KeyStore implementation from wolfJCE. BUT, this KeyStore type will actually be a
WolfSSLKeyStore (WKS) type internally. Loading actual PKCS12 files will fail.
This can be helpful when FIPS compliance is required, but existing code gets
a PKCS12 KeyStore instance - and this assumes the caller has the flexibility to
actually load a real WKS KeyStore file into this KeyStore object. If this
property is being set at runtime programatically, the wolfJCE provider services
will need to be refreshed / reloaded, by doing:

```
WolfCryptProvider prov = (WolfCryptProvider)Security.getProvider("wolfJCE");
prov.refreshServices();
```

#### System Property Support

Expand Down
Binary file added examples/certs/client.p12
Binary file not shown.
62 changes: 33 additions & 29 deletions examples/certs/update-jks-wks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ CERT_LOCATION=$1
export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH

# ARGS: <keystore-name> <cert file> <alias> <password>
# ARGS: <keystore-name> <keystore-type> <cert file> <alias> <password>
add_cert() {
keytool -import -keystore "$1" -file "$CERT_LOCATION/$2" -alias "$3" -noprompt -trustcacerts -deststoretype JKS -storepass "$4" &> /dev/null
keytool -import -keystore "$1" -file "$CERT_LOCATION/$3" -alias "$4" -noprompt -trustcacerts -deststoretype "$2" -storepass "$5" &> /dev/null
if [ $? -ne 0 ]; then
printf "fail"
exit 1
fi
}

# ARGS: <keystore-name> <cert file> <key file> <alias> <password>
# ARGS: <keystore-name> <keystore-type> <cert file> <key file> <alias> <password>
add_cert_key() {
openssl pkcs12 -export -in "$CERT_LOCATION/$2" -inkey "$CERT_LOCATION/$3" -out tmp.p12 -passin pass:"$5" -passout pass:"$5" -name "$4" &> /dev/null
keytool -importkeystore -deststorepass "$5" -destkeystore "$1" -deststoretype JKS -srckeystore tmp.p12 -srcstoretype PKCS12 -srcstorepass "$5" -alias "$4" &> /dev/null
openssl pkcs12 -export -in "$CERT_LOCATION/$3" -inkey "$CERT_LOCATION/$4" -out tmp.p12 -passin pass:"$6" -passout pass:"$6" -name "$5" &> /dev/null
keytool -importkeystore -deststorepass "$6" -destkeystore "$1" -deststoretype "$2" -srckeystore tmp.p12 -srcstoretype PKCS12 -srcstorepass "$6" -alias "$5" &> /dev/null
if [ $? -ne 0 ]; then
printf "fail"
exit 1
Expand All @@ -85,100 +85,104 @@ jks_to_wks() {
# Client cert: both RSA 2048-bit and ECC
printf "\tCreating client.jks ..."
rm client.jks &> /dev/null
add_cert_key "client.jks" "/client-cert.pem" "/client-key.pem" "client" "wolfsslpassword"
add_cert_key "client.jks" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
add_cert_key "client.jks" "JKS" "/client-cert.pem" "/client-key.pem" "client" "wolfsslpassword"
add_cert_key "client.jks" "JKS" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
printf "done\n"

printf "\tCreating client.p12 ..."
rm client.p12 &> /dev/null
add_cert_key "client.p12" "PKCS12" "/client-cert.pem" "/client-key.pem" "client" "wolfsslpassword"
add_cert_key "client.p12" "PKCS12" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
printf "done\n"

# Client cert: RSA, 1024-bit only
printf "\tCreating client-rsa-1024.jks ..."
rm client-rsa-1024.jks &> /dev/null
add_cert_key "client-rsa-1024.jks" "/1024/client-cert.pem" "/1024/client-key.pem" "client-rsa-1024" "wolfsslpassword"
add_cert_key "client-rsa-1024.jks" "JKS" "/1024/client-cert.pem" "/1024/client-key.pem" "client-rsa-1024" "wolfsslpassword"
printf "done\n"

# Client cert: RSA 2048-bit only
printf "\tCreating client-rsa.jks ..."
rm client-rsa.jks &> /dev/null
add_cert_key "client-rsa.jks" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
add_cert_key "client-rsa.jks" "JKS" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
printf "done\n"

# Client cert: ECC only
printf "\tCreating client-ecc.jks ..."
rm client-ecc.jks &> /dev/null
add_cert_key "client-ecc.jks" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
add_cert_key "client-ecc.jks" "JKS" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
printf "done\n"

#################### SERVER KEYSTORES ####################

# Server cert: both RSA 2048-bit and ECC
printf "\tCreating server.jks ..."
rm server.jks &> /dev/null
add_cert_key "server.jks" "/server-cert.pem" "/server-key.pem" "server" "wolfsslpassword"
add_cert_key "server.jks" "/server-ecc.pem" "/ecc-key.pem" "server-ecc" "wolfsslpassword"
add_cert_key "server.jks" "JKS" "/server-cert.pem" "/server-key.pem" "server" "wolfsslpassword"
add_cert_key "server.jks" "JKS" "/server-ecc.pem" "/ecc-key.pem" "server-ecc" "wolfsslpassword"
printf "done\n"

# Server cert: RSA, 1024-bit only
printf "\tCreating server-rsa-1024.jks ..."
rm server-rsa-1024.jks &> /dev/null
add_cert_key "server-rsa-1024.jks" "/1024/server-cert.pem" "/1024/server-key.pem" "server-1024" "wolfsslpassword"
add_cert_key "server-rsa-1024.jks" "JKS" "/1024/server-cert.pem" "/1024/server-key.pem" "server-1024" "wolfsslpassword"
printf "done\n"

# Server cert: RSA, 2048-bit only
printf "\tCreating server-rsa.jks ..."
rm server-rsa.jks &> /dev/null
add_cert_key "server-rsa.jks" "/server-cert.pem" "/server-key.pem" "server-rsa" "wolfsslpassword"
add_cert_key "server-rsa.jks" "JKS" "/server-cert.pem" "/server-key.pem" "server-rsa" "wolfsslpassword"
printf "done\n"

# Server cert: ECC only
printf "\tCreating server-ecc.jks ..."
rm server-ecc.jks &> /dev/null
add_cert_key "server-ecc.jks" "/server-ecc.pem" "/ecc-key.pem" "server-ecc" "wolfsslpassword"
add_cert_key "server-ecc.jks" "JKS" "/server-ecc.pem" "/ecc-key.pem" "server-ecc" "wolfsslpassword"
printf "done\n"

#################### CA CERT KEYSTORES ###################

# Contains all CA certs (RSA and ECC), verifies both client and server certs
printf "\tCreating cacerts.jks ..."
rm cacerts.jks &> /dev/null
add_cert_key "cacerts.jks" "/ca-cert.pem" "/ca-key.pem" "cacert" "wolfsslpassword"
add_cert_key "cacerts.jks" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
add_cert_key "cacerts.jks" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
add_cert_key "cacerts.jks" "/ca-cert.pem" "/ca-key.pem" "ca-rsa" "wolfsslpassword"
add_cert_key "cacerts.jks" "/ca-ecc-cert.pem" "/ca-ecc-key.pem" "ca-ecc" "wolfsslpassword"
add_cert_key "cacerts.jks" "/1024/ca-cert.pem" "/1024/ca-key.pem" "ca-1024" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/ca-cert.pem" "/ca-key.pem" "cacert" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/ca-cert.pem" "/ca-key.pem" "ca-rsa" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/ca-ecc-cert.pem" "/ca-ecc-key.pem" "ca-ecc" "wolfsslpassword"
add_cert_key "cacerts.jks" "JKS" "/1024/ca-cert.pem" "/1024/ca-key.pem" "ca-1024" "wolfsslpassword"
printf "done\n"

# Contains CA certs used to verify client certs:
# client-cert.pem verifies itself (self signed)
# client-ecc-cert.pem verifies itself (self signed)
printf "\tCreating ca-client.jks ..."
rm ca-client.jks &> /dev/null
add_cert_key "ca-client.jks" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
add_cert_key "ca-client.jks" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
add_cert_key "ca-client.jks" "JKS" "/client-cert.pem" "/client-key.pem" "client-rsa" "wolfsslpassword"
add_cert_key "ca-client.jks" "JKS" "/client-ecc-cert.pem" "/ecc-client-key.pem" "client-ecc" "wolfsslpassword"
printf "done\n"

# Contains CA certs used to verify server certs:
# ca-cert.pem verifies server-cert.pem
# ca-ecc-cert.pem verifies server-ecc.pem
printf "\tCreating ca-server.jks ..."
rm ca-server.jks &> /dev/null
add_cert_key "ca-server.jks" "/ca-cert.pem" "/ca-key.pem" "ca-rsa" "wolfsslpassword"
add_cert_key "ca-server.jks" "/ca-ecc-cert.pem" "/ca-ecc-key.pem" "ca-ecc" "wolfsslpassword"
add_cert_key "ca-server.jks" "JKS" "/ca-cert.pem" "/ca-key.pem" "ca-rsa" "wolfsslpassword"
add_cert_key "ca-server.jks" "JKS" "/ca-ecc-cert.pem" "/ca-ecc-key.pem" "ca-ecc" "wolfsslpassword"
printf "done\n"

# Contains CA cert used to verify RSA 2048-bit server cert:
# ca-cert.pem verifies server-cert.pem
printf "\tCreating ca-server-rsa-2048.jks ..."
rm ca-server-rsa-2048.jks &> /dev/null
#add_cert_key "ca-server-rsa-2048.jks" "/ca-cert.pem" "/ca-key.pem" "ca-rsa" "wolfsslpassword"
add_cert "ca-server-rsa-2048.jks" "/ca-cert.pem" "ca-rsa" "wolfsslpassword"
add_cert "ca-server-rsa-2048.jks" "JKS" "/ca-cert.pem" "ca-rsa" "wolfsslpassword"
printf "done\n"

# Contains CA cert used to verify ECC P-256 server cert:
# ca-ecc-cert.pem verifies server-ecc.pem
printf "\tCreating ca-server-ecc-256.jks ..."
rm ca-server-ecc-256.jks &> /dev/null
#add_cert_key "ca-server-ecc-256.jks" "/ca-ecc-cert.pem" "/ca-ecc-key.pem" "ca-ecc" "wolfsslpassword"
add_cert "ca-server-ecc-256.jks" "/ca-ecc-cert.pem" "ca-ecc" "wolfsslpassword"
add_cert "ca-server-ecc-256.jks" "JKS" "/ca-ecc-cert.pem" "ca-ecc" "wolfsslpassword"
printf "done\n"

################### CONVERT JKS TO WKS ###################
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package com.wolfssl.provider.jce;

import java.security.Provider;
import java.security.Security;
import com.wolfssl.wolfcrypt.FeatureDetect;
import com.wolfssl.wolfcrypt.Fips;

Expand All @@ -37,6 +38,27 @@ public final class WolfCryptProvider extends Provider {
*/
public WolfCryptProvider() {
super("wolfJCE", 1.7, "wolfCrypt JCE Provider");
registerServices();
}

/**
* Refresh the services provided by this JCE provider.
*
* This is required when one of the Security properties has been changed
* that affect the services offered by this provider. For example:
* wolfjce.mapJKStoWKS
* wolfjce.mapPKCS12toWKS
*/
public void refreshServices() {
registerServices();
}

/**
* Register services provided by wolfJCE, called by class constructor.
*/
private void registerServices() {
String mapJksToWks = null;
String mapPkcs12ToWks = null;

/* MessageDigest */
if (FeatureDetect.Md5Enabled()) {
Expand Down Expand Up @@ -222,6 +244,32 @@ public WolfCryptProvider() {
put("KeyStore.WKS",
"com.wolfssl.provider.jce.WolfSSLKeyStore");

/* Fake mapping of JKS to WKS type. Use with caution! This is
* usually used when FIPS compliance is needed but code cannot be
* changed that creates a JKS KeyStore object type. Any files loaded
* into this fake JKS KeyStore MUST be of actual type WKS or failures
* will happen. Remove service first here in case of refresh. */
remove("KeyStore.JKS");
mapJksToWks = Security.getProperty("wolfjce.mapJKStoWKS");
if (mapJksToWks != null && !mapJksToWks.isEmpty() &&
mapJksToWks.equalsIgnoreCase("true")) {
put("KeyStore.JKS",
"com.wolfssl.provider.jce.WolfSSLKeyStore");
}

/* Fake mapping of PKCS12 to WKS type. Use with caution! This is
* usually used when FIPS compliance is needed but code cannot be
* changed that creates a JKS KeyStore object type. Any files loaded
* into this fake JKS KeyStore MUST be of actual type WKS or failures
* will happen. Remove service first here in case of refresh. */
remove("KeyStore.PKCS12");
mapPkcs12ToWks = Security.getProperty("wolfjce.mapPKCS12toWKS");
if (mapPkcs12ToWks != null && !mapPkcs12ToWks.isEmpty() &&
mapPkcs12ToWks.equalsIgnoreCase("true")) {
put("KeyStore.PKCS12",
"com.wolfssl.provider.jce.WolfSSLKeyStore");
}

/* If using a FIPS version of wolfCrypt, allow private key to be
* exported for use. Only applicable to FIPS 140-3 */
if (Fips.enabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public static void testProviderInstallationAtRuntime() {
System.out.println("JCE WolfCryptKeyAgreementTest Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMac Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMessageDigestMd5Test");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMessageDigestSha256 Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMessageDigestSha384 Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMessageDigestSha512 Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptMessageDigestSha Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static void testProviderInstallationAtRuntime()
/* Install wolfJCE provider at runtime. Not registering as top priority
* provider so we can still likely get SunJCE or platform provider
* when not specifying wolfJCE explicitly. */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider(provider);
assertNotNull(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static void testProviderInstallationAtRuntime()
System.out.println("JCE WolfCryptSignature Class");

/* install wolfJCE provider at runtime */
Security.addProvider(new WolfCryptProvider());
Security.insertProviderAt(new WolfCryptProvider(), 1);

Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
Expand Down
Loading