A couple of weeks ago, I wrote a post on the eMudhra incident. The company has now published their Full Incident Report. Strangely, at least to me, they posted it as a comment on the Bugzilla ticket but not on their public page about the incident.
I saw quite a bit of chatter on Twitter about the topic of exporting private keys from hardware security modules (HSMs). I’m not going to comment on that because it’s outside my domain of expertise. What I did want to comment on were some of the details mentioned in the write-up that get at the constraints that the engineers at eMudhra faced, and how those constraints influenced decisions that the engineers made in the moment.
Technical background
Before we can get into it, I need to say a little about public key certificates. This was largely for my own benefit, because trying to explain the technology forces me to learn more about it.
Certificates and browsers
When your web browser makes a secure connection to a website, it does a check to verify that you are connected to the real website, and not some fake website that was set up by a nefarious actor who is trying to fool you. As part of the protocol, the website will return a server certificate that attests “this is the right website”. Your web browser will check that the certificate was properly signed by a trusted authority.
Let’s use everybody’s favorite example website: example.com. Your browser can show you information about the server certificate by clicking on the little icon next in the browser bar > Connection is secure > Certificate details. Here’s what you see in Google Chrome for example.com.

Certificate authorities
For the purposes of this post, the important bit is the “Issued By” section: That tells us which entity issued the certificate. An issuer of certificates is called a Certificate Authority (CA). For example.com, the CA’s common name is Cloudflare TLS Issuing ECC CA 3.
The browser needs the public key of the CA in order to check that the certificate’s signature is valid. It also needs to know whether it can trust the CA that issued the certificate. After all, anybody can set up a CA and issue whatever server certificates they want. The browser has to ensure that the certificate was issued by a trusted CA.
Browsers use the same mechanism for checking whether to trust a CA as they do for checking whether to trust a server: they check a certificate! Instead of a server certificate it’s a CA certificate, but it’s also issued by a CA. In Chrome’s certificate viewer, under “details”, you can see the chain of CAs involved:

Browsers need a way to trust some CAs without verifying that their CA certificates were signed by another CA, or else you have an infinite regress problem. And so there are a set of CAs that browsers automatically trust. You can view the Chrome Root Store, the set of CAs that are trusted in Chrome, by pointing your browser to chrome://certificate-manager/crscerts. It looks like this:

The website normally sends over the server certificate and intermediate certificates needed to build the chain up to one that is known to already be trusted by browsers. The browser then checks the chain to verify that the server certificate was signed by a trusted CA.
For example.com, here’s a diagram that depicts the various CAs that are involved in the chain.

Intermediate CAs
CAs that are already trusted by browsers are referred to as root CAs, and CAs below the root are called intermediate CAs or subordinate CAs. I’m calling out this terminology here because the CA involved in this incident was an intermediate CA. The important thing to remember is that an intermediate CA must have a CA certificate that’s signed by another CA. (Because root CAs are already trusted by browsers, their CA certificate doesn’t need to be signed by another trusted CA, and so they can be self-signed).
The ingredients of a CA
In order to operate an intermediate certificate authority, you need two things:
- a public-private keypair
- CA certificate
The private key is used to sign certificates. The public key is used by the browser to verify that the signature is valid. The CA certificate demonstrates that another CA trusts you.
A bit of detail that will be important later is that, in order to get that signed CA certificate, you need to already have generated your public-private keypair. If you haven’t generated a keypair yet, you can’t get that certificate.
Hardware security modules (HSMs)
If somebody gets a hold of your CA’s private key, then they can use it to forge certificates. The industry uses hardware security modules (HSMs), which are dedicated hardware devices you connect to a server to securely manage sensitive private keys.
If your server has an HSM installed, it can generate the keypair and keep the private key within the HSM, which means your server never needs to load the private key into memory in order to perform cryptographic functions like signing certificates. HSMs play an important role in this incident because the lack of HSMs ended up becoming a constraint, as we’ll see.
The constraints
With those background details out of the way, let’s dive into the constraints that eMudhra engineers faced as mentioned in the writeup.
CAs must be physically based in Europe and the U.S.
While eMudhra is based in India, their customers had data sovereignty requirements that there had to be CAs physically located in datacenters in the U.S. and Europe. This meant that they needed HSMs at these U.S. and European datacenters, since the private key for the CAs had to be managed by HSM.
The naming convention they used for the CAs at the three sites are:
- Series A – based in India
- Series B – based in Netherlands
- Series C – based in United States
According to the writeup, eMudhra ordered the HSMs for the U.S. site in April of 2025. (It doesn’t say when they ordered the HSMs for Europe). This timing will become important later on.
Supporting older clients
(This section is speculative because the rationale isn’t explicitly stated in the incident report).
eMudhra was setting up an intermediate CA. Recall from earlier that an intermediate CA needs to have a CA certificate signed by a different CA. The eMudhra intermediate CA’s certificate is signed by eMudhra’s own root CA, for which they use the brand name emSign.
Here’s a certificate associated with the American (C series) data center: EM DV TLS CA ‑ G3C. You can see the issuer was emSign Root TLS CA – G3.
If you are a CA and the client doesn’t trust your CA certificate, then you have a problem: the client won’t trust the certificates that you issue. However, you can get your CA certificate cross-signed by a CA that the client does trust, and then you’re good.
There are some older clients out there, ones that don’t have eMudhra’s in their trust stores, and eMudhra dealt with that by having their CA certificate cross-signed by an older CA. In this case, that CA was managed by a separate company: Sectigo (As an aside, here’s Sectigo’s statement on this incident).
Sectigo’s CAs go by the name “AAA Certificate Services”, and you can see the cross-signed certificate here. Below is a diagram of the various CA certificates involved here.

