/*
 * Copyright (c) 2015-2017, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbedtls_stub.h"

mbedtls_stub_def mbedtls_stub;

//From ssl.h
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
{
    if( mbedtls_stub.useCounter ){

        if( mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE ||
                mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE_RETURN_ZERO){

            ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
            if(mbedtls_stub.retArray[mbedtls_stub.counter] == HANDSHAKE_FINISHED_VALUE_RETURN_ZERO)
                return 0;
        }
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

int mbedtls_ssl_close_notify( mbedtls_ssl_context *a )
{
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_ssl_init( mbedtls_ssl_context *a ){

}
void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ){

}

void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ){
    
}

void mbedtls_ssl_config_init( mbedtls_ssl_config *a ){

}

void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *a, uint32_t b, uint32_t c)
{

}

void mbedtls_ssl_free( mbedtls_ssl_context *a ){

}

int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *a,
                              mbedtls_x509_crt *b,
                              mbedtls_pk_context *c ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *a, int c ){

}

void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *a,
                               mbedtls_x509_crt *b,
                               mbedtls_x509_crl *c ){

}

int mbedtls_ssl_conf_psk( mbedtls_ssl_config *a,
                const unsigned char *b, size_t c,
                const unsigned char *d, size_t e ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

int mbedtls_ssl_config_defaults( mbedtls_ssl_config *a,
                                 int b, int c, int d){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_ssl_conf_rng( mbedtls_ssl_config *a,
                  int (*f_rng)(void *, unsigned char *, size_t),
                  void *b ){

}

void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *a,
                                   const int *b)
{

}

int mbedtls_ssl_setup( mbedtls_ssl_context *a,
                       const mbedtls_ssl_config *b ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
        void *p_bio,
        int (*f_send)(void *, const unsigned char *, size_t),
        int (*f_recv)(void *, unsigned char *, size_t),
        int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ){
    if( p_bio != NULL ){
        if( f_send )
            f_send( p_bio, NULL, 0 );
        if( f_recv )
            f_recv( p_bio, NULL, 0 );
        if( f_recv_timeout )
            f_recv_timeout( p_bio, NULL, 0, 0 );
    }
}

void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *a,
                               void *ctx,
                               void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms),
                               int (*f_get_timer)(void *) ){
    f_set_timer(ctx, 1, 2);
    f_get_timer(ctx);
    if(mbedtls_stub.invalidate_timer){
        f_set_timer(ctx, 0, 0);
    }
    f_get_timer(ctx);
}

int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *a ){
    return mbedtls_stub.uint32_value;
}

int mbedtls_ssl_read( mbedtls_ssl_context *a, unsigned char *b, size_t c){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

int mbedtls_ssl_write( mbedtls_ssl_context *a, const unsigned char *b, size_t c ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}



//From crt_drbg.h
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *a,
                   int (*f_entropy)(void *, unsigned char *, size_t),
                   void *b,
                   const unsigned char *c,
                   size_t d ){
    return mbedtls_stub.crt_expected_int;
}

void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *a ){

}

void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *a ){

}

int mbedtls_ctr_drbg_random_with_add( void *a,
                              unsigned char *b, size_t c,
                              const unsigned char *d, size_t e ){
    return mbedtls_stub.crt_expected_int;
}

int mbedtls_ctr_drbg_random( void *p_rng,
                     unsigned char *output, size_t output_len ){
    return mbedtls_stub.crt_expected_int;
}

//From x509_crt.h
void mbedtls_x509_crt_init( mbedtls_x509_crt *a ){

}

void mbedtls_x509_crt_free( mbedtls_x509_crt *a ){

}

int mbedtls_x509_crt_parse( mbedtls_x509_crt *a, const unsigned char *b, size_t c ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

//From entropy.h
void mbedtls_entropy_init( mbedtls_entropy_context *a ){

}

void mbedtls_entropy_free( mbedtls_entropy_context *ctx ){

}

int mbedtls_entropy_func( void *a, unsigned char *b, size_t c ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

int mbedtls_entropy_add_source( mbedtls_entropy_context *a,
                        mbedtls_entropy_f_source_ptr f_source, void *b,
                        size_t c, int d ){
    unsigned char buf[2];
    size_t len;
    f_source(NULL, buf, 1, &len);

    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

//From pk.h
int mbedtls_pk_parse_key( mbedtls_pk_context *a,
                  const unsigned char *b, size_t c,
                  const unsigned char *d, size_t e ){
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_pk_init( mbedtls_pk_context *ctx )
{

}

void mbedtls_pk_free( mbedtls_pk_context *ctx )
{

}

void mbedtls_ssl_config_free( mbedtls_ssl_config *a)
{

}

int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
                                         const unsigned char *pw,
                                         size_t pw_len )
{
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}

void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf,
                           mbedtls_ssl_cookie_write_t *f_cookie_write,
                           mbedtls_ssl_cookie_check_t *f_cookie_check,
                           void *p_cookie )
{
    if( mbedtls_stub.cookie_obj && f_cookie_check && mbedtls_stub.cookie_len > 0 ){
        f_cookie_check(mbedtls_stub.cookie_obj, &mbedtls_stub.cookie_value, mbedtls_stub.cookie_len, NULL, 0);
    }
    if( mbedtls_stub.cookie_obj && f_cookie_write && mbedtls_stub.cookie_len > 0 ){
        unsigned char out[16];
        unsigned char *ptr = &out;
        f_cookie_write(mbedtls_stub.cookie_obj, &ptr, ptr+mbedtls_stub.cookie_len, NULL, 0);
    }
}

void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
        mbedtls_ssl_export_keys_t *f_export_keys,
        void *p_export_keys )
{
    if( f_export_keys && p_export_keys){
        unsigned char value[40];
        memset(&value, 1, 40);
        f_export_keys(p_export_keys, &value, "", 0, 0,0); //failure case

        f_export_keys(p_export_keys, &value, "", 0, 20,0); //success case
    }
}

int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
{
    if( mbedtls_stub.useCounter ){
        return mbedtls_stub.retArray[mbedtls_stub.counter++];
    }
    return mbedtls_stub.expected_int;
}
