使用OpenSSL和TPM引擎创建自签名x509证书的实际步骤是什么? 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)将密钥blob写入文件

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)使用(3)中创建的EVP_PKEY生成证书

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引擎的大量文档 . 谢谢 .