A Hardware Security Module (HSM) is a tamper-resistant, security-hardened device used to ensure the integrity of cryptographic operations. HSMs generate, protect, and manage keys used for encrypting data. They also create and preserve digital signatures and facilitate certificate management. HSMs provide a secure environment to perform cryptographic operations that are certified to meet FIPS and Common Criteria standards. Read on to understand how to use an HSM to achieve higher levels of data security and trust in ToxSec’s HSM Crash Course.
Why use an HSM?
Hardware Security Modules enhance the security of cryptographic operations. When using software-based solutions, there are intrinsic risks. When keys are generated or used on devices, they will be in clear text on disc or in memory during critical use. For a public key infrastructure (PKI) to work, symmetric and private keys should never be revealed. Having keys visible in memory creates unnecessary risk. With this in mind, HSMs create secure boundaries which never expose keys in the clear. HSMs generate keys using modules specifically designed for the task. As a result, sensitive key data exists only in the device’s physically and logically protected hardware. Further, because access to keys and the HSM itself can be restricted, the integrity of the data stored within the device is better managed.
Heartbleed
An example of exposing sensitive information from a software-based solution is the Heartbleed attack on OpenSSL. OpenSSL is a software library for applications to use when implementing HTTPS. The CVE-2014-0160 vulnerability is a serious flaw that allows an attacker to steal protected information. This exploit enables an attacker to read a system’s active memory. To this end, the attack compromises the secret keys used to encrypt traffic. Accordingly, the attack exposes user data, including passwords and page content. By protecting TLS/SSL keys with an HSM, you can prevent attacks such as Heartbleed from affecting your services.
What are HSMs used for?
HSMs have a myriad of uses in today’s environment. For example, they generally support application-level and database encryption, TLS operations, access management, payment transactions, signing services, and more. In any case, HSMs are flexible and can even be used to store cryptocurrency wallets or support DNSSEC by signing zone files.
Use Case | Hardware Security Module |
Public Key Infrastructure | Protect CA signing keys and securely store PKI Root Certificates. Support TLS/SSL applications by securing encryption keys. |
Digital Signatures | Ensure software integrity by protecting the keys used for signing software parts. |
Offload Crypto Operations | Speed up cryptographic processing by using the HSM as a dedicated piece of hardware for crypto operations. |
Key Management | Enforce your key management policy in a cloud environment or across multiple domains. |
Identity and Authentication | Create and manage identity credentials. Manage roles, privileges, and authentication rule sets. |
Containers and Virtual Machines | Integrate HSMs into your cloud environment. Sign and encrypt virtual machines, containers, and orchestration operations remotely. |
Smart Card Systems | Implement smart card management systems. Generate, backup, store or revoke certificates on smartcards. |
Audit and Compliance | Follow FIPS 140 and Common Criteria compliance. Log activity while protecting sensitive data. |
Random Number Generation | Integrate HSMs pseudo-true random number generator API with existing applications. |
Real-Time AAA | HSMs are used for authorization and authentication in critical infrastructure. |
How HSMs are used
Essentially, HSMs can be incorporated into operations at the network or application layer. They are often used to support existing protocols with their cryptographic operations. HSMs can be configured to easily expose an API for web applications to call during sensitive processes.
Example Use Case
- A customer inserts their card into a Point of Sale card reader.
- The chip generates and encrypts the information to send to the bank to verify the transaction.
- The merchant sends data over a TLS secured web request to the bank’s web server.
- The server forwards critical information to the HSM.
- The HSM will confirm or deny the validity of the encrypted data.
- The web application will then approve or decline the transition based on the response from the HSM.
- The application uses a TLS secured web request to send back the final result to the PoS terminal.
Cloud HSMs
HSM as a service is a subscription-based model for organizations to take advantage of HSM security. Cloud HSMs support a lightweight remote infrastructure. This allows the cloud to generate, access, and protect keys while keeping the keys separate from the sensitive data they protect. Effectively, remote HSMs expose a platform-independent API for performing cryptographic operations. For Windows, the API will be available as a DLL file. For Linux, an SO file will be provided for use. By default, all HSMs will support symmetric and asymmetric keys, along with X.509 digital certificates.
Securing the HSM
The most common methodology for protecting an HSM is the use of access cards, quorums, and a secure facility. A quorum is a set of individuals registered to perform operations on the HSM. Quorums are broken down into groups of K out of N people. These are adjustable for different functions of the HSM. For example, pulling logs from the HSM might require a quorum of two out of six (2/6). This would mean any two out of the six registered users are needed to retrieve log files. Sensitive functions such as a full reset may require a full quorum (6/6). Quorum members are given secure badges along with a unique passphrase to keep safe. Secure badges are cards that control who has access to the HSM.
Any person who holds a secure access card is a member of the quorum. Cards can be stored by an individual, preferably in a safe or protected site. Some organizations require a two-person safe to access the card. Many organizations also implement a geo-location separation policy for cardholders for highly sensitive data sites.
HSMs are capable of implementing a two-tiered system with general access cards and administrator access cards. The details of each scheme are left up to the organization. These cards are usable either remotely or locally. For cloud-based operations, developers may be given logical cards or cards that can be used with a card reader. In either case, it is often a good policy to require at least one admin to be local to the machine for sensitive operations. Organizations need to carefully consider the balance of availability and security when providing access to the HSM.
Security Standards
If you have a hard requirement of meeting the highest security standards available, HSMs can be rated against FIPS 140-2 levels 1-4. The most commonly used industry-approved standard for communicating with HSM is the PKCS standard. PKCS#11 Cryptographic Token Interface Base Specification is one of the most focused technical standards an organization can implement. As a result, any HSM worth its price will comply with this standard. If your organization needs to meet HIPAA, GDPR, or PCI DSS regulations, an HSM is an excellent investment to simplify the auditing and compliance process. Below are a few common regulations that HSMs can help comply with:
- PCI DSS Compliance
- FIPS 140-2
- Common Criteria
- GDPR
Interacting with the HSM
AWS is a heavily used cloud platform that provides HSM as a service. Let’s take a quick look at how a developer would interact with an HSM over AWS.
Command Line
AWS CloudHSM contains the CloudHSM Management Utility (CMU). The CMU enables you to interact with the HSM over command line.
getCert
Requirement: Our application needs to pull a certificate from the HSM.
Solution: We can use the getCert
command to retrieve a particular certificate from the HSM.
aws-cloudhsm> server 0 // First specify the server for the command.
server0> getCert /tmp/PO.crt 4 // <file-name> <cert-type>
getCert Success // Response from server.
In this case, ‘4’ maps to a customer root certificate. With this command, we are able to pull a cert from the HSM into our local data stores.
Another example to look at is the listUsers
command. With this command, we can easily query the HSM for a list of all registered HSM users. If we are managing an application’s authentication and authorization services, the user’s credentials can be kept here.
listUsers
Requirement: A list of all users needs to be displayed.
Solution: Use the listUsers
command.
aws-cloudhsm>listUsers
Users on server 0(10.0.2.9):
Number of users found:3
User Id User Type User Name MofnPubKey LoginFailureCnt 2FA
1 CO admin NO 0 NO
2 AU app_user NO 0 NO
3 CU example_user NO 0 NO
Users on server 1(10.0.3.11):
...
Web
In this example, a developer calls the CreateHsm
action. For more detailed information, see the official documentation.
Request Syntax
{
"AvailabilityZone": "string",
"ClusterId": "string",
"IpAddress": "string"
}
AvailabilityZone
specifies where you want to create the HSM. ClusterID
allows you to provide an identifier for the HSM’s cluster. In AWS, a cluster is a collection of HSMs kept in sync. The IpAddress
argument specifies the IP address from the subnet that maps to the availability you entered.
Response Syntax
{
"Hsm": {
"AvailabilityZone": "string",
"ClusterId": "string",
"EniId": "string",
"EniIp": "string",
"HsmId": "string",
"State": "string",
"StateMessage": "string",
"SubnetId": "string"
}
}
The response message will contain the state of the response. If there was an error in your request, you will be notified in the response. Otherwise, the StateMessage
attribute will return the HSM’s current state.
Practical
ToxSec made a PoC HSM that students can pull down and spin up to get some hands-on practice.
GitHub Repository
To get familiar with an HSM, you can take a look at our code repo. This is a straightforward PoC HSM to demonstrate how HSM’s can be used and implemented. The front end of the project was developed in Angular, while the backend uses Java over Spring Boot and MongoDB.
https://github.com/Cijams/ToxSec-HSM
Requirements
Let’s take a quick look at the needs our HSM implements. In general, we have a basic application that can register/login a user, create secure keys, and encrypt or digitally sign data. For our project, the client will interact with the HSM via a thin-client web application over the browser. Importantly, the project performs all crypto operations in the HSM secure environment – the HSM Core. With this type of implementation, an HSM can easily integrate into an existing production environment.
Effectively, for our web application, we are going to use an API exposed by the HSM for cryptographic operations. Not only will this enhance our web application by speeding up crypto operations, but we can also be assured that keys are being stored in a secure manner. Using Java’s built-in security framework, we can see the basic implementation of an HSM.
Code
Below is a simplified version of the HSM. In brief, it demonstrates how developers may perform basic operations. The GitHub repository includes the code needed to run the project. Implementing an HSM requires master keys, unique user keys, key encrypting keys, and special passphrases. To clarify, mechanisms not mentioned on this page are in use. You can take a look at the repo if you’d like a deep dive into the subject.
Encryption
Our web application makes a simple, asynchronous call to a Spring Boot server. In this case, a button click triggers the following Typescript to run. This code will use RSA to encrypt the user’s form field data.
Web App
public onEncrypt() {
const url = 'https://HSM:9004/encrypt';
this.http.get(url,
{
params: new HttpParams().set('text', this.encryptForm.get('textToEncrypt').value)
...
// Send the data and update the web app with the response.
The Spring Boot (HSM) server catches the HTTPS call.
HSM
@GetMapping("/encrypt")
public Map<String, String> encrypt(@RequestParam String text, @RequestParam String eKeyID,
@RequestParam String keyPassword) throws Exception {
...
// Encrypt the incoming plaintext.
encryptedText = encrypt_RSA(text, privateKey2);
The server encrypts the data, and Base64 encodes it for the return trip over HTTPS.
HSM
public static String encrypt_RSA(String plainText, PrivateKey privateKey) throws Exception {
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(UTF_8));
return Base64.getEncoder().encodeToString(cipherText);
}
The HSM returns the data to the web application.
HSM
...
// Return the Base64 representation of the RSA encrypted data.
data.put("Encrypted:", encrytpedText);
return data;
With this, we have encrypted text using keys that were never visible in cleartext. This is certainly a simplified use case, but the principles are the same. An API enables hashing, digital signatures, and key exchanges.
Decrypt
To make the trip back from ciphertext into the clear, we need the password the user or web application used for the encryption and a copy of the ciphertext. Because of this, developers manage passwords as they see fit, often choosing a secure web token.
HSM
@GetMapping("/decrypt")
public Map<String, String> decrypt(@RequestParam String keyPassword,
@RequestParam String cipherText,
@RequestParam String eKeyID) throws Exception {
...
// Decrypt the incoming ciphertext.
String decryptedText = decrypt_RSA(cipherText, publicKey);
The server decodes and decrypts the data.
HSM
public static String decrypt_RSA(String cipherText, PublicKey publicKey) throws Exception {
byte[] bytes = Base64.getDecoder().decode(cipherText);
Cipher decriptCipher = Cipher.getInstance("RSA");
decriptCipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(decriptCipher.doFinal(bytes), UTF_8);
}
Keygen
Generating an RSA key pair is pretty simple. For example, you can use an HSM’s RNG feature to create a tweak that makes sure that each key generated is unique.
HSM
@GetMapping("/generateKeyPair")
public Map<String, String> generateKeys(@RequestParam String userID,
@RequestParam String keyPassword)
throws Exception {
...
KeyPair kp = _generateKeyPair(keyPassword);
In this case, we generate a secure 2048 bit key.
HSM
private static KeyPair _generateKeyPair(String tweak) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, new SecureRandom(tweak.getBytes()));
KeyPair pair = generator.generateKeyPair();
return pair;
}
We return the key pair to the calling function and separate the data into two variables. Consequently, we can now use the HSM’s secure storage capabilities to save the private key and send out the corresponding public key and key ID.
HSM
PublicKey pub = kp.getPublic();
PrivateKey pvt = kp.getPrivate();
...
// Store private key and return a public key and key ID.
Sign and Verify
Signing code or a message is pretty simple. We just need to use the user’s private key and plaintext.
HSM
public static String sign(String plainText, PrivateKey privateKey) throws Exception {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes(UTF_8));
byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
}
To verify a signature, use the same basic process with the public key.
HSM
public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
Signature publicSignature = Signature.getInstance("SHA256withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes(UTF_8));
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return publicSignature.verify(signatureBytes);
}
Hash
If you have requirements for a random number generator, an HSM will provide seeds or numbers over an API call. HSMs have modules to generate or seed “truly random numbers”. These modules also support double-checking the output ensure correctness.
Catch the web call.
HSM
public Map<String, String> hashWeb(@RequestParam String textToHash) throws NoSuchAlgorithmException {
HashMap<String, String> hashedData = new HashMap<>();
byte[] sha2 = new byte[0];
StringBuilder hexString = null;
sha2 = generateSha2(textToHash);
...
Hash it using a message digest of your choice.
HSM
public static byte[] generateSha2(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return md.digest(input.getBytes(StandardCharsets.UTF_8));
}
Convert it to a renderable format and return the data.
HSM
// Convert SHA-2 to hexadecimal
hashedData.put("Hash:", hexString.toString());
return hashedData;
}
Commonly Asked Questions
Why do we need to Base64 encode the encryption data
It’s not a strict requirement to encode encryption data. Put simply, it’s a more convenient way of representing the data and avoiding problems during transmission. Some protocols, especially legacy protocols, have trouble with non-printable characters. You can use other encoding mechanisms, but Base64 works well with the web and has a proven history.
How do you protect user passwords in transit?
Protecting user passwords in transit between the web application and HSM is application-specific. Secure protocols such as HTTPS keep information encrypted in transit. When the password gets to the server, the server should hash the password and compare the result against the hash stored within the HSM. This scheme works well if the HSM is also powering the TLS implementation.
What is the Key ID?
HSMs use Key IDs for login purposes. The key id is a method of mapping keys to users for web applications that implements a login system. In general, user names and passwords hash to a unique value for private key lookup.
What If I lose a Card or forget a password?
HSM cards are, and their related key phrase unlocks the device. The use of a quorum prevents one or two lost cards from losing access entirely. However, a lost card can be dangerous, and if a card goes missing, the HSM needs to reset the keys behind the cards. You will essentially need to factory reset the HSM if the quorum loses enough cards. This event will result in the loss of all encrypted data keys stored in the HSM.
What is BYOK?
Bring Your Own Key (BYOK) is an encryption key management system that allows users to encrypt data while retaining control of their encryption key. To clarify, an organization can own its key stored within an HSM. As a result, this will enable them to control the export of the key to the cloud. BYOK keeps the keys in-house.