bool generateCertPKCS12()

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;
}