in xplat/Flipper/CertificateUtils.cpp [237:373]
bool generateCertPKCS12(
const char* cacertFilepath,
const char* certFilepath,
const char* keyFilepath,
const char* pkcs12Filepath,
const char* pkcs12Name,
const char* pkcs12Password) {
X509 *cert = NULL, *cacert = NULL;
STACK_OF(X509)* cacertstack = NULL;
PKCS12* pkcs12bundle = NULL;
EVP_PKEY* cert_privkey = NULL;
FILE *cacertfile = NULL, *certfile = NULL, *keyfile = NULL,
*pkcs12file = NULL;
int bytes = 0;
/* 1) These function calls are essential to make PEM_read and
* other openssl functions work.
*/
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* 2) load the certificate's private key
*/
if ((cert_privkey = EVP_PKEY_new()) == NULL) {
return false;
}
if (!(keyfile = fopen(keyFilepath, "r"))) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
if (!(cert_privkey = PEM_read_PrivateKey(keyfile, NULL, NULL, NULL))) {
fclose(keyfile);
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
fclose(keyfile);
/* 3) Load the corresponding certificate
*/
if (!(certfile = fopen(certFilepath, "r"))) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
if (!(cert = PEM_read_X509(certfile, NULL, NULL, NULL))) {
fclose(certfile);
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
fclose(certfile);
/* 4) Load the CA certificate who signed it
*/
if (!(cacertfile = fopen(cacertFilepath, "r"))) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
if (!(cacert = PEM_read_X509(cacertfile, NULL, NULL, NULL))) {
fclose(cacertfile);
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
fclose(cacertfile);
/* 5) Load the CA certificate on the stack
*/
if ((cacertstack = sk_X509_new_null()) == NULL) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
sk_X509_push(cacertstack, cacert);
/* 6) we create the PKCS12 structure and fill it with our data
*/
if ((pkcs12bundle = PKCS12_new()) == NULL) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
/* values of zero use the openssl default values */
pkcs12bundle = PKCS12_create(
const_cast<char*>(pkcs12Password), // certbundle access password
const_cast<char*>(pkcs12Name), // friendly certificate name
cert_privkey, // the certificate private key
cert, // the main certificate
cacertstack, // stack of CA cert chain
0, // int nid_key (default 3DES)
0, // int nid_cert (40bitRC2)
0, // int iter (default 2048)
0, // int mac_iter (default 1)
0 // int keytype (default no flag)
);
if (pkcs12bundle == nullptr) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
/* 7) Write the PKCS12 structure out to file
*/
if (!(pkcs12file = fopen(pkcs12Filepath, "w"))) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
bytes = i2d_PKCS12_fp(pkcs12file, pkcs12bundle);
if (bytes <= 0) {
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return false;
}
/* 8) Done, free resources.
*/
fclose(pkcs12file);
generateCertPKCS12_free(
cacert, cert, cert_privkey, cacertstack, pkcs12bundle);
return true;
}