5454public class PKCS11HSMProvider extends AdapterBase implements KMSProvider {
5555 private static final Logger logger = LogManager .getLogger (PKCS11HSMProvider .class );
5656 private static final String PROVIDER_NAME = "pkcs11" ;
57-
57+
5858 @ Inject
5959 private HSMProfileDao hsmProfileDao ;
60-
60+
6161 @ Inject
6262 private HSMProfileDetailsDao hsmProfileDetailsDao ;
63-
63+
6464 @ Inject
6565 private KMSKekVersionDao kmsKekVersionDao ;
6666
6767 // Session pool per HSM profile
6868 private final Map <Long , HSMSessionPool > sessionPools = new ConcurrentHashMap <>();
69-
69+
7070 // Profile configuration caching
7171 private final Map <Long , Map <String , String >> profileConfigCache = new ConcurrentHashMap <>();
7272
@@ -80,6 +80,16 @@ public String getProviderName() {
8080 return PROVIDER_NAME ;
8181 }
8282
83+ /**
84+ * @return The name of the component that provided this configuration
85+ * variable. This value is saved in the database so someone can easily
86+ * identify who provides this variable.
87+ **/
88+ @ Override
89+ public String getConfigComponentName () {
90+ return PKCS11HSMProvider .class .getSimpleName ();
91+ }
92+
8393 @ Override
8494 public ConfigKey <?>[] getConfigKeys () {
8595 return new ConfigKey <?>[0 ];
@@ -90,7 +100,7 @@ public String createKek(KeyPurpose purpose, String label, int keyBits, Long hsmP
90100 if (hsmProfileId == null ) {
91101 throw KMSException .invalidParameter ("HSM Profile ID is required for PKCS#11 provider" );
92102 }
93-
103+
94104 if (StringUtils .isEmpty (label )) {
95105 label = generateKekLabel (purpose );
96106 }
@@ -142,14 +152,14 @@ public byte[] unwrapKey(WrappedKey wrappedKey, Long hsmProfileId) throws KMSExce
142152 public WrappedKey rewrapKey (WrappedKey oldWrappedKey , String newKekLabel , Long targetHsmProfileId ) throws KMSException {
143153 // 1. Unwrap with old KEK
144154 byte [] plainKey = unwrapKey (oldWrappedKey , null ); // Auto-resolve old profile
145-
155+
146156 try {
147157 // 2. Wrap with new KEK
148158 Long profileId = targetHsmProfileId ;
149159 if (profileId == null ) {
150160 profileId = resolveProfileId (newKekLabel );
151161 }
152-
162+
153163 return wrapKey (plainKey , oldWrappedKey .getPurpose (), newKekLabel , profileId );
154164 } finally {
155165 // Zeroize plaintext key
@@ -183,16 +193,11 @@ public void deleteKek(String kekId) throws KMSException {
183193 }
184194 }
185195
186- @ Override
187- public List <String > listKeks (KeyPurpose purpose ) throws KMSException {
188- throw new KMSException (KMSException .ErrorType .OPERATION_FAILED , "Listing KEKs directly from HSMs not supported, use DB" );
189- }
190-
191196 @ Override
192197 public boolean isKekAvailable (String kekId ) throws KMSException {
193198 Long hsmProfileId = resolveProfileId (kekId );
194199 if (hsmProfileId == null ) return false ;
195-
200+
196201 HSMSessionPool pool = getSessionPool (hsmProfileId );
197202 PKCS11Session session = null ;
198203 try {
@@ -210,20 +215,20 @@ public boolean healthCheck() throws KMSException {
210215 return true ;
211216 }
212217
213- private Long resolveProfileId (String kekLabel ) throws KMSException {
218+ Long resolveProfileId (String kekLabel ) throws KMSException {
214219 KMSKekVersionVO version = kmsKekVersionDao .findByKekLabel (kekLabel );
215220 if (version != null && version .getHsmProfileId () != null ) {
216221 return version .getHsmProfileId ();
217222 }
218223 throw new KMSException (KMSException .ErrorType .KEK_NOT_FOUND , "Could not resolve HSM profile for KEK: " + kekLabel );
219224 }
220225
221- private HSMSessionPool getSessionPool (Long profileId ) {
222- return sessionPools .computeIfAbsent (profileId ,
226+ HSMSessionPool getSessionPool (Long profileId ) {
227+ return sessionPools .computeIfAbsent (profileId ,
223228 id -> new HSMSessionPool (id , loadProfileConfig (id )));
224229 }
225230
226- private Map <String , String > loadProfileConfig (Long profileId ) {
231+ Map <String , String > loadProfileConfig (Long profileId ) {
227232 return profileConfigCache .computeIfAbsent (profileId , id -> {
228233 List <HSMProfileDetailsVO > details = hsmProfileDetailsDao .listByProfileId (id );
229234 Map <String , String > config = new HashMap <>();
@@ -238,14 +243,14 @@ private Map<String, String> loadProfileConfig(Long profileId) {
238243 });
239244 }
240245
241- private boolean isSensitiveKey (String key ) {
242- return key .equalsIgnoreCase ("pin" ) ||
243- key .equalsIgnoreCase ("password" ) ||
246+ boolean isSensitiveKey (String key ) {
247+ return key .equalsIgnoreCase ("pin" ) ||
248+ key .equalsIgnoreCase ("password" ) ||
244249 key .toLowerCase ().contains ("secret" ) ||
245250 key .equalsIgnoreCase ("private_key" );
246251 }
247252
248- private String generateKekLabel (KeyPurpose purpose ) {
253+ String generateKekLabel (KeyPurpose purpose ) {
249254 return purpose .getName () + "-kek-" + UUID .randomUUID ().toString ().substring (0 , 8 );
250255 }
251256
@@ -256,14 +261,14 @@ private static class HSMSessionPool {
256261 private final Map <String , String > config ;
257262 private final int maxSessions ;
258263 private final int minIdleSessions ;
259-
264+
260265 HSMSessionPool (Long profileId , Map <String , String > config ) {
261266 this .profileId = profileId ;
262267 this .config = config ;
263268 this .maxSessions = Integer .parseInt (config .getOrDefault ("max_sessions" , "10" ));
264269 this .minIdleSessions = Integer .parseInt (config .getOrDefault ("min_idle_sessions" , "2" ));
265270 this .availableSessions = new ArrayBlockingQueue <>(maxSessions );
266-
271+
267272 // Pre-warm
268273 for (int i = 0 ; i < minIdleSessions ; i ++) {
269274 try {
@@ -273,7 +278,7 @@ private static class HSMSessionPool {
273278 }
274279 }
275280 }
276-
281+
277282 PKCS11Session acquireSession (long timeoutMs ) throws KMSException {
278283 try {
279284 PKCS11Session session = availableSessions .poll ();
@@ -288,15 +293,15 @@ PKCS11Session acquireSession(long timeoutMs) throws KMSException {
288293 throw new KMSException (KMSException .ErrorType .CONNECTION_FAILED , "Failed to acquire HSM session" , e );
289294 }
290295 }
291-
296+
292297 void releaseSession (PKCS11Session session ) {
293298 if (session != null && session .isValid ()) {
294299 if (!availableSessions .offer (session )) {
295300 session .close (); // Pool full
296301 }
297302 }
298303 }
299-
304+
300305 private PKCS11Session createNewSession () throws KMSException {
301306 return new PKCS11Session (config );
302307 }
@@ -307,12 +312,12 @@ private static class PKCS11Session {
307312 private final Map <String , String > config ;
308313 private KeyStore keyStore ;
309314 private Provider provider ;
310-
315+
311316 PKCS11Session (Map <String , String > config ) throws KMSException {
312317 this .config = config ;
313318 connect ();
314319 }
315-
320+
316321 private void connect () throws KMSException {
317322 try {
318323 String libraryPath = config .get ("library_path" );
@@ -324,33 +329,33 @@ private void connect() throws KMSException {
324329 throw new KMSException (KMSException .ErrorType .CONNECTION_FAILED , "Failed to connect to HSM: " + e .getMessage (), e );
325330 }
326331 }
327-
332+
328333 boolean isValid () {
329334 return true ;
330335 }
331-
336+
332337 void close () {
333338 if (provider != null ) {
334339 Security .removeProvider (provider .getName ());
335340 }
336341 }
337-
342+
338343 String generateKey (String label , int keyBits , KeyPurpose purpose ) throws KMSException {
339344 return label ;
340345 }
341-
346+
342347 byte [] wrapKey (byte [] plainDek , String kekLabel ) throws KMSException {
343348 return "wrapped_blob" .getBytes ();
344349 }
345-
350+
346351 byte [] unwrapKey (byte [] wrappedBlob , String kekLabel ) throws KMSException {
347352 return new byte [32 ]; // 256 bits
348353 }
349-
354+
350355 void deleteKey (String label ) throws KMSException {
351356 // Stub
352357 }
353-
358+
354359 boolean checkKeyExists (String label ) throws KMSException {
355360 return true ;
356361 }
0 commit comments