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

  const char cert_filestr[] = "./demo/cert-file.pem";
  const char pkey_filestr[] = "./demo/cert-file.key";
  const unsigned char cleartextstr[] = "This line will be encrypted and, if keys match, it decrypts again.";

          EVP_PKEY *privkey = NULL;
           EVP_PKEY *pubkey = NULL;
  BIO              *certbio = NULL;
  BIO              *pkeybio = NULL;
  X509                *cert = NULL;
  int i, enc_len, dec_len;

#if OPENSSL_VERSION_NUMBER < 0x30000000L
  /* ---------------------------------------------------------- *
   * These function calls initialize openssl for correct work.  *
   * ---------------------------------------------------------- */
  OpenSSL_add_all_algorithms();
  ERR_load_BIO_strings();
  ERR_load_crypto_strings();
#endif

  /* ---------------------------------------------------------- *
   * Create the Input/Output BIO's.                             *
   * ---------------------------------------------------------- */
  certbio = BIO_new(BIO_s_file());
  pkeybio = BIO_new(BIO_s_file());

  /* ---------------------------------------------------------- *
   * Load the certificate from file (PEM).                      *
   * ---------------------------------------------------------- */
  ret = BIO_read_filename(certbio, cert_filestr);
  if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
    printf("Error loading cert into memory\n");
    exit(1);
  }

  /* ---------------------------------------------------------- *
   * Load the private key from file (PEM).                      *
   * ---------------------------------------------------------- */
  ret = BIO_read_filename(pkeybio, pkey_filestr);
  if (! (privkey = PEM_read_bio_PrivateKey(pkeybio, NULL, 0, NULL))) {
    printf("Error loading private key into memory\n");
    exit(1);
  }

  /* ---------------------------------------------------------- *
   * Extract the certificate's public key data.                 *
   * ---------------------------------------------------------- */
  if ((pubkey = X509_get_pubkey(cert)) == NULL) {
    printf("Error getting public key from certificate");
    exit(1);
  }

  /* ---------------------------------------------------------- *
   * Print the public key information and the key in PEM format *
   * ---------------------------------------------------------- */
  /* display the key type and size here */
  if (pubkey) {
    teststr_len = strlen( (const char *) cleartextstr);

    switch (EVP_PKEY_id(pubkey)) {
      case EVP_PKEY_RSA:
        printf("Detected RSA pubkey [%d bit]. RSA modulus (n) check:\n", EVP_PKEY_bits(pubkey));
        if(RSAcmp_mod(privkey, pubkey) == 0)
          printf("Success: RSA modulus (n) matches between public and private key parts\n\n");
        else
          printf("Failure: RSA modulus (n) mismatch between public and private key parts\n\n");

        printf("Cleartext string check [%d bytes]:\n\"%s\"\n\n",
                       (int) teststr_len, cleartextstr);
        printf("Encrypting text with RSA public key [%d bit]. ", EVP_PKEY_bits(pubkey));
        enc_len = RSAencrypt(pubkey, cleartextstr);
        printf("Encrypted data (hex) [%d bytes]:\n", enc_len);
        for(i=0;i<enc_len;i++) { printf("%02x ", encdata[i]); }

        printf("\n\nDecrypting with RSA private key [%d bit]. ", EVP_PKEY_bits(privkey));
        dec_len = RSAdecrypt(privkey, enc_len);
        if (dec_len == -1) 
         printf("Failure: Keys don't match!");
        else {
          printf("Decrypted data [%d bytes]:\n\"%s\"\n", dec_len, decdata);
        }
        break;
      case EVP_PKEY_EC:
        printf("Detected EC Key[%d bit].\n\n", EVP_PKEY_bits(pubkey));
        printf("Creating signature with EC private key [%d bit]. ", EVP_PKEY_bits(privkey));
        ECDSA_SIG *sig = ECsign(privkey, cleartextstr);
        printf("\n\nVerifying signature with EC public key [%d bit]. ", EVP_PKEY_bits(pubkey));
        ret = ECverify(pubkey, cleartextstr, sig);
        break;
      default:
        printf("Unknown Key [%d bit].\n\n", EVP_PKEY_bits(pubkey));
        exit(1);
        break;
    }
  }

  /* ---------------------------------------------------------- *
   * Free up all structures                                     *
   * ---------------------------------------------------------- */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
  EVP_PKEY_free(pubkey);
  BIO_free_all(certbio);
#endif
  exit(0);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x90, %rsp
