Skip to content

Instantly share code, notes, and snippets.

@babelouest
Last active September 15, 2019 00:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save babelouest/b239099b209176376e7bf2640429ba87 to your computer and use it in GitHub Desktop.
Save babelouest/b239099b209176376e7bf2640429ba87 to your computer and use it in GitHub Desktop.
/**
*
* gnutls_generate_pkcs12.c
*
* Generate a new RSA key
* Generate the associated certificate
* Sign the certificate with the issuer key and certificate
* Create the PKCS#12 structure and exports it to the file out.p12 protected with the password PASSWORD
*
* License: MIT
*
*/
#include <stdio.h>
#include <string.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/abstract.h>
#include <gnutls/pkcs12.h>
#define EXPIRATION 60*60*24*512
#define DN "cn=localhost,dc=glewlwyd,dc=babelouest,dc=org"
#define PASSWORD "password"
#define FRIENDLY_NAME "My name"
#define OUTFILE "out.p12"
unsigned char key_issuer_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n\
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\n\
-----END RSA PRIVATE KEY-----";
unsigned char cert_issuer_pem[] = "-----BEGIN CERTIFICATE-----\n\
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\n\
-----END CERTIFICATE-----";
gnutls_x509_privkey_t privkey_x509 = NULL;
gnutls_x509_crt_t crt = NULL;
gnutls_privkey_t privkey = NULL;
int generate_pkcs12() {
gnutls_pkcs12_t pkcs12;
int res, bag_index;
gnutls_pkcs12_bag_t bag, key_bag;
char pkcs12_struct[10 * 1024];
unsigned char key_id_dat[1024];
size_t pkcs12_struct_size, key_id_dat_size = 1024;
FILE *fd;
gnutls_datum_t key_id = {NULL, 0}, cert_dat = {NULL, 0}, key_dat = {NULL, 0};
do {
if ((res = gnutls_x509_privkey_get_key_id(privkey_x509, 0, key_id_dat, &key_id_dat_size)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_get_key_id: %d\n", res);
break;
}
key_id.data = key_id_dat;
key_id.size = key_id_dat_size;
if ((res = gnutls_pkcs12_bag_init(&bag)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_init: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_init(&key_bag)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_init: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &cert_dat)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_export2: %d\n", res);
break;
}
if ((res = gnutls_x509_privkey_export2_pkcs8(privkey_x509, GNUTLS_X509_FMT_DER, PASSWORD, GNUTLS_PKCS_USE_PBES2_AES_128, &key_dat)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_export2_pkcs8: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_set_data(bag, GNUTLS_BAG_CERTIFICATE, &cert_dat)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_data: %d\n", res);
break;
}
bag_index = res;
if ((res = gnutls_pkcs12_bag_set_friendly_name(bag, bag_index, FRIENDLY_NAME)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_friendly_name: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_set_key_id(bag, bag_index, &key_id)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_key_id: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_encrypt(bag, PASSWORD, GNUTLS_PKCS_USE_PKCS12_RC2_40)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_encrypt: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_set_data(key_bag, GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &key_dat)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_data: %d\n", res);
break;
}
bag_index = res;
if ((res = gnutls_pkcs12_bag_set_friendly_name(key_bag, bag_index, FRIENDLY_NAME)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_friendly_name: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_bag_set_key_id(key_bag, bag_index, &key_id)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_bag_set_key_id: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_init(&pkcs12)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_init: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_set_bag(pkcs12, bag)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_set_bag: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_set_bag(pkcs12, key_bag)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_set_bag: %d\n", res);
break;
}
if ((res = gnutls_pkcs12_generate_mac(pkcs12, PASSWORD)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_generate_mac: %d\n", res);
break;
}
pkcs12_struct_size = sizeof(pkcs12_struct);
if ((res = gnutls_pkcs12_export(pkcs12, GNUTLS_X509_FMT_PEM, pkcs12_struct, &pkcs12_struct_size)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_export: %d\n", res);
break;
} else {
printf("pkcs12:\n%.*s\n", (int)pkcs12_struct_size, pkcs12_struct);
}
pkcs12_struct_size = sizeof(pkcs12_struct);
if ((res = gnutls_pkcs12_export(pkcs12, GNUTLS_X509_FMT_DER, pkcs12_struct, &pkcs12_struct_size)) < 0) {
fprintf(stderr, "error gnutls_pkcs12_export: %d\n", res);
break;
}
fd = fopen(OUTFILE, "w");
if (fd == NULL) {
fprintf(stderr, "cannot open file %s\n", OUTFILE);
}
fwrite(pkcs12_struct, 1, pkcs12_struct_size, fd);
fclose(fd);
} while (0);
gnutls_pkcs12_bag_deinit(bag);
gnutls_pkcs12_bag_deinit(key_bag);
gnutls_pkcs12_deinit(pkcs12);
gnutls_free(cert_dat.data);
gnutls_free(key_dat.data);
return 0;
}
void generate_key_cert() {
gnutls_x509_privkey_t key_issuer = NULL;
gnutls_x509_crt_t crt_issuer = NULL;
gnutls_datum_t dat;
time_t now, exp;
const char * err = NULL;
char crt_export[1024*16] = {0};
size_t crt_export_len = 1024*16;
int res, serial = 42;
time(&now);
exp = now + EXPIRATION;
do {
if ((res = gnutls_x509_privkey_init(&key_issuer)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_init: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_init(&crt_issuer)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_init: %d\n", res);
break;
}
dat.data = key_issuer_pem;
dat.size = strlen((const char *)key_issuer_pem);
if ((res = gnutls_x509_privkey_import(key_issuer, &dat, GNUTLS_X509_FMT_PEM)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_import: %d\n", res);
break;
}
dat.data = cert_issuer_pem;
dat.size = strlen((const char *)cert_issuer_pem);
if ((res = gnutls_x509_crt_import(crt_issuer, &dat, GNUTLS_X509_FMT_PEM)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_import: %d\n", res);
break;
}
if ((res = gnutls_x509_privkey_generate(privkey_x509, GNUTLS_PK_RSA, gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, GNUTLS_SEC_PARAM_MEDIUM), GNUTLS_PRIVKEY_FLAG_PROVABLE)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_generate: %d\n", res);
break;
}
if ((res = gnutls_privkey_import_x509(privkey, privkey_x509, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE)) < 0) {
fprintf(stderr, "error gnutls_privkey_import_x509: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_set_key(crt, privkey_x509)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_set_key: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_set_expiration_time(crt, exp)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_set_expiration_time: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_set_activation_time(crt, now)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_set_activation_time: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_set_serial(crt, &serial, sizeof(int))) < 0) {
fprintf(stderr, "error gnutls_x509_crt_set_serial: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_set_dn(crt, DN, &err)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_set_dn: %d\n", res);
break;
}
if ((res = gnutls_x509_crt_sign2(crt, crt_issuer, key_issuer, GNUTLS_DIG_SHA256, 0)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_sign2: %d\n", res);
break;
}
if ((res = gnutls_x509_privkey_export(privkey_x509, GNUTLS_X509_FMT_PEM, crt_export, &crt_export_len)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_export: %d\n", res);
break;
}
printf("privkey:\n%.*s\n", (int)crt_export_len, crt_export);
if ((res = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, crt_export, &crt_export_len)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_export: %d\n", res);
break;
}
printf("cert:\n%.*s\n\n", (int)crt_export_len, crt_export);
} while (0);
if (key_issuer)
gnutls_x509_privkey_deinit(key_issuer);
if (crt_issuer)
gnutls_x509_crt_deinit(crt_issuer);
}
int main() {
int res;
if ((res = gnutls_x509_privkey_init(&privkey_x509)) < 0) {
fprintf(stderr, "error gnutls_x509_privkey_init: %d\n", res);
return 1;
}
if ((res = gnutls_privkey_init(&privkey)) < 0) {
fprintf(stderr, "error gnutls_privkey_init: %d\n", res);
return 1;
}
if ((res = gnutls_x509_crt_init(&crt)) < 0) {
fprintf(stderr, "error gnutls_x509_crt_init: %d\n", res);
return 1;
}
generate_key_cert();
generate_pkcs12();
if (crt)
gnutls_x509_crt_deinit(crt);
if (privkey)
gnutls_privkey_deinit(privkey);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment