Question

I am trying to write an application which will create a self signed certificate with supplied distinguished names.

I have the following application which creates a .key and a .csr file.

#include <stdio.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>

#define _RAND_FILENAME  "/dev/random"
#define _RAND_LOADSIZE  128
#define _RSA_KEYSIZE    1024


int build_and_save_csr(int dn_entries, char *dn_fields[], char *dn_values[], FILE *req_f, FILE *priv_f)
{
    X509_REQ    *req_p;
    EVP_PKEY    *key_p;
    RSA     *rsa_p;
    X509_NAME   *name_p = NULL;
    int     priv_len;
    unsigned char   *priv_p;
    int     i;

    if (!(req_p = X509_REQ_new())) {
        fprintf(stderr, "X509_REQ_new() failed\n");
        return -1;
    }

    if (!(key_p = EVP_PKEY_new())) {
        X509_REQ_free(req_p);
        fprintf(stderr, "EVP_PKEY_new() failed\n");
        return -1;
    }

#if 0
    if (RAND_load_file(_RAND_FILENAME, _RAND_LOADSIZE) != _RAND_LOADSIZE) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "RAND_load_file() failed\n");
        return -1;
    }
#endif

    if (!(rsa_p = RSA_generate_key(_RSA_KEYSIZE, RSA_F4, NULL, NULL))) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "RSA key generatione failed\n");
        return -1;
    }

    if (!EVP_PKEY_assign_RSA(key_p, rsa_p)) {
        X509_REQ_free(req_p);
        RSA_free(rsa_p);
        EVP_PKEY_free(key_p);
        return -1;
    }
    /*!!! the memory for rsa_p is now managed by key_p - don't free! */


    if (!X509_REQ_set_version(req_p, 0L)        /* Version 1 */
     || !X509_REQ_set_pubkey(req_p, key_p)) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "Failed to set stuff on X509_REQ\n");
        return -1;
    }

    if (!(name_p  = X509_REQ_get_subject_name(req_p))) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "Failed to make get X509_REQ_get_subject_name\n");
        return -1;
    }

    /* Build the DN */
    for (i = 0; i < dn_entries; i++) {
        if (!X509_NAME_add_entry_by_txt(name_p, dn_fields[i], MBSTRING_ASC,
                dn_values[i], -1, -1, 0)) {
            X509_REQ_free(req_p);
            EVP_PKEY_free(key_p);
            fprintf(stderr, "Failed to make the X509_NAME\n");
            return -1;
        }
    }

    if (!X509_REQ_sign(req_p, key_p, EVP_sha1())) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "X509_REQ_sign() failed\n");
        return -1;
    }

    /* save the private key to file (PKCS#1) */
    priv_p = NULL;
    priv_len = i2d_RSAPrivateKey(rsa_p, &priv_p);
    fwrite(priv_p, priv_len, 1, priv_f);
    OPENSSL_free(priv_p);

    EVP_PKEY_free(key_p);   /* nolonger need the EVP structure */

    /* save the CSR to file (PKCS#10) */
    i2d_X509_REQ_fp(req_f, req_p);
    X509_REQ_free(req_p);

    return 0;
}

int main(int argc, char *argv[])
{
    char    *dn_fields[] = { "O", "CN" };
    char    *dn_values[] = { "My Application", "tomcelic@selleck.com" };
    FILE    *req_f, *priv_f;

    req_f = fopen("selleck.csr", "w");
    priv_f = fopen("selleck.key", "w");

    if (build_and_save_csr(2, dn_fields, dn_values, req_f, priv_f) != 0) {
        fprintf(stderr, "Oh bother...\n");
        fclose(req_f);
        fclose(priv_f);
        exit(1);
    }

    fclose(req_f);
    fclose(priv_f);
    return 0;
}

I presume this line could be swapped for one which creates a self signed cert instead of a sign request??

/* save the CSR to file (PKCS#10) */
i2d_X509_REQ_fp(req_f, req_p);

This is all totally new to me so I would appreciate any advice!

Was it helpful?

Solution

I presume this line could be swapped for one which creates a self signed cert instead of a sign request??

No, I'm sorry it's no so easy.

The X509_REQ is not the correct structure to create a self signed certificate. It's just for CSR (Certificate Sign Request) management, so the main structure and the functions (with the _REQ suffix) are not valid for your pourpose.

But, the process of a self signed certificate creation it's really close to this one (the CSR it's self signed as you can notice in the X509_REQ_sign call.).

Here you can find a very complete and exhaustive answer of the entire process, and here an example of a self-signed creation.

As explanation i2d_X509_REQ_fp it's used to save the X509 CSR to a PKCS#10 format, Info.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top