movaps 0xf02(%rip), %xmm0      # 0x22f0
leaq 0x70(%rsp), %r14
movaps %xmm0, (%r14)
movabsq $0x6d65702e656c69, %rax # imm = 0x6D65702E656C69
movq %rax, 0xd(%r14)
movaps 0xf04(%rip), %xmm0      # 0x2310
movaps %xmm0, (%rsp)
movabsq $0x79656b2e656c69, %rax # imm = 0x79656B2E656C69
movq %rax, 0xd(%rsp)
leaq 0xf0a(%rip), %rsi       # 0x2330
pushq $0x43
popq %rcx
leaq 0x20(%rsp), %rdi
rep  movsb (%rsi), %es:(%rdi)
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, %r15
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, %rbx
pushq $0x6c
popq %rsi
pushq $0x3
popq %rdx
movq %r15, %rdi
movq %r14, %rcx
callq 0x1080
movl %eax, 0x2cd1(%rip)      # 0x4138
movq %r15, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x1200
testq %rax, %rax
jne 0x1483
leaq 0xd98(%rip), %rdi       # 0x2219
jmp 0x14b7
movq %rax, %r14
pushq $0x6c
popq %rsi
pushq $0x3
popq %rdx
movq %rsp, %rcx
movq %rbx, %rdi
callq 0x1080
movl %eax, 0x2c9b(%rip)      # 0x4138
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x10f0
testq %rax, %rax
jne 0x14c4
leaq 0xd81(%rip), %rdi       # 0x2238
callq 0x11a0
pushq $0x1
popq %rdi
callq 0x1180
movq %rax, %rbx
movq %r14, %rdi
callq 0x11c0
testq %rax, %rax
jne 0x14e4
leaq 0xb4c(%rip), %rdi       # 0x2027
xorl %eax, %eax
callq 0x1040
jmp 0x14bc
movq %rax, %r14
leaq 0x20(%rsp), %rdi
callq 0x10d0
movl %eax, 0x2c45(%rip)      # 0x413c
movq %r14, %rdi
callq 0x1120
movl %eax, %ebp
movq %r14, %rdi
callq 0x1150
cmpl $0x198, %ebp            # imm = 0x198
je 0x1617
cmpl $0x6, %ebp
jne 0x167a
leaq 0xb2c(%rip), %rdi       # 0x2051
xorl %r12d, %r12d
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
movq %r14, %rsi
callq 0x131c
testl %eax, %eax
leaq 0xd61(%rip), %rax       # 0x22a6
leaq 0xd12(%rip), %rdi       # 0x225e
cmoveq %rax, %rdi
callq 0x11a0
movl 0x2be1(%rip), %esi      # 0x413c
leaq 0xb25(%rip), %rdi       # 0x2087
leaq 0x20(%rsp), %r15
movq %r15, %rdx
xorl %eax, %eax
callq 0x1040
movq %r14, %rdi
callq 0x1150
leaq 0xb31(%rip), %rdi       # 0x20b1
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %r14, %rdi
movq %r15, %rsi
callq 0x16ad
movl %eax, %ebp
leaq 0xb43(%rip), %rdi       # 0x20e0
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
testl %ebp, %ebp
movl %ebp, %r15d
cmovlel %r12d, %r15d
leaq 0xb4c(%rip), %r14       # 0x2102
xorl %r12d, %r12d
cmpq %r12, %r15
je 0x15d9
movq 0x2b63(%rip), %rax      # 0x4128
movzbl (%rax,%r12), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
incq %r12
jmp 0x15b9
movq %rbx, %rdi
callq 0x1150
leaq 0xb20(%rip), %rdi       # 0x2108
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
movl %ebp, %esi
callq 0x173c
cmpl $-0x1, %eax
jne 0x168f
leaq 0xb2a(%rip), %rdi       # 0x2135
xorl %eax, %eax
callq 0x1040
jmp 0x16a6
leaq 0xb53(%rip), %rdi       # 0x2171
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
callq 0x1150
leaq 0xb56(%rip), %rdi       # 0x218c
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
leaq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0x17c0
movq %rax, %r15
movq %r14, %rdi
callq 0x1150
leaq 0xb60(%rip), %rdi       # 0x21be
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rsi
movq %r15, %rdx
callq 0x180b
movl %eax, 0x2ac0(%rip)      # 0x4138
jmp 0x16a6
leaq 0xb71(%rip), %rdi       # 0x21f2
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
jmp 0x14bc
movq 0x2a9a(%rip), %rdx      # 0x4130
leaq 0xab3(%rip), %rdi       # 0x2150
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
xorl %edi, %edi
callq 0x1180