/********************************* (C) РОТЕК ***********************************
 * @module  cert_req
 * @file    cert_req.c
 * @version 1.0.0
 * @date    XX.XX.XXXX
 *******************************************************************************
 * @history     Version  Author         Comment
 * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
 *******************************************************************************
 */
#include "cert_req.h"

#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif

#include "mbedtls/platform.h"

#include "mbedtls/x509_csr.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"

#include "settings_api.h"

#ifdef PRINTF_STDLIB
#include <stdio.h>
#endif
#ifdef PRINTF_CUSTOM
#include "tinystdio.h"
#endif
#include <stdlib.h>
#include <string.h>

#define DFL_FILENAME            0 //"keyfile.key"
#define DFL_DEBUG_LEVEL         0
#define DFL_OUTPUT_FILENAME     0 //"cert.req"
#define DFL_SUBJECT_NAME        0 //"CN=Cert,O=mbed TLS,C=UK" // Надо CN - ip, O - VimpelCom, C=RU
#define DFL_KEY_USAGE           0
#define DFL_NS_CERT_TYPE        0

extern SETTINGS_t sSettings;


struct options
{
    const char *filename;       /* filename of the key file             */
    int debug_level;            /* level of debugging                   */
    const char *output_file;    /* where to store the constructed key file  */
    const char *subject_name;   /* subject name for certificate request */
    unsigned char key_usage;    /* key usage flags                      */
    unsigned char ns_cert_type; /* NS cert type                         */
} opt;


unsigned char req_cert[500];


void SSL_CreateReqCert()
{
    int ret = 0;
    mbedtls_pk_context key;
    mbedtls_x509write_csr req;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    const char *pers = "csr example app";
    char subject_name[40];
 
    // Set to sane values
    mbedtls_x509write_csr_init( &req );
    mbedtls_x509write_csr_set_md_alg( &req, MBEDTLS_MD_SHA256 );
    mbedtls_pk_init( &key );
    mbedtls_ctr_drbg_init( &ctr_drbg );
    
    // default
    opt.filename            = DFL_FILENAME;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.output_file         = DFL_OUTPUT_FILENAME;
    opt.subject_name        = DFL_SUBJECT_NAME;
    opt.key_usage           = DFL_KEY_USAGE;
    opt.ns_cert_type        = DFL_NS_CERT_TYPE;
    
    // user
    memset(subject_name, 0, 40);
    strcpy(subject_name, "CN=");
    strcat(subject_name, sSettings.sWebParams.ip);
    strcat(subject_name, ",O=VimpelCom,C=RU");
    
    opt.subject_name = subject_name;
    //opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
    //opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
    
    if( opt.key_usage )
        mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );

    if( opt.ns_cert_type )
        mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );
    

    // 0. Seed the PRNG
    mbedtls_printf( "  . Seeding the random number generator..." );
   // fflush( stdout );

    mbedtls_entropy_init( &entropy );
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        mbedtls_printf( " failed\r\n  !  mbedtls_ctr_drbg_seed returned %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\r\n" );
    
    // 1.0. Check the subject name for validity
    mbedtls_printf( "  . Checking subject name..." );
   // fflush( stdout );

    if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 )
    {
        mbedtls_printf( " failed\r\n  !  mbedtls_x509write_csr_set_subject_name returned %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\r\n" );
    
    // 1.1. Load the key
    mbedtls_printf( "  . Loading the private key ..." );
//    fflush( stdout );

    ret =  mbedtls_pk_parse_key( &key, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 );
            
    if( ret != 0 )
    {
        mbedtls_printf( " failed\r\n  !  mbedtls_pk_parse_keyfile returned %d", ret );
        goto exit;
    }

    mbedtls_x509write_csr_set_key( &req, &key );

    mbedtls_printf( " ok\r\n" );
        
    // 1.2. Writing the request
    mbedtls_printf( "  . Writing the certificate request ..." );
   
    ret = mbedtls_x509write_csr_pem( &req, req_cert, 4096, mbedtls_ctr_drbg_random, &ctr_drbg );
    if (ret != 0)
    {
        mbedtls_printf( " failed\r\n  !  write_certifcate_request %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\r\n" );
    
    //mbedtls_printf(req_cert);
    mbedtls_printf("\r\n");
    
exit:

    if( ret != 0 && ret != 1)
    {
        mbedtls_printf("\r\n");
    }

    mbedtls_x509write_csr_free( &req );
    mbedtls_pk_free( &key );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );    
}


/********************************* (C) РОТЕК **********************************/
