// File: /workspace/github_c_makefile_star2_O2/fm4dd[P]learn-ssl/certcreate.c
// Function: main
int main() {

  ASN1_INTEGER                 *aserial = NULL;
  EVP_PKEY                     *ca_privkey, *req_pubkey;
  EVP_MD                       const *digest = NULL;
  X509                         *newcert, *cacert;
  X509_NAME                    *name;
  X509V3_CTX                   ctx;
  FILE                         *fp;
  long                         valid_secs = 31536000;

  /* ---------------------------------------------------------- *
   * Create the Input/Output BIO's.                             *
   * ---------------------------------------------------------- */
  outbio  = BIO_new(BIO_s_file());
  outbio = BIO_new_fp(stdout, BIO_NOCLOSE);

  /* ---------------------------------------------------------- *
   * Load the request data in a BIO, then in a x509_REQ struct. *
   * ---------------------------------------------------------- */
  reqbio = BIO_new_mem_buf(request_str, -1);

  if (! (certreq = PEM_read_bio_X509_REQ(reqbio, NULL, NULL, NULL))) {
    BIO_printf(outbio, "Error can't read X509 request data into memory\n");
    exit(1);
   }

  /* -------------------------------------------------------- *
   * Load ithe signing CA Certificate file                    *
   * ---------------------------------------------------------*/
  if (! (fp=fopen(CACERT, "r"))) {
    BIO_printf(outbio, "Error reading CA cert file %s\n", CACERT);
    exit(1);
   }

  if(! (cacert = PEM_read_X509(fp,NULL,NULL,NULL))) {
    BIO_printf(outbio, "Error loading CA cert into memory\n");
    exit(1);
   }

  fclose(fp);

  /* -------------------------------------------------------- *
   * Import CA private key file for signing                   *
   * ---------------------------------------------------------*/
  ca_privkey = EVP_PKEY_new();

  if (! (fp = fopen (CAKEY, "r"))) {
    BIO_printf(outbio, "Error reading CA private key file: %s\n", CAKEY);
    exit(1);
   }

  if (! (ca_privkey = PEM_read_PrivateKey( fp, NULL, NULL, PASS))) {
    BIO_printf(outbio, "Error importing key content from file: %s\n", CAKEY);
    exit(1);
   }

  fclose(fp);

  /* --------------------------------------------------------- *
   * Build Certificate with data from request                  *
   * ----------------------------------------------------------*/
  if (! (newcert=X509_new())) {
    BIO_printf(outbio, "Error creating new X509 object\n");
    exit(1);
   }

  if (X509_set_version(newcert, 2) != 1) {
    BIO_printf(outbio, "Error setting certificate version\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * set the certificate serial number here                    *
   * If there is a problem, the value defaults to '0'          *
   * ----------------------------------------------------------*/
  aserial=ASN1_INTEGER_new();
  ASN1_INTEGER_set(aserial, 0);
  if (! X509_set_serialNumber(newcert, aserial)) {
    BIO_printf(outbio, "Error setting serial number of the certificate\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Extract the subject name from the request                 *
   * ----------------------------------------------------------*/
  if (! (name = X509_REQ_get_subject_name(certreq)))
    BIO_printf(outbio, "Error getting subject from cert request\n");

  /* --------------------------------------------------------- *
   * Set the new certificate subject name                      *
   * ----------------------------------------------------------*/
  if (X509_set_subject_name(newcert, name) != 1) {
    BIO_printf(outbio, "Error setting subject name of certificate\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Extract the subject name from the signing CA cert         *
   * ----------------------------------------------------------*/
  if (! (name = X509_get_subject_name(cacert))) {
    BIO_printf(outbio, "Error getting subject from CA certificate\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Set the new certificate issuer name                       *
   * ----------------------------------------------------------*/
  if (X509_set_issuer_name(newcert, name) != 1) {
    BIO_printf(outbio, "Error setting issuer name of certificate\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Extract the public key data from the request              *
   * ----------------------------------------------------------*/
  if (! (req_pubkey=X509_REQ_get_pubkey(certreq))) {
    BIO_printf(outbio, "Error unpacking public key from request\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Optionally: Use the public key to verify the signature    *
   * ----------------------------------------------------------*/
  if (X509_REQ_verify(certreq, req_pubkey) != 1) {
    BIO_printf(outbio, "Error verifying signature on request\n");
    exit(1);
   }

  /* --------------------------------------------------------- *
   * Set the new certificate public key                        *
   * ----------------------------------------------------------*/
  if (X509_set_pubkey(newcert, req_pubkey) != 1) {
    BIO_printf(outbio, "Error setting public key of certificate\n");
    exit(1);
   }

  /* ---------------------------------------------------------- *
   * Set X509V3 start date (now) and expiration date (+365 days)*
   * -----------------------------------------------------------*/
   if (! (X509_gmtime_adj(X509_get_notBefore(newcert),0))) {
      BIO_printf(outbio, "Error setting start time\n");
    exit(1);
   }

   if(! (X509_gmtime_adj(X509_get_notAfter(newcert), valid_secs))) {
      BIO_printf(outbio, "Error setting expiration time\n");
    exit(1);
   }

  /* ----------------------------------------------------------- *
   * Add X509V3 extensions                                       *
   * ------------------------------------------------------------*/
  X509V3_set_ctx(&ctx, cacert, newcert, NULL, NULL, 0);

  /* ----------------------------------------------------------- *
   * Set digest type, sign new certificate with CA's private key *
   * ------------------------------------------------------------*/
  digest = EVP_sha256();

  if (! X509_sign(newcert, ca_privkey, digest)) {
    BIO_printf(outbio, "Error signing the new certificate\n");
    exit(1);
   }

  /* ------------------------------------------------------------ *
   *  print the certificate                                       *
   * -------------------------------------------------------------*/
  if (! PEM_write_bio_X509(outbio, newcert)) {
    BIO_printf(outbio, "Error printing the signed certificate\n");
    exit(1);
   }

  /* ---------------------------------------------------------- *
   * Free up all structures                                     *
   * ---------------------------------------------------------- */
  EVP_PKEY_free(req_pubkey);
  EVP_PKEY_free(ca_privkey);
  X509_REQ_free(certreq);
  X509_free(newcert);
  BIO_free_all(reqbio);
  BIO_free_all(outbio);

  exit(0);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x48, %rsp
callq 0x1050
movq %rax, %rdi
callq 0x11f0
movq %rax, 0x2f85(%rip)      # 0x4300
movq 0x2c4e(%rip), %rax      # 0x3fd0
movq (%rax), %rdi
xorl %esi, %esi
callq 0x1100
movq %rax, 0x2f6d(%rip)      # 0x4300
leaq 0x2da6(%rip), %rdi      # 0x4140
pushq $-0x1
popq %rsi
callq 0x1040
movq %rax, 0x2f4f(%rip)      # 0x42f8
movq %rax, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x1120
movq %rax, 0x2f52(%rip)      # 0x4310
testq %rax, %rax
jne 0x13dd
movq 0x2f36(%rip), %rdi      # 0x4300
leaq 0xc33(%rip), %rsi       # 0x2004
xorl %eax, %eax
callq 0x1250
jmp 0x14a4
leaq 0xc50(%rip), %rdi       # 0x2034
leaq 0xc5b(%rip), %rsi       # 0x2046
callq 0x1160
testq %rax, %rax
jne 0x140f
movq 0x2f04(%rip), %rdi      # 0x4300
leaq 0xc45(%rip), %rsi       # 0x2048
leaq 0xc2a(%rip), %rdx       # 0x2034
jmp 0x149d
movq %rax, %rbx
movq %rax, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x11a0
testq %rax, %rax
jne 0x1435
movq 0x2ed4(%rip), %rdi      # 0x4300
leaq 0xc34(%rip), %rsi       # 0x2067
jmp 0x13d1
movq %rax, %r15
movq %rbx, %rdi
callq 0x1130
callq 0x1210
leaq 0xc3e(%rip), %rdi       # 0x208a
leaq 0xbf3(%rip), %rsi       # 0x2046
callq 0x1160
testq %rax, %rax
jne 0x146d
movq 0x2e9c(%rip), %rdi      # 0x4300
leaq 0xc31(%rip), %rsi       # 0x209c
jmp 0x1496
movq %rax, %r14
leaq 0xc4c(%rip), %rcx       # 0x20c3
movq %rax, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x1110
testq %rax, %rax
jne 0x14ac
movq 0x2e71(%rip), %rdi      # 0x4300
leaq 0xc3c(%rip), %rsi       # 0x20d2
leaq 0xbed(%rip), %rdx       # 0x208a
xorl %eax, %eax
callq 0x1250
pushq $0x1
popq %rdi
callq 0x1170
movq %rax, %rbx
movq %r14, %rdi
callq 0x1130
callq 0x1030
testq %rax, %rax
jne 0x14d4
movq 0x2e38(%rip), %rdi      # 0x4300
leaq 0xc2e(%rip), %rsi       # 0x20fd
jmp 0x13d1
movq %rax, %r14
pushq $0x2
popq %rsi
movq %rax, %rdi
callq 0x1080
cmpl $0x1, %eax
jne 0x151b
callq 0x1240
movq %rax, %r12
movq %rax, %rdi
xorl %esi, %esi
callq 0x10f0
movq %r14, %rdi
movq %r12, %rsi
callq 0x11c0
testl %eax, %eax
jne 0x152e
movq 0x2df1(%rip), %rdi      # 0x4300
leaq 0xc2a(%rip), %rsi       # 0x2140
jmp 0x13d1
movq 0x2dde(%rip), %rdi      # 0x4300
leaq 0xbf4(%rip), %rsi       # 0x211d
jmp 0x13d1
movq 0x2ddb(%rip), %rdi      # 0x4310
callq 0x1140
movq %rax, %r12
testq %rax, %rax
jne 0x1557
movq 0x2db7(%rip), %rdi      # 0x4300
leaq 0xc20(%rip), %rsi       # 0x2170
xorl %eax, %eax
callq 0x1250
movq %r14, %rdi
movq %r12, %rsi
callq 0x11b0
cmpl $0x1, %eax
jne 0x1587
movq %r15, %rdi
callq 0x1150
testq %rax, %rax
jne 0x159a
movq 0x2d85(%rip), %rdi      # 0x4300
leaq 0xc42(%rip), %rsi       # 0x21c4
jmp 0x13d1
movq 0x2d72(%rip), %rdi      # 0x4300
leaq 0xc04(%rip), %rsi       # 0x2199
jmp 0x13d1
movq %r14, %rdi
movq %rax, %rsi
callq 0x10a0
cmpl $0x1, %eax
jne 0x15ce
movq 0x2d5f(%rip), %rdi      # 0x4310
callq 0x1090
testq %rax, %rax
jne 0x15e1
movq 0x2d3e(%rip), %rdi      # 0x4300
leaq 0xc50(%rip), %rsi       # 0x2219
jmp 0x13d1
movq 0x2d2b(%rip), %rdi      # 0x4300
leaq 0xc13(%rip), %rsi       # 0x21ef
jmp 0x13d1
movq %rax, %r12
movq 0x2d25(%rip), %rdi      # 0x4310
movq %rax, %rsi
callq 0x11d0
cmpl $0x1, %eax
jne 0x1632
movq %r14, %rdi
movq %r12, %rsi
callq 0x10d0
cmpl $0x1, %eax
jne 0x1645
movq %r14, %rdi
callq 0x1230
movq %rax, %rdi
xorl %esi, %esi
callq 0x11e0
testq %rax, %rax
jne 0x1658
movq 0x2cda(%rip), %rdi      # 0x4300
leaq 0xc64(%rip), %rsi       # 0x2291
jmp 0x13d1
movq 0x2cc7(%rip), %rdi      # 0x4300
leaq 0xc02(%rip), %rsi       # 0x2242
jmp 0x13d1
movq 0x2cb4(%rip), %rdi      # 0x4300
leaq 0xc15(%rip), %rsi       # 0x2268
jmp 0x13d1
movq %r14, %rdi
callq 0x1060
movl $0x1e13380, %esi        # imm = 0x1E13380
movq %rax, %rdi
callq 0x11e0
testq %rax, %rax
jne 0x1685
movq 0x2c87(%rip), %rdi      # 0x4300
leaq 0xc2b(%rip), %rsi       # 0x22ab
jmp 0x13d1
leaq 0x8(%rsp), %rdi
movq %r15, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x1220
callq 0x1200
movq %r14, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x10b0
movq 0x2c49(%rip), %rdi      # 0x4300
testl %eax, %eax
jne 0x16c7
leaq 0xc08(%rip), %rsi       # 0x22ca
jmp 0x13d1
movq %r14, %rsi
callq 0x1180
testl %eax, %eax
jne 0x16e6
movq 0x2c26(%rip), %rdi      # 0x4300
leaq 0xc0c(%rip), %rsi       # 0x22ed
jmp 0x13d1
movq %r12, %rdi
callq 0x10e0
movq %rbx, %rdi
callq 0x10e0
movq 0x2c13(%rip), %rdi      # 0x4310
callq 0x1190
movq %r14, %rdi
callq 0x10c0
movq 0x2be7(%rip), %rdi      # 0x42f8
callq 0x1070
movq 0x2be3(%rip), %rdi      # 0x4300
callq 0x1070
xorl %edi, %edi
callq 0x1170