// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xe0, %rsp
movl $0x0, -0x4(%rbp)
movq 0xee7(%rip), %rax       # 0x2300
movq %rax, -0x20(%rbp)
movq 0xee4(%rip), %rax       # 0x2308
movq %rax, -0x18(%rbp)
movl 0xee2(%rip), %eax       # 0x2310
movl %eax, -0x10(%rbp)
movb 0xedd(%rip), %al        # 0x2314
movb %al, -0xc(%rbp)
movq 0xedf(%rip), %rax       # 0x2320
movq %rax, -0x40(%rbp)
movq 0xedc(%rip), %rax       # 0x2328
movq %rax, -0x38(%rbp)
movl 0xeda(%rip), %eax       # 0x2330
movl %eax, -0x30(%rbp)
movb 0xed5(%rip), %al        # 0x2334
movb %al, -0x2c(%rbp)
leaq -0x90(%rbp), %rdi
leaq 0xed0(%rip), %rsi       # 0x2340
movl $0x43, %edx
callq 0x1120
movq $0x0, -0x98(%rbp)
movq $0x0, -0xa0(%rbp)
movq $0x0, -0xa8(%rbp)
movq $0x0, -0xb0(%rbp)
movq $0x0, -0xb8(%rbp)
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, -0xa8(%rbp)
callq 0x10a0
movq %rax, %rdi
callq 0x11d0
movq %rax, -0xb0(%rbp)
movq -0xa8(%rbp), %rdi
leaq -0x20(%rbp), %rcx
movl $0x6c, %esi
movl $0x3, %edx
callq 0x1080
movl %eax, 0x2c3f(%rip)      # 0x4138
movq -0xa8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x1200
movq %rax, -0xb8(%rbp)
cmpq $0x0, %rax
jne 0x1534
leaq 0xb04(%rip), %rdi       # 0x2027
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x1190
movq -0xb0(%rbp), %rdi
leaq -0x40(%rbp), %rcx
movl $0x6c, %esi
movl $0x3, %edx
callq 0x1080
movl %eax, 0x2be4(%rip)      # 0x4138
movq -0xb0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x10f0
movq %rax, -0x98(%rbp)
cmpq $0x0, %rax
jne 0x158f
leaq 0xac9(%rip), %rdi       # 0x2047
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x1190
movq -0xb8(%rbp), %rdi
callq 0x11c0
movq %rax, -0xa0(%rbp)
cmpq $0x0, %rax
jne 0x15c0
leaq 0xabf(%rip), %rdi       # 0x206e
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x1190
cmpq $0x0, -0xa0(%rbp)
je 0x1835
leaq -0x90(%rbp), %rdi
callq 0x10d0
movl %eax, 0x2b5c(%rip)      # 0x413c
movq -0xa0(%rbp), %rdi
callq 0x1130
movl %eax, %ecx
movl %ecx, -0xd4(%rbp)
subl $0x6, %eax
je 0x1611
jmp 0x15fb
movl -0xd4(%rbp), %eax
subl $0x198, %eax            # imm = 0x198
je 0x177d
jmp 0x180d
movq -0xa0(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xa72(%rip), %rdi       # 0x2098
movb $0x0, %al
callq 0x1040
movq -0x98(%rbp), %rdi
movq -0xa0(%rbp), %rsi
callq 0x1320
cmpl $0x0, %eax
jne 0x1655
leaq 0xa82(%rip), %rdi       # 0x20ce
movb $0x0, %al
callq 0x1040
jmp 0x1663
leaq 0xaba(%rip), %rdi       # 0x2116
movb $0x0, %al
callq 0x1040
movl 0x2ad3(%rip), %esi      # 0x413c
leaq -0x90(%rbp), %rdx
leaq 0xae8(%rip), %rdi       # 0x215f
movb $0x0, %al
callq 0x1040
movq -0xa0(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xaf6(%rip), %rdi       # 0x2189
movb $0x0, %al
callq 0x1040
movq -0xa0(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x1840
movl %eax, -0xc0(%rbp)
movl -0xc0(%rbp), %esi
leaq 0xaf8(%rip), %rdi       # 0x21b8
movb $0x0, %al
callq 0x1040
movl $0x0, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
cmpl -0xc0(%rbp), %eax
jge 0x1710
movq 0x2a42(%rip), %rax      # 0x4128
movslq -0xbc(%rbp), %rcx
movzbl (%rax,%rcx), %esi
leaq 0xae2(%rip), %rdi       # 0x21da
movb $0x0, %al
callq 0x1040
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x16d1
movq -0x98(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xabb(%rip), %rdi       # 0x21e0
movb $0x0, %al
callq 0x1040
movq -0x98(%rbp), %rdi
movl -0xc0(%rbp), %esi
callq 0x18e0
movl %eax, -0xc4(%rbp)
cmpl $-0x1, -0xc4(%rbp)
jne 0x175d
leaq 0xab9(%rip), %rdi       # 0x220d
movb $0x0, %al
callq 0x1040
jmp 0x1778
movl -0xc4(%rbp), %esi
movq 0x29c6(%rip), %rdx      # 0x4130
leaq 0xab7(%rip), %rdi       # 0x2228
movb $0x0, %al
callq 0x1040
jmp 0x1833
movq -0xa0(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xab7(%rip), %rdi       # 0x2249
movb $0x0, %al
callq 0x1040
movq -0x98(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xab6(%rip), %rdi       # 0x2264
movb $0x0, %al
callq 0x1040
movq -0x98(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x1970
movq %rax, -0xd0(%rbp)
movq -0xa0(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xab2(%rip), %rdi       # 0x2296
movb $0x0, %al
callq 0x1040
movq -0xa0(%rbp), %rdi
leaq -0x90(%rbp), %rsi
movq -0xd0(%rbp), %rdx
callq 0x19e0
movl %eax, 0x292d(%rip)      # 0x4138
jmp 0x1833
movq -0xa0(%rbp), %rdi
callq 0x1160
movl %eax, %esi
leaq 0xaa8(%rip), %rdi       # 0x22ca
movb $0x0, %al
callq 0x1040
movl $0x1, %edi
callq 0x1190
jmp 0x1835
xorl %edi, %edi
callq 0x1190
nopl (%rax)