verdnatura-chat/ios/Pods/Flipper/xplat/Flipper/CertificateUtils.cpp

225 lines
4.8 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "CertificateUtils.h"
#include <fcntl.h>
#include <folly/portability/Fcntl.h>
#include <folly/portability/SysStat.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <cstring>
void free(
EVP_PKEY* pKey,
X509_REQ* x509_req,
BIGNUM* bne,
BIO* privateKey,
BIO* csrBio);
bool generateCertSigningRequest(
const char* appId,
const char* csrFile,
const char* privateKeyFile) {
int ret = 0;
BIGNUM* bne = NULL;
int nVersion = 1;
int bits = 2048;
// Using 65537 as exponent
unsigned long e = RSA_F4;
X509_NAME* x509_name = NULL;
const char* subjectCountry = "US";
const char* subjectProvince = "CA";
const char* subjectCity = "Menlo Park";
const char* subjectOrganization = "Flipper";
const char* subjectCommon = appId;
X509_REQ* x509_req = X509_REQ_new();
EVP_PKEY* pKey = EVP_PKEY_new();
RSA* rsa = RSA_new();
BIO* privateKey = NULL;
BIO* csrBio = NULL;
EVP_PKEY_assign_RSA(pKey, rsa);
// Generate rsa key
bne = BN_new();
BN_set_flags(bne, BN_FLG_CONSTTIME);
ret = BN_set_word(bne, e);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
{
// Write private key to a file
int privateKeyFd =
open(privateKeyFile, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR);
if (privateKeyFd < 0) {
free(pKey, x509_req, bne, privateKey, csrBio);
return -1;
}
FILE* privateKeyFp = fdopen(privateKeyFd, "w");
if (privateKeyFp == NULL) {
free(pKey, x509_req, bne, privateKey, csrBio);
return -1;
}
privateKey = BIO_new_fp(privateKeyFp, BIO_CLOSE);
ret =
PEM_write_bio_RSAPrivateKey(privateKey, rsa, NULL, NULL, 0, NULL, NULL);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
}
rsa = NULL;
ret = BIO_flush(privateKey);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_REQ_set_version(x509_req, nVersion);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
x509_name = X509_REQ_get_subject_name(x509_req);
ret = X509_NAME_add_entry_by_txt(
x509_name,
"C",
MBSTRING_ASC,
(const unsigned char*)subjectCountry,
-1,
-1,
0);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_NAME_add_entry_by_txt(
x509_name,
"ST",
MBSTRING_ASC,
(const unsigned char*)subjectProvince,
-1,
-1,
0);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_NAME_add_entry_by_txt(
x509_name,
"L",
MBSTRING_ASC,
(const unsigned char*)subjectCity,
-1,
-1,
0);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_NAME_add_entry_by_txt(
x509_name,
"O",
MBSTRING_ASC,
(const unsigned char*)subjectOrganization,
-1,
-1,
0);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_NAME_add_entry_by_txt(
x509_name,
"CN",
MBSTRING_ASC,
(const unsigned char*)subjectCommon,
-1,
-1,
0);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_REQ_set_pubkey(x509_req, pKey);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
ret = X509_REQ_sign(
x509_req, pKey, EVP_sha256()); // returns x509_req->signature->length
if (ret <= 0) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
{
// Write CSR to a file
int csrFd = open(csrFile, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR);
if (csrFd < 0) {
free(pKey, x509_req, bne, privateKey, csrBio);
return -1;
}
FILE* csrFp = fdopen(csrFd, "w");
if (csrFp == NULL) {
free(pKey, x509_req, bne, privateKey, csrBio);
return -1;
}
csrBio = BIO_new_fp(csrFp, BIO_CLOSE);
ret = PEM_write_bio_X509_REQ(csrBio, x509_req);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
}
ret = BIO_flush(csrBio);
if (ret != 1) {
free(pKey, x509_req, bne, privateKey, csrBio);
return ret;
}
return (ret == 1);
}
void free(
EVP_PKEY* pKey,
X509_REQ* x509_req,
BIGNUM* bne,
BIO* privateKey,
BIO* csrBio) {
BN_free(bne);
X509_REQ_free(x509_req);
EVP_PKEY_free(pKey);
BIO_free_all(privateKey);
BIO_free_all(csrBio);
}