Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
HSM cloud di Azure offre un supporto affidabile per l'archiviazione dei certificati tramite l'API PKCS#11. Questo articolo illustra come usare l'API PKCS#11 per gestire i certificati X.509, tra cui la creazione, la copia, l'eliminazione e il recupero degli attributi del certificato. Per una panoramica dettagliata della configurazione dell'archiviazione dei certificati, inclusi i prerequisiti e la configurazione, vedere Azure archiviazione dei certificati del modulo di protezione hardware cloud.
Uso dell'API PKCS#11 per l'archiviazione dei certificati X.509
Le API esistenti seguenti in PKCS#11 per HSM cloud di Azure sono state espanse per aggiungere il supporto per i certificati di chiave pubblica X.509.
- C_CreateObject: crea un nuovo oggetto certificato.
- C_DestroyObject: elimina un oggetto certificato esistente.
- C_CopyObject: copia un oggetto certificato esistente.
- C_GetAttributeValue: ottiene il valore di uno o più attributi di un oggetto certificato.
- C_SetAttributeValue: aggiorna il valore di uno o più attributi di un oggetto certificato.
- C_FindObjectsInit: avvia una ricerca di oggetti certificato.
- C_FindObjects: Continua una ricerca di oggetti certificati.
- C_FindObjectsFinal: termina una ricerca di oggetti certificati.
C_CreateObject
L'API C_CreateObject funziona in modo analogo sia per le chiavi che per i certificati. Prevede una matrice di attributi, il numero di attributi e un puntatore a un handle di oggetto in cui verrà archiviato l'handle generato.
Di seguito è riportato un esempio di come usare il C_CreateObject.
int create_cert(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE_PTR cert_handle)
{
// Dummy certificate data
CK_BYTE certData[] = { 0x30, 0x82, 0x03, 0x08, 0x30, 0x82, 0x02, 0xD0 }; // Sample DER-encoded cert
CK_ULONG certSize = sizeof(certData);
CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_BBOOL trueValue = CK_TRUE;
CK_BYTE id[] = {123};
// Dummy DER-encoded Subject Name (adjust as needed)
CK_BYTE subjectData[] = { 0x30, 0x1D, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x12, 'M', 'y', 'C', 'e',
'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '-', 'B', 'b', 'j' };
CK_ULONG subjectSize = sizeof(subjectData);
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, &objClass, sizeof(objClass) },
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
{ CKA_TOKEN, &trueValue, sizeof(trueValue) },
{ CKA_LABEL, "MyCertificate", 13 },
{ CKA_SUBJECT, subjectData, subjectSize },
{ CKA_ID, id, sizeof(id) },
{ CKA_VALUE, certData, certSize }
};
int n_attr = sizeof(certTemplate) / sizeof(CK_ATTRIBUTE);
if ((func_list->C_CreateObject)(session_rw, certTemplate,
n_attr, cert_handle)) {
return FAILED;
}
#ifdef DEBUG
printf("The cert handle created is : %lu \n", *cert_handle);
#endif
return CKR_OK;
}
Gli attributi seguenti rappresentano il set minimo necessario per creare un certificato X.509 in PKCS#11.
| Livello | Attributo | Tipo di dati | Descrizione |
|---|---|---|---|
| Attributi comuni | CKA_CLASS | CK_OBJECT_CLASS | Classe Oggetto (tipo) |
| Oggetti certificati | CKA_CERTIFICATE_TYPE | CK_CERTIFICATE_TYPE | Tipo di certificato, CKC_X_509 per i certificati di chiave pubblica X.509 |
| Oggetti di certificato di chiave pubblica X.509 | CKA_SUBJECT | Matrice di byte | Codifica DER del nome soggetto del certificato |
| Oggetti di certificato di chiave pubblica X.509 | CKA_VALUE | Matrice di byte | Codifica BER del certificato |
Gli attributi seguenti sono applicabili ai certificati di chiave pubblica X.509.
| Livello | Attributo | Tipo di dati | Descrizione |
|---|---|---|---|
| Attributi comuni | CKA_CLASS | CK_OBJECT_CLASS | Classe Oggetto (tipo) |
| Oggetti di archiviazione | CKA_TOKEN | CK_BBOOL | CK_TRUE se l'oggetto è un oggetto token; CK_FALSE se l'oggetto è un oggetto sessione. Il valore predefinito è CK_FALSE. |
| Oggetti di archiviazione | CKA_PRIVATE | CK_BBOOL | CK_TRUE se l'oggetto è un oggetto privato; CK_FALSE se l'oggetto è un oggetto pubblico. Il valore predefinito è specifico del token e può dipendere dai valori di altri attributi dell'oggetto. |
| Oggetti di archiviazione | CKA_MODIFIABLE | CK_BBOOL | CK_TRUE se è possibile modificare l'oggetto, default è CK_TRUE. |
| Oggetti di archiviazione | CKA_LABEL | stringa RFC2279 | Descrizione dell'oggetto (valore predefinito vuoto). |
| Oggetti di archiviazione | CKA_COPYABLE | CK_BBOOL | CK_TRUE se l'oggetto può essere copiato tramite C_CopyObject. CK_TRUE per impostazione predefinita. Non può essere impostato su TRUE dopo che è stato impostato su FALSE. |
| Oggetti di archiviazione | CKA_DESTROYABLE | CK_BBOOL | CK_TRUE se l'oggetto può essere eliminato definitivamente usando C_DestroyObject. Il valore predefinito è CK_TRUE. |
| Oggetti certificati | CKA_CERTIFICATE_TYPE | CK_CERTIFICATE_TYPE | Tipo di certificato, CKC_X_509 per i certificati di chiave pubblica X.509 |
| Oggetti certificati | CKA_TRUSTED | CK_BBOOL | Il certificato può essere considerato attendibile per l'applicazione creata. |
| Oggetti certificati | CKA_CERTIFICATE_CATEGORY | CKA_CERTIFICATE_CATEGORY | (CK_CERTIFICATE_CATEGORY_UNSPECIFIED per impostazione predefinita) |
| Oggetti certificati | CKA_CHECK_VALUE | Matrice di byte | Checksum |
| Oggetti certificati | CKA_START_DATE | CK_DATE | Data di inizio per il certificato (valore predefinito vuoto) |
| Oggetti certificati | CKA_END_DATE | CK_DATE | Data di fine per il certificato (valore predefinito vuoto) |
| Oggetti certificati | CKA_PUBLIC_KEY_INFO | Matrice di byte | Codifica DER dell'oggetto SubjectPublicKeyInfo per la chiave pubblica contenuta in questo certificato (impostazione predefinita vuota) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_SUBJECT | Matrice di byte | Codifica DER del nome soggetto del certificato |
| Oggetti di certificato di chiave pubblica X.509 | CKA_ID | Matrice di byte | Identificatore della chiave per la coppia di chiavi pubblica/privata (valore predefinito vuoto) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_ISSUER | Matrice di byte | Codifica DER del nome dell'autorità di certificazione (valore predefinito vuoto) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_SERIAL_NUMBER | Matrice di byte | Codifica DER del numero di serie del certificato (valore predefinito vuoto) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_VALUE | Matrice di byte | Codifica BER del certificato |
| Oggetti di certificato di chiave pubblica X.509 | CKA_URL | stringa RFC2279 | Se questo attributo non è vuoto, fornisce l'URL in cui è possibile ottenere il certificato completo (valore predefinito vuoto) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_HASH_OF_SUBJECT_PUBLIC_KEY | Matrice di byte | Hash della chiave pubblica del soggetto (valore predefinito vuoto). L'algoritmo hash è definito da CKA_NAME_HASH_ALGORITHM |
| Oggetti di certificato di chiave pubblica X.509 | CKA_HASH_OF_ISSUER_PUBLIC_KEY | Matrice di byte | Hash della chiave pubblica dell'autorità di certificazione (valore predefinito vuoto). L'algoritmo hash è definito da CKA_NAME_HASH_ALGORITHM |
| Oggetti di certificato di chiave pubblica X.509 | CKA_JAVA_MIDP_SECURITY_DOMAIN | CK_JAVA_MIDP_SECURITY_DOMAIN | Dominio di sicurezza MIDP Java. (CK_SECURITY_DOMAIN_UNSPECIFIED per impostazione predefinita) |
| Oggetti di certificato di chiave pubblica X.509 | CKA_NAME_HASH_ALGORITHM | CK_MECHANISM_TYPE | Definisce il meccanismo utilizzato per calcolare CKA_HASH_OF_SUBJECT_PUBLIC_KEY e CKA_HASH_OF_ISSUER_PUBLIC_KEY. Se l'attributo non è presente, per impostazione predefinita il tipo è SHA-1. |
C_DestroyObject
L'API C_DestroyObject accetta un handle di sessione e l'handle dell'oggetto associato al certificato da eliminare. Richiamare questa funzione rimuove il certificato specificato dall'account di archiviazione BLOB di Azure eliminando il BLOB JWS corrispondente denominato pkcs11_certificate_<cert-handle>.
Di seguito è riportato un frammento di codice che illustra come chiamare C_DestroyObject per i certificati (lo stesso approccio si applica alle chiavi).
int delete_cert(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE cert_handle)
{
CK_RV rv = 0;
rv = (func_list->C_DestroyObject)(session_rw, cert_handle);
if(rv != CKR_OK) {
printf("Deleting Certificate failed \n");
return rv;
}
return rv;
}
C_CopyObject
L'API C_CopyObject accetta un handle di sessione, l'handle dell'oggetto da copiare e un puntatore per ricevere l'handle dell'oggetto appena creato. Per mantenere la parità con l'implementazione C_CopyObject per gli oggetti chiave nel modulo di protezione hardware cloud di Azure, l'implementazione del certificato non supporta la modifica degli attributi durante l'operazione di copia.
Di seguito è riportato un frammento di codice di esempio che illustra come usare C_CopyObject per l'archiviazione dei certificati.
int copy_cert(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE cert_handle,
CK_OBJECT_HANDLE_PTR copied_cert_handle)
{
CK_RV rv = 0;
rv = (func_list->C_CopyObject)(session_rw, cert_handle, NULL, 0, copied_cert_handle);
if(rv != CKR_OK) {
printf("Copying Certificate failed \n");
return rv;
}
return rv;
}
C_GetAttributeValue
L'API C_GetAttributeValue consente il recupero di tutti gli attributi elencati nella sezione API C_CreateObject. Questa API viene in genere richiamata due volte. La prima chiamata determina le dimensioni degli attributi con lunghezze sconosciute, ad esempio CKA_SUBJECT, che contiene l'oggetto del certificato con codifica DER.
Di seguito è riportato un esempio di come chiamare C_GetAttributeValue per ottenere le dimensioni degli attributi specificati.
int get_cert_attribute(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE_PTR cert_handle)
{
CK_RV rv = 0;
CK_ULONG cka_class = 0;
CK_CERTIFICATE_TYPE cka_cert_type = 0;
CK_BBOOL cka_token = 0;
char* cka_label = NULL;
char* cka_subject = NULL;
CK_BYTE* cka_id = NULL;
CK_BYTE* cka_value = NULL;
// Determine size needed for each attribute by calling C_GetAttributeValue with NULL pointers
// and zero as the length.
CK_ATTRIBUTE cert_template[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_CERTIFICATE_TYPE, NULL, 0 },
{ CKA_TOKEN, NULL, 0 },
{ CKA_LABEL, NULL, 0 },
{ CKA_ID, NULL, 0 },
};
int n_attr = sizeof(cert_template) / sizeof(CK_ATTRIBUTE);
rv = (func_list->C_GetAttributeValue)(session_rw, *cert_handle, cert_template, n_attr);
if (rv != CKR_OK) {
printf("C_GetAttributeValue failed with %ld\n", rv);
return FAILED;
}
Once the attribute sizes are known, memory can be allocated accordingly. A second call to the C_GetAttributeValue API is then made to retrieve the attribute values and store them in the allocated memory.
The image below shows a code snippet demonstrating this process based on the previous example:
cka_label = (char*)malloc(cert_template[3].ulValueLen);
if (cka_label == NULL) {
printf("Memory allocation failed for CKA_LABEL.\n");
rv = FAILED;
goto end_test_get_cert_attribute;
}
cert_template[3].pValue = cka_label;
if (cert_template[4].ulValueLen <= 0) {
printf("CKA_ID size must be > 0.\n");
rv = FAILED;
goto end_test_get_cert_attribute;
}
cka_id = (CK_BYTE*)malloc(cert_template[4].ulValueLen);
if (cka_id == NULL) {
printf("Memory allocation failed for CKA_ID.\n");
rv = FAILED;
goto end_test_get_cert_attribute;
}
cert_template[4].pValue = cka_id;
rv = (func_list->C_GetAttributeValue)(session_rw, *cert_handle, cert_template, n_attr);
if (rv != CKR_OK) {
printf("C_GetAttributeValue failed with %ld\n", rv);
rv = FAILED;
goto end_test_get_cert_attribute;
}
C_SetAttributeValue
L'API C_SetAttributeValue supporta ora l'aggiornamento degli oggetti certificato. Richiede l'handle di sessione, l'handle del certificato da aggiornare, una matrice di attributi e i relativi nuovi valori e il numero di attributi da aggiornare. Per gli aggiornamenti sono supportati solo gli attributi elencati nella tabella Utilizzo API C_CreateObject. Se si tenta di modificare gli attributi non supportati, si verifica una chiamata API non riuscita.
Di seguito è riportato un frammento di codice che mostra come usare C_SetAttributeValue con gli oggetti certificato.
int set_cert_attribute(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE_PTR cert_handle)
{
CK_RV rv = CKR_OK;
CK_BBOOL falseValue = CK_FALSE;
CK_BYTE subjectData[] = { 0x40, 0x41, 0x42, 0x43, 0x44 };
CK_BYTE id[] = {254};
CK_BYTE certData[] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
CK_ATTRIBUTE certTemplateValid1[] = {
{ CKA_TOKEN, &falseValue, sizeof(falseValue) },
{ CKA_LABEL, "This is a new label", strlen("This is a new label") },
{ CKA_SUBJECT, subjectData, sizeof(subjectData) },
{ CKA_ID, id, sizeof(id) },
{ CKA_VALUE, certData, sizeof(certData) }
};
int n_attr = sizeof(certTemplateValid1) / sizeof(CK_ATTRIBUTE);
rv = (func_list->C_SetAttributeValue)(session_rw, *cert_handle, certTemplateValid1, n_attr);
if (rv != CKR_OK) {
printf("test_set_cert_attribute failed when updating attribute values.\n");
return FAILED;
}
return rv;
}
C_FindObjectsInit
L'API C_FindObjects* supporta ora l'individuazione di oggetti certificato oltre agli oggetti chiave. Un'operazione di ricerca può restituire handle di chiave e certificato se il modello di ricerca include attributi comuni a entrambi i tipi di oggetto. L'API C_FindObjectsInit è stata migliorata per supportare tutti gli attributi correlati al certificato elencati nella tabella Utilizzo API C_CreateObject.
Di seguito è riportato un esempio di una chiamata C_FindObjectsInit che esegue una ricerca di certificati usando gli attributi CKA_CLASS, CKA_CERTIFICATE_TYPE e CKA_LABEL per trovare tutti gli oggetti certificato corrispondenti.
int find_cert(CK_SESSION_HANDLE session_rw, CK_OBJECT_HANDLE cert_handle)
{
CK_RV rv;
CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, &objClass, sizeof(objClass) },
{ CKA_CERTIFICATE_TYPE, &certType, sizeof(certType) },
{ CKA_LABEL, "MyCertificate", 13 }
};
// Step 1: Initialize the search
rv = (func_list->C_FindObjectsInit)(session_rw, certTemplate, sizeof(certTemplate) / sizeof(CK_ATTRIBUTE));
if (rv != CKR_OK) {
printf("C_FindObjectsInit failed: 0x%lX\n", rv);
return rv;
}
C_FindObjects
Dopo l'inizializzazione dei parametri di ricerca, l'API C_FindObjects viene usata per recuperare gli handle di oggetto corrispondenti. Restituisce anche il numero di oggetti trovati. Questa API accetta l'handle di sessione, una matrice per archiviare gli handle di oggetto risultanti, il numero massimo di oggetti da recuperare e un parametro di output che indica il numero di oggetti trovati.
Il frammento di codice seguente mostra una chiamata a C_FindObjects seguendo la configurazione del modello di ricerca nell'esempio C_FindObjectsInit precedente.
// Step 2: Call C_FindObjects
CK_OBJECT_HANDLE_PTR foundObjects = NULL;
CK_ULONG maxObjects = 50;
foundObjects = (CK_OBJECT_HANDLE_PTR)malloc(sizeof(CK_OBJECT_HANDLE) * maxObjects);
if (!foundObjects) {
printf("Memory allocation failed\n");
return CKR_HOST_MEMORY;
}
CK_ULONG foundCount = 0;
rv = (func_list->C_FindObjects)(session_rw, foundObjects, maxObjects, &foundCount);
if (rv != CKR_OK) {
printf("C_FindObjects failed: 0x%lX\n", rv);
(func_list->C_FindObjectsFinal)(session_rw); // Ensure cleanup
free(foundObjects);
return rv;
}
C_FindObjectsFinal
L'API C_FindObjectsFinal si comporta allo stesso modo sia per gli oggetti chiave che per gli oggetti certificato. Accetta l'handle di sessione corrente come argomento ed esegue la pulizia della memoria e di tutte le strutture correlate alla ricerca durante la chiamata C_FindObjectsInit.
Di seguito è riportato un frammento di codice che illustra come chiamare C_FindObjectsFinal per completare e pulire il processo di ricerca avviato dalle API C_FindObjectsInit e C_FindObjects.
// Step 3: Finalize the search
rv = (func_list->C_FindObjectsFinal)(session_rw);
if (rv != CKR_OK) {
printf("C_FindObjectsFinal failed: 0x%lX\n", rv);
free(foundObjects);
return rv;
}
}
Configurare ed eseguire l'applicazione PKCS#11 con HSM cloud di Azure
Azure Cloud HSM include codice di esempio dell'applicazione per aiutare a convalidare l'archiviazione dei certificati, disponibile nella Guida all'integrazione dell'archiviazione dei certificati di Azure Cloud HSM all'interno dell'SDK di Azure Cloud HSM su GitHub.
Struttura del certificato nell'archiviazione
Verificare i certificati nell'archiviazione
Dopo la corretta chiamata all'API C_CreateObject(), l'oggetto certificato appena creato verrà visualizzato nell'account di archiviazione BLOB di Azure, come specificato nel file azcloudhsm_application.cfg. Il BLOB verrà denominato usando il formato pkcs11_certificate_<object-handle>, come illustrato di seguito. Gli oggetti certificato vengono assegnati a handle di oggetto che vanno da 0xFFF00000 a 0xFFFFFFFF (intervallo decimale: 4.293.918.720 a 4.294.967.295), consentendo il supporto per un massimo di 1.048.575 certificati.
Sia dal portale di Azure che dalla macchina virtuale di Azure è possibile visualizzare i certificati archiviati.
Verificare dal portale di Azure
Verifica dalla macchina virtuale di Azure con Azure CLI installato.
chsmVMAdmin@AdminVM:~$ az login --identity
[
{
"environmentName": "AzureCloud",
"homeTenantId": "",
"id": "",
"isDefault": true,
"managedByTenants": [],
"name": "Test Subscription",
"state": "Enabled",
"tenantId": "",
"user": {
"assignedIdentityInfo": "MSI",
"name": "systemAssignedIdentity",
"type": "servicePrincipal"
}
}
]
chsmVMAdmin@AdminVM:~$ az storage blob list \
--account-name chsmstorage \
--container-name certificates \
--auth-mode login \
--output table
Name Blob Type Blob Tier Length Content Type Last Modified
----------------------------------- ----------- ----------- -------- ------------------------ -------------------------
pkcs11_certificate_4293918720 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:43:31+00:00
pkcs11_certificate_4293918721 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:47:25+00:00
pkcs11_certificate_4293918722 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:47:25+00:00
pkcs11_certificate_4293918723 BlockBlob Hot 3452 application/octet-stream 2025-05-16T22:56:28+00:00
Il download del BLOB o la visualizzazione nel portale di Azure e l'ispezione del relativo contenuto rivelerà che il certificato viene archiviato come token JWS (firma Web JSON). Il token segue la struttura JWS standard, divisa nel formato seguente:
chsmVMAdmin@AdminVM:~$ az storage blob list \
--account-name chsmstorage \
--container-name certificates \
--auth-mode login \
--output table
Name Blob Type Blob Tier Length Content Type Last Modified
----------------------------------- ----------- ----------- -------- ------------------------ -------------------------
pkcs11_certificate_4293918720 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:43:31+00:00
pkcs11_certificate_4293918721 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:47:25+00:00
pkcs11_certificate_4293918722 BlockBlob Hot 1305 application/octet-stream 2025-05-16T22:47:25+00:00
pkcs11_certificate_4293918723 BlockBlob Hot 3452 application/octet-stream 2025-05-16T22:56:28+00:00
chsmVMAdmin@AdminVM:~$ az storage blob download \
--account-name chsmstorage \
--container-name certificates \
--name pkcs11_certificate_4293918723 \
--file pkcs11_certificate_4293918723.crt \
--auth-mode login
Finished[########################################] 100.0000%
{
"container": "certificates",
"content": ""
}
chsmVMAdmin@AdminVM:~$ cat pkcs11_certificate_4293918723.crt
eyJhbgGciOiJSUzUxMiIsImp... (base64-encoded certificate continues)
Passaggi successivi
- Esercitazione sull'archiviazione del certificato HSM del cloud di Azure: informazioni su come impostare i prerequisiti di archiviazione del certificato e configurare l'archiviazione BLOB di Azure per le applicazioni PKCS#11.
- Panoramica di Azure Cloud HSM
- Proteggi il cloud HSM di Azure