/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 <stdio.h>
#include <axis2_util.h>
#include <oxs_constants.h>
#include <oxs_error.h>
#include <oxs_buffer.h>
#include <oxs_cipher.h>
#include <oxs_sign_ctx.h>
#include <oxs_signature.h>
#include <oxs_buffer.h>
#include <openssl_rsa.h>
#include <openssl_sign.h>
#include <openssl_digest.h>
#include <openssl_hmac.h>

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_sign_hmac_sha1(const axutil_env_t *env,
                      oxs_sign_ctx_t *sign_ctx,
                      oxs_buffer_t *input,
                      oxs_buffer_t *output)
{
    axis2_status_t status = AXIS2_FAILURE;
    axis2_char_t *encoded_str = NULL;
    oxs_buffer_t *signed_result_buf = NULL;
    oxs_key_t *secret = NULL;
    int signedlen = -1;
    int encodedlen = -1;
    int ret = -1;
    /*Create output buffer to store signed data*/
    signed_result_buf = oxs_buffer_create(env);

    /*Get the shared secret form the sig_ctx*/
    secret = oxs_sign_ctx_get_secret(sign_ctx, env);
    if(!secret){
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIGN_FAILED,"Signature failed. using HMAC-SHA1. No secret key is set");
        return AXIS2_FAILURE;
    }
    /*Sign using HMAC-SHA1*/
    status = openssl_hmac_sha1(env, secret, input, signed_result_buf);
    if(AXIS2_FAILURE == status){
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIGN_FAILED,"Signature failed. using HMAC-SHA1 ");
        return AXIS2_FAILURE;
    }

    signedlen = oxs_buffer_get_size(signed_result_buf, env);
    /*Base64 encode*/
    encodedlen = axutil_base64_encode_len(signedlen);
    encoded_str = AXIS2_MALLOC(env->allocator, encodedlen);
    ret = axutil_base64_encode(encoded_str, (const char *)
            oxs_buffer_get_data(signed_result_buf, env), signedlen);
    status = oxs_buffer_populate(output, env, (unsigned char*)encoded_str,
                                 encodedlen);


    /*Free signed_result_buf*/
    oxs_buffer_free(signed_result_buf, env);
    signed_result_buf = NULL;

    /*Free encoded_str*/
    AXIS2_FREE(env->allocator, encoded_str);
    encoded_str = NULL;
    
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_sign_rsa_sha1(const axutil_env_t *env,
                      oxs_sign_ctx_t *sign_ctx,
                      oxs_buffer_t *input,
                      oxs_buffer_t *output)
{
    axis2_char_t *encoded_str = NULL;
    axis2_status_t status = AXIS2_FAILURE;
    oxs_buffer_t *signed_result_buf = NULL;
    openssl_pkey_t *prvkey = NULL;
    int signedlen = -1;
    int encodedlen = -1;
    int ret = -1;

    /*Create output buffer to store signed data*/
    signed_result_buf = oxs_buffer_create(env);

    /*Sign */
    prvkey = oxs_sign_ctx_get_private_key(sign_ctx, env);
    signedlen = openssl_sig_sign(env, prvkey, input, signed_result_buf);
    if (signedlen < 0)
    {
        /*Error*/
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIGN_FAILED,
                  "Signature failed. The length of signature is %d", signedlen);
    }

    /*Base64 encode*/
    encodedlen = axutil_base64_encode_len(signedlen);
    encoded_str = AXIS2_MALLOC(env->allocator, encodedlen);
    ret = axutil_base64_encode(encoded_str, (const char *)
            oxs_buffer_get_data(signed_result_buf, env), signedlen);
    status = oxs_buffer_populate(output, env, (unsigned char*)encoded_str,
                                 encodedlen);

    /*Free signed_result_buf*/
    oxs_buffer_free(signed_result_buf, env);
    signed_result_buf = NULL;

    /*Free encoded_str*/
    AXIS2_FREE(env->allocator, encoded_str);
    encoded_str = NULL;

    return AXIS2_SUCCESS;
}


