//
//  main.c
//  pkcs7
//
//  Created by michal on 01.04.2021.
//

#include <stdio.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include "scep.h"


int verify( PKCS7 *pkiMessage, X509 * ca_cert, BIO **encData)
{
    int error = 0;
    BIO *data = NULL;
    X509_STORE *store = X509_STORE_new();
    
    X509_STORE_add_cert(store, ca_cert);
    data = BIO_new(BIO_s_mem());

    if (!PKCS7_verify(pkiMessage, NULL, store, NULL, data, PKCS7_NOVERIFY)) {
        error = 1;
    }
    *encData = data;
    return error;
}

int main(int argc, const char * argv[]) {
    
    printf("BEGIN PKCS7 decrypt program\n");

    // OpenSSL setup
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
    
    // Decryption certificate and key
    BIO *rawcacert = NULL;
    BIO *rawkey = NULL;
    X509 *cacert;
    EVP_PKEY *cakey;
    
    // Input data
    BIO *in ;//= BIO_new(BIO_s_file());
    PKCS7 *pkiMessage = NULL;
    PKCS7 *p7env;
    BIO *encData;

    // Output
    BIO *decData = NULL;
    decData = BIO_new(BIO_s_mem());
    SCEP_DATA *output = NULL;
    output = malloc(sizeof(SCEP_DATA));
    
    // prepare datastructures
    encData = BIO_new(BIO_s_mem());
    decData = BIO_new(BIO_s_mem());
    
    // load cacert from disk
    rawcacert = BIO_new_file("scep.pem", "r");
    cacert = PEM_read_bio_X509(rawcacert, NULL, 0, NULL);

    // load cakey from disk
    rawkey = BIO_new_file("scep.key", "r");
    cakey = PEM_read_bio_PrivateKey(rawkey, NULL, 0, NULL);
    
    in = BIO_new_file("pkimessage.p7b", "r");
    pkiMessage = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
        
    if(verify(pkiMessage, cacert, &encData) == 0) {
        printf("PKCS7 verified\n");
    } else {
        printf("PKCS7 verify failed\n");
        exit(1);
    }
    
    p7env = d2i_PKCS7_bio(encData, NULL);

    // Try to connvert p7env into CMS_ContentInfo
    CMS_ContentInfo *cmsMessage = NULL;
    BIO *convert = NULL;
    convert = BIO_new(BIO_s_mem());
    PEM_write_bio_PKCS7(convert, p7env);
    cmsMessage = PEM_read_bio_CMS(convert, NULL, NULL, NULL);
    
    
    //if(PKCS7_decrypt(p7env, cakey, cacert, decData, 0)) {
    if (CMS_decrypt(cmsMessage, cakey, cacert, NULL, decData, 0)) {
        printf("PKCS7 decrypted\n");
    } else {
        printf("PKCS7 decryption failed\n");
        exit(1);
    }
    
    // Output
    output->request = NULL;
    d2i_X509_REQ_bio(decData, &(output->request));
    if(!output->request){
        printf("Not valid CSR after decrpytion");
        exit(1);
    }
    
    printf("Name: %s\n", X509_NAME_oneline(X509_REQ_get_subject_name(output->request), 0, 0));
}
