

# Advanced configurations for AWS CloudHSM JCE for Client SDK 5
<a name="java-lib-configs"></a>

The AWS CloudHSM JCE provider includes the following advanced configurations, which are not part of the general configurations most customers utilize.
+ [Connecting to multiple clusters](java-lib-configs-multi.md)
+ [Key extraction using JCE](java-lib-configs-getencoded.md)
+ [Retry configuration for JCE](java-lib-configs-retry.md)

# Connecting to multiple AWS CloudHSM clusters with the JCE provider
<a name="java-lib-configs-multi"></a>

This configuration allows a single client instance to communicate to multiple AWS CloudHSM clusters. Compared to having a single instance only communicate with a single cluster, this can be a cost-savings feature for some use cases. The `CloudHsmProvider` class is AWS CloudHSM's implementation of [Java Security's Provider class](https://docs.oracle.com/javase/8/docs/api/java/security/Provider.html). Each instance of this class represents a connection to your entire AWS CloudHSM cluster. You instantiate this class and add it to Java Security provider's list so that you can interact with it using standard JCE classes.

The following example instantiates this class and adds it to Java Security provider’s list:

```
if (Security.getProvider(CloudHsmProvider.PROVIDER_NAME) == null) {
    Security.addProvider(new CloudHsmProvider());
}
```

`CloudHsmProvider` can be configured in two ways:

1. Configure with file (default configuration)

1. Configure using code

The following topics describe these configurations, and how to connect to multiple clusters.

**Topics**
+ [Configure the AWS CloudHSM `CloudHsmProvider` class with a file (Default configuration)](java-lib-configs-default.md)
+ [Configure the AWS CloudHSM `CloudHsmProvider` class using code](java-lib-configs-using-code.md)
+ [Connect to multiple AWS CloudHSM clusters](java-lib-connecting-to-multiclusters.md)

# Configure the AWS CloudHSM `CloudHsmProvider` class with a file (Default configuration)
<a name="java-lib-configs-default"></a>

The default way to configure the AWS CloudHSM `CloudHsmProvider` class is with a file.

When you instantiate `CloudHsmProvider` using default constructor, by default it will look for configuration file in `/opt/cloudhsm/etc/cloudhsm-jce.cfg` path in Linux. This configuration file can be configured using the `configure-jce`. 

An object created using the default constructor will use the default CloudHSM provider name `CloudHSM`. The provider name is useful to interact with JCE to let it know which provider to use for various operation. An example to use CloudHSM provider name for Cipher operation is as below:

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "CloudHSM");
```

# Configure the AWS CloudHSM `CloudHsmProvider` class using code
<a name="java-lib-configs-using-code"></a>

As of Client SDK version 5.8.0, you can also configure the AWS CloudHSM `CloudHsmProvider` class using Java code. The way to do this is using an object of `CloudHsmProviderConfig` class. You can build this object using `CloudHsmProviderConfigBuilder`. 

`CloudHsmProvider` has another constructor which takes the `CloudHsmProviderConfig` object, as the following sample shows.

**Example**  

```
CloudHsmProviderConfig config = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath)
                                            .withClusterUniqueIdentifier("CloudHsmCluster1")
        .withServer(CloudHsmServer.builder().withHostIP(hostName).build())  
                        .build())  
        .build();
CloudHsmProvider provider = new CloudHsmProvider(config);
```

In this example, the name of the JCE provider is `CloudHsmCluster1`. This is the name that application can then use to interact with JCE:

**Example**  

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "CloudHsmCluster1");
```

Alternatively, applications can also use the provider object created above to let JCE know to use that provider for the operation:

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider);
```

If a unique identifier is not specified with the `withClusterUniqueIdentifier` method, a randomly generated provider name is created for you. To get this randomly generated identifier, applications can call `provider.getName()` to get the identifier.

# Connect to multiple AWS CloudHSM clusters
<a name="java-lib-connecting-to-multiclusters"></a>

Each `CloudHsmProvider` represents a connection to your AWS CloudHSM Cluster. If you want to talk to another cluster from the same application, you can create another object of `CloudHsmProvider` with configurations for your other cluster and you can interact with this other cluster either using the provider object or using the provider name, as shown in the following example.

**Example**  

```
CloudHsmProviderConfig config = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath)
                                            .withClusterUniqueIdentifier("CloudHsmCluster1")
        .withServer(CloudHsmServer.builder().withHostIP(hostName).build())  
                        .build())  
        .build();
CloudHsmProvider provider1 = new CloudHsmProvider(config);

if (Security.getProvider(provider1.getName()) == null) {
    Security.addProvider(provider1);
}

CloudHsmProviderConfig config2 = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath2)
                                            .withClusterUniqueIdentifier("CloudHsmCluster2")
        .withServer(CloudHsmServer.builder().withHostIP(hostName2).build())  
                        .build())  
        .build();
CloudHsmProvider provider2 = new CloudHsmProvider(config2);

if (Security.getProvider(provider2.getName()) == null) {
    Security.addProvider(provider2);
}
```

Once you have configured both the providers (both the clusters) above, you can interact with them either using the provider object or using the provider name. 

Expanding upon this example that shows how to talk to `cluster1`, you could use the following sample for a AES/GCM/NoPadding operation:

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider1);
```

