Создание самозаверяющего сертификата x509 с использованием OpenSSL с программным обеспечением TPM
Каковы действительные шаги по созданию самозаверяющего сертификата x509 с использованием OpenSSL с механизмом TPM? X509_sign(cert, key, EVP_sha1()), кажется, терпит неудачу каждый раз для меня.
Код ошибки, который я получил от X509_sign:
Error code 2147913847
Используя ERR_print_errors_fp я получил:
3064825040:error:0D0DC006:asn1 encoding routines:func(220):EVP lib:a_sign.c:314:
То, что я сделал, было:
1) создать ключ с помощью TPM
2) записать ключевой блоб в файл
if ((outb = BIO_new_file(KEY_FILENAME, "w")) == NULL) {
fprintf(stderr, "Error opening file for write: %s\n", KEY_FILENAME);
Tspi_Context_CloseObject(tpm.hContext, hKey);
Tspi_Context_Close(tpm.hContext);
exit(-1);
}
blob_str = ASN1_OCTET_STRING_new();
if (!blob_str) {
fprintf(stderr, "Error allocating ASN1_OCTET_STRING\n");
Tspi_Context_CloseObject(tpm.hContext, hKey);
Tspi_Context_Close(tpm.hContext);
exit(-1);
}
ASN1_STRING_set(blob_str, blob, blob_size);
asn1_len = i2d_ASN1_OCTET_STRING(blob_str, &blob_asn1);
PEM_write_bio(outb, "TSS KEY BLOB", "", blob_asn1, asn1_len);
BIO_free(outb);
3) Используйте механизм TPM, чтобы прочитать файл, созданный в (2), и измените его на EVP_PKEY.
const char *engineId = "tpm";
ENGINE *e;
EVP_PKEY *key;
ENGINE_load_builtin_engines();
e = ENGINE_by_id(engineId);
if (!e) { // Engine not available
ERR_print_errors_fp(stderr);
ERR("ENGINE_by_id failed.");
return NULL;
}
if (!ENGINE_init(e)) { // Engine couldn't initialise
ERR_print_errors_fp(stderr);
ERR("ENGINE_init failed.");
ENGINE_free(e);
ENGINE_finish(e);
return NULL;
}
if (!ENGINE_set_default_RSA(e) || !ENGINE_set_default_RAND(e)) {
/* This should only happen when 'e' can't initialise, but the previous
* statement suggests it did. */
ERR_print_errors_fp(stderr);
ERR("ENGINE_init failed.");
ENGINE_free(e);
ENGINE_finish(e);
return NULL;
}
ENGINE_ctrl_cmd(e, "PIN", 0, SRK_PASSWORD, NULL, 0);
ENGINE_free(e);
if ((key = ENGINE_load_private_key(e, fileName, NULL, NULL)) == NULL) {
ERR_print_errors_fp(stderr);
ERR("Couldn't load TPM key \"%s\" from file.", fileName);
return NULL;
}
ENGINE_finish(e);
e = NULL;
4) Создайте сертификат, используя EVP_PKEY, созданный в (3)
X509 *cert;
X509_NAME *name = NULL;
FILE * fp = NULL;
// pk = key;
cert = X509_new();
X509_set_version(cert, 2);
// serial = M_ASN1_INTEGER_new();
ASN1_INTEGER_set(X509_get_serialNumber(cert), 0);
X509_gmtime_adj(X509_get_notBefore(cert), 0);
X509_gmtime_adj(X509_get_notAfter(cert), (long)60 * 60 * 24 * CERT_VALIDITY);
X509_set_pubkey(cert, key);
name = X509_get_subject_name(cert);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char *)"SG", -1, -1, 0); //country
X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (const unsigned char *)"SG", -1, -1, 0); //state
X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (const unsigned char *)"Singapore", -1, -1, 0); //locality
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (const unsigned char *)"org", -1, -1, 0); //organisation
X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (const unsigned char *)"unit", -1, -1, 0); //organisational unit
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char *)"name", -1, -1, 0); //common name
X509_set_issuer_name(cert, name); // Its self signed so set the issuer name to be the same as the subject.
PEM_write_PrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL);
PEM_write_PUBKEY(stdout, key);
if (!X509_sign(cert, key, EVP_sha1())) {
printf("Error signing certificate\n");
printf("Error code %lu\n", ERR_get_error());
ERR_print_errors_fp(stderr);
return;
} else {
PEM_write_X509(stdout, cert);
fp = fopen("x509.cert", "wb");
if (fp != NULL) {
i2d_X509_fp(fp, cert);
}
fclose(fp);
X509_free(cert);
}
Я что-то делаю неправильно? Пожалуйста, помогите, я не могу найти много документации по использованию OpenSSL с механизмом TPM. Благодарю.