/*Public functions*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_sign(const axutil_env_t *env,
             oxs_sign_ctx_t *sign_ctx,
             oxs_buffer_t *input,
             oxs_buffer_t *output)
{
    axis2_char_t *sign_algo = NULL;

    /*Get algo. To check whether we support*/
    sign_algo = oxs_sign_ctx_get_sign_mtd_algo(sign_ctx, env);

    /*Prepare content and sign*/
    if ((axutil_strcmp(sign_algo, OXS_HREF_RSA_SHA1)) == 0)
    {
        oxs_sig_sign_rsa_sha1(env, sign_ctx, input, output);
    } 
    else if ((axutil_strcmp(sign_algo, OXS_HREF_HMAC_SHA1)) == 0)
    {
        oxs_sig_sign_hmac_sha1(env, sign_ctx, input, output);
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
                  "Cannot support cipher %s", sign_algo);
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_verify_hmac_sha1(const axutil_env_t *env,
               oxs_sign_ctx_t *sign_ctx,
               axis2_char_t *content,
               axis2_char_t *signature)
{
    axis2_status_t status = AXIS2_FAILURE;
    oxs_buffer_t *input_buf = NULL;
    oxs_buffer_t *output_buf = NULL;
    axis2_char_t *signed_val = NULL;

    /*Make the input and out put buffers*/
    input_buf = oxs_buffer_create(env);
    output_buf = oxs_buffer_create(env);

    oxs_buffer_populate(input_buf, env, (unsigned char *)content, axutil_strlen(content));
    /*Sign the content and get the output*/
    status = oxs_sig_sign_hmac_sha1(env, sign_ctx, input_buf, output_buf); 

    signed_val = (axis2_char_t*)oxs_buffer_get_data(output_buf, env);
	oxs_buffer_free(input_buf, env);
    /*Compare the output with the signature. If tally; SUCCESS*/
    if(axutil_strcmp(signature, signed_val) == 0){
		oxs_buffer_free(output_buf, env);
        return AXIS2_SUCCESS;
    }else{
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED, "Signature verification failed using HMAC-SHA1");
		oxs_buffer_free(output_buf, env);
        return AXIS2_FAILURE;
    }
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_verify(const axutil_env_t *env,
               oxs_sign_ctx_t *sign_ctx,
               axis2_char_t *content,
               axis2_char_t *signature)
{
    axis2_status_t status = AXIS2_FAILURE;
    axis2_char_t *sign_algo = NULL;

    /*Get algo. To check whether we support*/
    sign_algo = oxs_sign_ctx_get_sign_mtd_algo(sign_ctx, env);

    /*Prepare content and verify*/
    if ((axutil_strcmp(sign_algo, OXS_HREF_RSA_SHA1)) == 0)
    {
        status = oxs_sig_verify_rsa_sha1(env, sign_ctx, content, signature);
    }
    else if ((axutil_strcmp(sign_algo, OXS_HREF_HMAC_SHA1)) == 0)
    {
        status = oxs_sig_verify_hmac_sha1(env, sign_ctx,  content, signature);
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_INVALID_DATA,  "Cannot support cipher %s for verification", sign_algo);
        status = AXIS2_FAILURE;
    }

    return status;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_sig_verify_rsa_sha1(const axutil_env_t *env,
               oxs_sign_ctx_t *sign_ctx,
               axis2_char_t *content,
               axis2_char_t *signature)
{
    axis2_status_t status = AXIS2_FAILURE;
    oxs_buffer_t *in_buf =  NULL;
    oxs_buffer_t *sig_buf =  NULL;
    openssl_pkey_t *pubkey = NULL;

    unsigned char* decoded_data = NULL;
    int decoded_len = -1;
    int ret = -1;

    /*Base64 decode the signature value and create the sig buffer*/
    /*Allocate enough space*/
    decoded_data = AXIS2_MALLOC(env->allocator,
                                axutil_base64_decode_len(signature));
    decoded_len = axutil_base64_decode_binary(decoded_data, signature);
    if (decoded_len < 0)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                  "axutil_base64_decode_binary failed");
        return AXIS2_FAILURE;
    }

    /*Create the signature buffer*/
    sig_buf = oxs_buffer_create(env);
    ret = oxs_buffer_populate(sig_buf, env, decoded_data, decoded_len);

    /*Create the input buffer*/
    in_buf = oxs_buffer_create(env);
    status = oxs_buffer_populate(in_buf, env, (unsigned char*)content,
                                 axutil_strlen(content));

	AXIS2_FREE(env->allocator, decoded_data);

    /* Get the public key. See.. this method is trickey. It might take the
     * public key from the certificate, only if
     * the public key is not available directly
     */
    pubkey = oxs_sign_ctx_get_public_key(sign_ctx, env);
    if (!pubkey)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                  "Cannot obtain the public key.");
        return AXIS2_FAILURE;
    }

    /*Call OpenSSL function to verify the signature*/
    status = openssl_sig_verify(env, pubkey, in_buf, sig_buf);
    if (status != AXIS2_SUCCESS)
    {
        /*Error in signature processing*/
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                  "Signature verification FAILED.");
        oxs_buffer_free(sig_buf, env);
        sig_buf = NULL;
        oxs_buffer_free(in_buf, env);
        in_buf = NULL;

        return AXIS2_FAILURE;
    }
    else
    {
        /*Signature SUCCESS*/
        AXIS2_LOG_INFO(env->log, "[oxs][sig] Signature verification SUCCESS");
        oxs_buffer_free(sig_buf, env);
        sig_buf = NULL;
        oxs_buffer_free(in_buf, env);
        in_buf = NULL;

        return AXIS2_SUCCESS;
    }
}