And in the same application to do "AES" Key generation on the second cluster using the provider name, you could also use the following sample:

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider2.getName());
```

# Key extraction using JCE for AWS CloudHSM
<a name="java-lib-configs-getencoded"></a>

The Java Cryptography Extension (JCE) uses an architecture that allows different cryptography implementations to be plugged in. AWS CloudHSM ships one such JCE provider that offloads cryptographic operations to the HSM. For most other JCE providers to work with keys stored in AWS CloudHSM, they must extract the key bytes from your HSMs in clear text into your machine’s memory for their use. HSMs typically only allow keys to be extracted as wrapped objects, not clear text. However, to support inter-provider integration use cases, AWS CloudHSM allows an opt-in configuration option to enable extraction of the key bytes in the clear.

**Important**  
JCE offloads operations to AWS CloudHSM whenever the AWS CloudHSM provider is specified or an AWS CloudHSM key object is used. You do not need to extract keys in clear if you expect your operation to happen inside the HSM. Key extraction in clear text is only needed when your application cannot use secure mechanisms such as wrapping and unwrapping a key due to restrictions from a third party library or JCE provider. 

The AWS CloudHSM JCE Provider allows extraction of **public keys** to work with external JCE providers by default. The following methods are always allowed:


| Class | Method | Format (getEncoded) | 
| --- | --- | --- | 
| EcPublicKey | getEncoded() | X.509 | 
|  | getW() | N/A | 
| RSAPublicKey | getEncoded() | X.509 | 
|  | getPublicExponent() | N/A | 
| CloudHsmRsaPrivateCrtKey | getPublicExponent() | N/A | 

The AWS CloudHSM JCE Provider doesn’t allow extraction of key bytes in clear for the **private** or **secret** keys by default. If your use case requires it, you can enable extraction of key bytes in clear for **private** or **secret** keys under the following conditions:

1. The `EXTRACTABLE` attribute for private and secret keys is set to **true**.
   + By default, the `EXTRACTABLE` attribute for private and secret keys is set to **true**. `EXTRACTABLE` keys are keys that are permitted to be exported out of the HSM. For more information see Supported Java attributes for [Client SDK 5](java-lib-attributes_5.md).

1. The `WRAP_WITH_TRUSTED` attribute for the private and secret keys is set to **false**.
   + `getEncoded`, `getPrivateExponent`, and `getS` cannot be used with private keys that cannot be exported in clear. `WRAP_WITH_TRUSTED` doesn't allow your private keys to exported out of the HSM in clear. For more information see [Using trusted keys to control key unwraps](manage-keys-using-trusted-keys.md).

# Allow the JCE provider to extract private key secrets out of AWS CloudHSM
<a name="get-encoded-take-out-private-keys"></a>

Use the following steps to allow AWS CloudHSM JCE provider to extract your private key secrets.

**Important**  
This configuration change allows extraction of all `EXTRACTABLE` key bytes in clear from your HSM cluster. For better security, you should consider using [key wrapping methods](java-lib-supported_5.md) to extract the key out of the HSM securely. This prevents unintentional extraction of your key bytes from the HSM. 

1. Use the following commands to enable your **private** or **secret** keys to be extracted in JCE:

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/configure-jce --enable-clear-key-extraction-in-software
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --enable-clear-key-extraction-in-software
   ```

------

1. Once you enable your clear key extraction, the following methods are enabled for extracting private keys into memory.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/get-encoded-take-out-private-keys.html)

If you want restore the default behavior and not allow JCE to export keys in clear, run the following command:

------
#### [ Linux ]

```
$ /opt/cloudhsm/bin/configure-jce --disable-clear-key-extraction-in-software
```

------
#### [ Windows ]

```
PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --disable-clear-key-extraction-in-software
```

------

# Retry commands for JCE for AWS CloudHSM
<a name="java-lib-configs-retry"></a>

AWS CloudHSM Client SDK 5.8.0 and later have a built-in automatic retry strategy which will retry HSM-throttled operations from the client side. When an HSM throttles operations because it is too busy performing previous operations and cannot take more requests, client SDKs will attempt to retry throttled operations up to 3 times while exponentially backing off. This automatic retry strategy can be set to one of two modes: **off** and **standard**.
+ **off**: The Client SDK will not perform any retry strategy for any throttled operations by the HSM.
+ **standard**: This is the default mode for Client SDK 5.8.0 and later. In this mode, client SDKs will automatically retry throttled operations by exponentially backing off.

For more information, see [HSM throttling](troubleshoot-hsm-throttling.md).

## Set retry commands to off mode
<a name="w2aac25c21c25c25c15b9"></a>

------
#### [ Linux ]

**To set retry commands to **off** for Client SDK 5 on Linux**
+ You can use the following command to set retry configuration to **off** mode:

  ```
  $ sudo /opt/cloudhsm/bin/configure-jce --default-retry-mode off
  ```

------
#### [ Windows ]

**To set retry commands to **off** for Client SDK 5 on Windows**
+ You can use the following command to set retry configuration to **off** mode:

  ```
  PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --default-retry-mode off
  ```

------