(Note that cross-signing technically creates separate certificates, which I’m not explicitly depicting)
To sum up, the need to support older clients (which didn’t trust their root CA) created a constraint that eMudhra had to get their CA certificate cross-signed by another CA; in this case, that CA was operated by Sectigo.
Client certificates and Chrome Root Store Policy Change Deadline
On the web, browsers use server certificates to verify the identity of websites, but it doesn’t work the other way: websites generally don’t use client certificates to verify user identity, even though browsers support it. Instead, they use things like username and password.
However, there are domains where public-key certificates are used by both servers and clients for verifying each other’s identities, and the use of both server and client certificates is called mutual TLS. One place I have personally seen this used was internally at Netflix. And some enterprises apparently do use client certificates in browsers. eMudhra apparently wanted their new intermediate CA to be able to issue both server certificates and client certificates. The incident writeup doesn’t say why eMudhra wanted this capability.
But there was an issue with this new intermediate CA being able to issue client certificates as well as server certificates. The intermediate CA would be chained to their root CA (emSign ECC Root CA – G3 in the diagram above), which was in the Chrome Root Store. Google had long required that CAs below a root CA in the Trust Store had to be included in the Common CA database (CCADB). But they were about to add a new constraint: intermediate CAs with a root CA in the Chrome Root Store would only be permitted to issue server certificates, not client certificates.
Back in February 2023, on a Chrome Root Program Policy page called Moving Forward, Together, in a section called Focusing on simplicity, they discussed how they value CAs that focus exclusively on web use cases (emphasis mine)
Though multipurpose root CAs have offered flexibility in addressing subscriber use cases over the last few decades, they are now faced with satisfying the demands of multiple sets of increasingly rigorous expectations and requirements that do not always align. We believe in the value of purpose-built, dedicated infrastructures and the increased opportunity for innovation that comes along with them. We also think there’s value in reducing the complexity of the Web PKI to increase the security and stability of the ecosystem. By promoting dedicated-use hierarchies, we can better align the related policies and processes that CAs must conform to with the expectations of subscribers, relying parties, and root program operators.
They noted that they may add a restriction that CAs in the program only support server authentication use cases [emphasis in the original]
In a future policy update or CA/Browser Forum Ballot Proposal, we may introduce:
- a requirement that would restrict extendedKeyUsage values in new subordinate CA and TLS server authentication subscriber certificates to only “id-kp-serverAuth.” Modifying the definition of a dedicated TLS PKI hierarchy to prohibit use of other extendedKeyUsage values (i.e., id-kp-clientAuth) in new CA certificates capable of issuing TLS server certificates more closely aligns CA practices with web browser use cases (i.e., securing connections to websites). Further, it eliminates the risk and unintended consequences of other use cases (e.g., IoT) from negatively affecting website authentication.
Google eventually committed to this policy, announcing that they would be enforcing this as of June 15, 2025. Here’s the relevant bit from Section 3.2.1 of the Chrome Root Program Policy doc [emphasis in the original]:
The Chrome Root Program will only accept [Common CA Database] Root Inclusion Requests from Applicant PKI hierarchies that are dedicated to TLS server authentication certificate issuance.
To qualify as a dedicated TLS server authentication PKI hierarchy under this policy:
- All corresponding unexpired and unrevoked subordinate CA certificates operated beneath an applicant root CA MUST:
- when disclosed to the CCADB…
- prior to June 15, 2025, include the extendedKeyUsage extension and (1) only assert an extendedKeyUsage purpose of id-kp-serverAuth OR (2) only assert extendedKeyUsage purposes of id-kp-serverAuth and id-kp-clientAuth.
- on or after June 15, 2025, include the extendedKeyUsage extension and only assert an extendedKeyUsage purpose of id-kp-serverAuth.
- …
The writeup mentions this date, so I assume this is what they were referring to. The thing is, though, their root CA was already in the trust store, and for intermediate CAs with roots already in the key store, according to section 3.2.2 of that document, the deadline was a year later: June 15, 2026.
At any rate, I assume eMudhra believed that if they wanted their intermediate CA to be able to issue client certificates, they had to disclose it to the CCADB before June 15, 2025. That meant they needed it cross-signed by Sectigo before then. Which meant that they needed to generate the keypairs, which required the HSMs.
Supply chain delays
The HSMs had been ordered in April of 2025. But there was a problem: they were taking longer to arrive than expected. The incident report states that “delivery of the HSMs ordered for the US facility was delayed by global supply‑chain constraints.” and doesn’t go into more detail than that, nor does it mention anything about the European facility.
What is the clear, though, is that this added production pressure. If the HSMs didn’t make it to the site quickly enough for them to generate the keys and get the certificates cross-signed by Certigo then eMudhra could miss Google’s June deadline for disclosing to the CCADB. Alas, the business implications of missing the deadline aren’t spelled out in the report, but it was clearly enough to act as a significant constraint.
Requiring WebTrust certified environments
The report says “It was also eMudhra’s intention to only operate HSMs within WebTrust certified environments…” Unfortunately, they don’t go into detail about why that’s their intention.
The Server Cert working group of the CA/Browser Forum requires compliance audits for CAs (see section 8), using on approved auditing scheme, which explicitly mentions WebTrust as one of these approved schemes. But it doesn’t explicitly say that an audit is required before operating an HSM at the site. However, what’s clear is that eMudhra had an internal policy about this.
Presumably, the HSMs had to be in place first before the WebTrust certification audit could happen, and that would introduce additional delays. Even if the HSM made it before the June deadline, they couldn’t use the HSM to generate the keypair because that would violate their policy.
Moving keys across HSMs from different vendors
The HSMs that the eMudhra engineers used to generate the key pairs were made by a vendor named Utimaco, but the new HSMs they had purchased for U.S. and European sites were made by a different vendor: Crypto4A. According to the write-up, the fact that the HSMs were manufactured by different vendors constrained their ability to transfer keys from one to the other. I assume based on this that vendors provide better support for transferring keys between HSMs of the same vendor. But in this case, the eMudhra engineers had to write a custom Python script to support the transfer, and the resulting script they wrote had a bug in it that led to the unintentional truncation of the private key to a single byte.
The outcome: a workaround leads to an incident
Based on the constraints they were facing, the eMudhra engineers decided to generate the keypairs for the European and U.S. sites at the (WebTrust certified) India site, and then export the keys out of the Indian HSM into the U.S. and European ones when they were able to. This was a workaround and … things went wrong during a rehearsal of the transfer process, and as a result they ended up with a cryptographically weak private key. You can read about the specifics of the failure mode elsewhere, it’s not my focus here.
Instead, my focus is how constraints shape behavior. Some of the constraints were business-oriented constraints (wanting to support mutual TLS, support for older clients), some were technical (transferring keys across HSMs manufactured by different vendors) and some were external (supply chain induced delays), but others were explicitly designed to improve security:
- Data sovereignty requirements
- Chrome Root Store Policy change to increase simplicity
- Hardware security module requirements
- WebTrust certification requirements
These are all well-intentioned, reasonable requirements, that nevertheless conspired against the eMudhra engineers in this scenario. The goals of each of these is to increase security, and yet, in this particular scenario, they each contributed to a significant security incident.
It’s also a textbook example of the role of production pressure. Look at how these factors interacted to create a hard deadline, and how that deadline influenced the work. It’s tempting to fault the engineers for doing the wrong thing here. But if you really want to understand how incidents happen, you have to look at how constraints influence decisions and workarounds.





















