// File: /workspace/github_c_makefile_star2_O1/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 0xefe(%rip), %xmm0      # 0x22f0
leaq 0x70(%rsp), %r14
movaps %xmm0, (%r14)
movabsq $0x6d65702e656c69, %rax # imm = 0x6D65702E656C69
movq %rax, 0xd(%r14)
movaps 0xf00(%rip), %xmm0      # 0x2310
movaps %xmm0, (%rsp)
movabsq $0x79656b2e656c69, %rax # imm = 0x79656B2E656C69
movq %rax, 0xd(%rsp)
leaq 0xf06(%rip), %rsi       # 0x2330
leaq 0x20(%rsp), %rax
movl $0x8, %ecx
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
movb $0x0, 0x42(%rax)
movw $0x2e6e, 0x40(%rax)     # imm = 0x2E6E
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, %r15
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, %rbx
movl $0x3, %edx
movq %r15, %rdi
movl $0x6c, %esi
movq %r14, %rcx
callq 0x1080
movl %eax, 0x2cb9(%rip)      # 0x4138
movq %r15, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x1200
testq %rax, %rax
jne 0x149b
leaq 0xd80(%rip), %rdi       # 0x2219
jmp 0x14d3
movq %rax, %r14
movq %rsp, %rcx
movl $0x3, %edx
movq %rbx, %rdi
movl $0x6c, %esi
callq 0x1080
movl %eax, 0x2c7f(%rip)      # 0x4138
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x10f0
testq %rax, %rax
jne 0x14e2
leaq 0xd65(%rip), %rdi       # 0x2238
callq 0x11a0
movl $0x1, %edi
callq 0x1180
movq %rax, %rbx
movq %r14, %rdi
callq 0x11c0
testq %rax, %rax
jne 0x1502
leaq 0xb2e(%rip), %rdi       # 0x2027
xorl %eax, %eax
callq 0x1040
jmp 0x14d8
movq %rax, %r14
leaq 0x20(%rsp), %rdi
callq 0x10d0
movl %eax, 0x2c27(%rip)      # 0x413c
movq %r14, %rdi
callq 0x1120
movl %eax, %ebp
movq %r14, %rdi
callq 0x1150
cmpl $0x198, %ebp            # imm = 0x198
je 0x162e
cmpl $0x6, %ebp
jne 0x1691
leaq 0xb0e(%rip), %rdi       # 0x2051
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
movq %r14, %rsi
callq 0x131c
testl %eax, %eax
leaq 0xd46(%rip), %rax       # 0x22a6
leaq 0xcf7(%rip), %rdi       # 0x225e
cmoveq %rax, %rdi
callq 0x11a0
movl 0x2bc6(%rip), %esi      # 0x413c
leaq 0xb0a(%rip), %rdi       # 0x2087
leaq 0x20(%rsp), %r15
movq %r15, %rdx
xorl %eax, %eax
callq 0x1040
movq %r14, %rdi
callq 0x1150
leaq 0xb16(%rip), %rdi       # 0x20b1
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %r14, %rdi
movq %r15, %rsi
callq 0x16c4
movl %eax, %ebp
leaq 0xb28(%rip), %rdi       # 0x20e0
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
testl %ebp, %ebp
jle 0x15f0
movl %ebp, %r15d
leaq 0xb33(%rip), %r14       # 0x2102
xorl %r12d, %r12d
movq 0x2b4f(%rip), %rax      # 0x4128
movzbl (%rax,%r12), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
incq %r12
cmpq %r12, %r15
jne 0x15d2
movq %rbx, %rdi
callq 0x1150
leaq 0xb09(%rip), %rdi       # 0x2108
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
movl %ebp, %esi
callq 0x179c
cmpl $-0x1, %eax
jne 0x16a6
leaq 0xb13(%rip), %rdi       # 0x2135
xorl %eax, %eax
callq 0x1040
jmp 0x16bd
leaq 0xb3c(%rip), %rdi       # 0x2171
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rdi
callq 0x1150
leaq 0xb3f(%rip), %rdi       # 0x218c
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
leaq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0x1868
movq %rax, %r15
movq %r14, %rdi
callq 0x1150
leaq 0xb49(%rip), %rdi       # 0x21be
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
movq %rbx, %rsi
movq %r15, %rdx
callq 0x18c8
movl %eax, 0x2aa9(%rip)      # 0x4138
jmp 0x16bd
leaq 0xb5a(%rip), %rdi       # 0x21f2
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
jmp 0x14d8
movq 0x2a83(%rip), %rdx      # 0x4130
leaq 0xa9c(%rip), %rdi       # 0x2150
movl %eax, %esi
xorl %eax, %eax
callq 0x1040
xorl %edi, %edi
callq 0x1180