/*
 * 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_c14n.h>
#include <oxs_axiom.h>
#include <oxs_utility.h>
#include <openssl_rsa.h>
#include <openssl_digest.h>
#include <oxs_sign_ctx.h>
#include <oxs_sign_part.h>
#include <oxs_xml_signature.h>
#include <oxs_signature.h>
#include <oxs_transform.h>
#include <oxs_transforms_factory.h>
#include <oxs_tokens.h>
#include <axiom_util.h>


/* This method is common for both signing and verification */
static axis2_char_t *
oxs_xml_sig_transform_n_digest(
    const axutil_env_t *env,
    axiom_node_t *node,
    axutil_array_list_t *transforms,
    axis2_char_t *digest_mtd)
{
    axis2_char_t *serialized_node = NULL;
    axis2_char_t *digest = NULL;
    axiom_node_t *ori_node = NULL, *sig_node = NULL;
    oxs_tr_dtype_t output_dtype = OXS_TRANSFORM_TYPE_UNKNOWN;/*This will always be the current dtype*/
    void *tr_output = NULL;
    int i = 0;

    if((transforms) && (0 < axutil_array_list_size(transforms, env)))
    {

        output_dtype = OXS_TRANSFORM_TYPE_NODE; /*We always begin with a node*/

        tr_output = node; /*The first transformation is applied to the node*/

        /*LOOP: Apply transforms. For example exclusive C14N*/
        for(i = 0; i < axutil_array_list_size(transforms, env); i++)
        {
            oxs_transform_t *tr = NULL;
            oxs_transform_tr_func tr_func = NULL;
            oxs_tr_dtype_t input_dtype = OXS_TRANSFORM_TYPE_UNKNOWN;
            void *tr_input = NULL;
            axis2_char_t *tr_id = NULL;

            /*Get the ith transform*/
            tr = (oxs_transform_t*)axutil_array_list_get(transforms, env, i);
            tr_id = oxs_transform_get_id(tr, env);
            tr_func = oxs_transform_get_transform_function(tr, env);
            input_dtype = oxs_transform_get_input_data_type(tr, env);

            /*Prepare the input*/
            /*If the required input type is CHAR and what we have is a NODE*/
            if((input_dtype == OXS_TRANSFORM_TYPE_CHAR)
                && (output_dtype == OXS_TRANSFORM_TYPE_NODE))
            {
                /*Serialize*/
                tr_input = axiom_node_to_string((axiom_node_t*)tr_output, env);
                /*If the required input type is NODE and what we have is a CHAR*/
            }
            else if((input_dtype == OXS_TRANSFORM_TYPE_NODE) && (output_dtype
                == OXS_TRANSFORM_TYPE_CHAR))
            {
                /*De-serialize*/
                tr_input = oxs_axiom_deserialize_node(env, (axis2_char_t *)tr_output);
            }
            else if((input_dtype == OXS_TRANSFORM_TYPE_NODE) && (output_dtype
                == OXS_TRANSFORM_TYPE_NODE_ARRAY_LIST))
            {
                ori_node = axutil_array_list_get((axutil_array_list_t*)tr_output, env, 0);
                sig_node = axutil_array_list_get((axutil_array_list_t*)tr_output, env, 1);
                tr_input = ori_node;
            }
            else if((input_dtype == OXS_TRANSFORM_TYPE_CHAR) && (output_dtype
                == OXS_TRANSFORM_TYPE_NODE_ARRAY_LIST))
            {
                ori_node = axutil_array_list_get((axutil_array_list_t*)tr_output, env, 0);
                sig_node = axutil_array_list_get((axutil_array_list_t*)tr_output, env, 1);
                tr_input = axiom_node_to_string(ori_node, env);
            }
            else
            {
                /*Let it go as it is. */
                tr_input = tr_output;
            }
            /*Apply transform*/
            if(tr_func)
            {
                output_dtype = (*tr_func)(env, tr_input, input_dtype, &tr_output);
            }
            else
            {
                oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,
                    "Cannot get the transform implementation for %s", tr_id);
            }
            /*If the output data type is unknown OR the output is NULL its an error*/
            if((output_dtype == OXS_TRANSFORM_TYPE_UNKNOWN) || (!tr_output))
            {
                oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,
                    "Transform failed for %s", tr_id);
                return NULL;
            }
        }/*eof for loop*/
        /*We have applied all our transforms now*/
        /*Serialize node*/
        if(OXS_TRANSFORM_TYPE_NODE == output_dtype)
        {
            serialized_node = axiom_node_to_string((axiom_node_t*)tr_output, env);
        }
        else if(OXS_TRANSFORM_TYPE_CHAR == output_dtype)
        {
            serialized_node = (axis2_char_t*)tr_output;
        }
        else if(OXS_TRANSFORM_TYPE_NODE_ARRAY_LIST == output_dtype)
        {
            ori_node
                = (axiom_node_t*)axutil_array_list_get((axutil_array_list_t*)tr_output, env, 0);
            sig_node
                = (axiom_node_t*)axutil_array_list_get((axutil_array_list_t*)tr_output, env, 1);
            serialized_node = axiom_node_to_string(ori_node, env);
        }
        else
        {
            /*Error*/
            oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,
                "Unsupported transform data type  %d", output_dtype);
        }
    }
    else
    {
        /*No transforms defined. Thus we simply direct the node, to make the digest*/
        serialized_node = axiom_node_to_string(node, env);
    }

    if(0 == axutil_strcmp(OXS_HREF_SHA1, digest_mtd))
    {
        digest = openssl_sha1(env, serialized_node, axutil_strlen(serialized_node));
    }
    else if(0 == axutil_strcmp(OXS_HREF_SHA256, digest_mtd))
    {
        digest = openssl_sha256(env, serialized_node, axutil_strlen(serialized_node));
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,
            "Unsupported digest method  %s", digest_mtd);
        return NULL;
    }

    if(ori_node && sig_node)
    {
        axiom_node_add_child(ori_node, env, sig_node);
    }
    if(serialized_node)
    {
        AXIS2_FREE(env->allocator, serialized_node);
        serialized_node = NULL;
    }
    return digest;
}

/*parent is ds:SignedInfo*/
static axis2_status_t
oxs_xml_sig_build_reference(
    const axutil_env_t *env,
    axiom_node_t *parent,
    oxs_sign_part_t *sign_part)
{
    axis2_char_t *digest = NULL;
    axis2_char_t *digest_mtd = NULL;
    axis2_char_t *ref_id = NULL;
    axis2_char_t *id = NULL, *id_name = NULL;
    axiom_namespace_t *ns = NULL;
    axis2_char_t *ns_uri = NULL;
    axutil_array_list_t *transforms = NULL;
    axiom_node_t *node = NULL;
    axiom_node_t *reference_node = NULL;
    axiom_node_t *digest_value_node = NULL;
    axiom_node_t *digest_mtd_node = NULL;
    int i = 0;

    /*Get the node to digest*/
    node = oxs_sign_part_get_node(sign_part, env);

    id_name = oxs_sign_part_get_id_name(sign_part, env);
    ns = oxs_sign_part_get_sign_namespace(sign_part, env);

    if(ns)
        ns_uri = axiom_namespace_get_uri(ns, env);
    else if(!ns && !id_name)
        ns_uri = OXS_WSU_XMLNS;
    else
        ns_uri = NULL;

    if(!id_name)
        id_name = OXS_ATTR_ID;

    /*Get the reference ID from the node and hence to the ds:Reference node*/
    id = oxs_axiom_get_attribute_value_of_node_by_name(env, node, id_name, ns_uri);

    ref_id = axutil_stracat(env, OXS_LOCAL_REFERENCE_PREFIX, id);/* <ds:Reference URI="#id">*/
    reference_node = oxs_token_build_ds_reference_element(env, parent, NULL, ref_id, NULL);

    AXIS2_FREE(env->allocator, ref_id);
    ref_id = NULL;

    /*Get transforms if any*/
    transforms = oxs_sign_part_get_transforms(sign_part, env);
    /*Get the digest method*/
    digest_mtd = oxs_sign_part_get_digest_mtd(sign_part, env);

    /*Transform and Digest*/
    digest = oxs_xml_sig_transform_n_digest(env, node, transforms, digest_mtd);
    if(!digest)
    {
        return AXIS2_FAILURE;
    }

    /*Build ds:Transforms node and its children*/
    if((transforms) && (0 < axutil_array_list_size(transforms, env)))
    {
        axiom_node_t *transforms_node = NULL;

        transforms_node = oxs_token_build_transforms_element(env, reference_node);
        for(i = 0; i < axutil_array_list_size(transforms, env); i++)
        {
            oxs_transform_t *tr = NULL;
            axis2_char_t *tr_id = NULL;

            /*Get the ith transform*/
            tr = (oxs_transform_t*)axutil_array_list_get(transforms, env, i);
            tr_id = oxs_transform_get_id(tr, env);
            oxs_token_build_transform_element(env, transforms_node, tr_id);
        }
    }
    /*Construct nodes*/
    digest_mtd_node = oxs_token_build_digest_method_element(env, reference_node, digest_mtd);
    digest_value_node = oxs_token_build_digest_value_element(env, reference_node, digest);

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

    return AXIS2_SUCCESS;
}
/**
 *  C14N -> Serialize -> Sign the <SignedInfo> element
 */
static axis2_status_t
oxs_xml_sig_sign_signed_info(
    const axutil_env_t *env,
    axiom_node_t *signature_node,
    axiom_node_t *signed_info_node,
    oxs_sign_ctx_t *sign_ctx)
{
    axis2_char_t *signature_val = NULL;
    axis2_char_t *serialized_signed_info = NULL;
    axis2_char_t *c14n_algo = NULL;
    axis2_char_t *c14nized = NULL;
    axiom_node_t *signature_val_node = NULL;
    axiom_document_t *doc = NULL;
    oxs_buffer_t *input_buf = NULL;
    oxs_buffer_t *output_buf = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    /*Cannonicalize <SignedInfo>*/
    c14n_algo = oxs_sign_ctx_get_c14n_mtd(sign_ctx, env);
    doc = axiom_node_get_document(signed_info_node, env);

    /*oxs_c14n_apply(env, doc, AXIS2_FALSE, &c14nized, AXIS2_TRUE, NULL, signed_info_node); */
    oxs_c14n_apply_algo(env, doc, &c14nized, NULL, signed_info_node, c14n_algo);
    AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[oxs][xml_sig] C14N (sig)= %s ", c14nized);

    /*Then serialize <SignedInfo>*/
    serialized_signed_info = c14nized; /*axiom_node_to_string(signed_info_node, env);*/

    /*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 *)serialized_signed_info, axutil_strlen(
        serialized_signed_info));
    /*Then sign... NOTE: The signature process includes making the digest. e.g. rsa-sha1 => RSA(SHA-1(contents))*/
    status = oxs_sig_sign(env, sign_ctx, input_buf, output_buf);

    signature_val = (axis2_char_t*)oxs_buffer_get_data(output_buf, env);

    /*Construct <SignatureValue>*/
    signature_val_node
        = oxs_token_build_signature_value_element(env, signature_node, signature_val);

    /*Free*/
    AXIS2_FREE(env->allocator, c14nized);
    c14nized = NULL;
    oxs_buffer_free(input_buf, env);
    input_buf = NULL;
    oxs_buffer_free(output_buf, env);
    output_buf = NULL;

    return status;
}

/*Public functions*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_sign(
    const axutil_env_t *env,
    oxs_sign_ctx_t *sign_ctx,
    axiom_node_t *parent,
    axiom_node_t **sig_node)
{
    axiom_node_t *signed_info_node = NULL;
    axiom_node_t *signature_node = NULL;
    axiom_node_t *signature_mtd_node = NULL;
    axiom_node_t *c14n_mtd_node = NULL;
    axis2_char_t *sign_algo = NULL;
    axis2_char_t *c14n_algo = NULL;
    axis2_char_t *sig_id = NULL;
    axutil_array_list_t *sign_parts = NULL;
    axis2_status_t status = AXIS2_FAILURE;
    int i = 0;

    /*Construct the <Signature> element*/
    sig_id = oxs_util_generate_id(env, OXS_SIG_ID);
    signature_node = oxs_token_build_signature_element(env, parent, sig_id);

    AXIS2_FREE(env->allocator, sig_id);
    sig_id = NULL;

    /*Construct the <SignedInfo>  */
    signed_info_node = oxs_token_build_signed_info_element(env, signature_node);

    /*Construct the <CanonicalizationMethod> */
    c14n_algo = oxs_sign_ctx_get_c14n_mtd(sign_ctx, env);
    c14n_mtd_node = oxs_token_build_c14n_method_element(env, signed_info_node, c14n_algo);

    /*Construct the <SignatureMethod>  */
    sign_algo = oxs_sign_ctx_get_sign_mtd_algo(sign_ctx, env);
    signature_mtd_node = oxs_token_build_signature_method_element(env, signed_info_node, sign_algo);

    /*Look for signature parts*/
    sign_parts = oxs_sign_ctx_get_sign_parts(sign_ctx, env);

    /*For each and every signature part in sig ctx,*/
    for(i = 0; i < axutil_array_list_size(sign_parts, env); i++)
    {
        oxs_sign_part_t *sign_part = NULL;

        /*Get ith sign_part*/
        sign_part = (oxs_sign_part_t*)axutil_array_list_get(sign_parts, env, i);
        /*Create <ds:Reference> elements */
        if(oxs_xml_sig_build_reference(env, signed_info_node, sign_part) != AXIS2_SUCCESS)
        {
            return AXIS2_FAILURE;
        }

    }
    /*At this point we have a complete <SignedInfo> node. Now we need to sign it*/
    status = oxs_xml_sig_sign_signed_info(env, signature_node, signed_info_node, sign_ctx);
    /*sig_id = axiom_node_to_string(parent, env);*/
    *sig_node = signature_node;
    return status;
}

/*******************************Verification specific*****************************/

/*Populates a sign_part according to the <ds:Reference> node*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_process_ref_node(
    const axutil_env_t *env,
    oxs_sign_part_t *sign_part,
    axiom_node_t *ref_node,
    axiom_node_t *scope_node)
{
    axis2_char_t *ref_id = NULL;
    axis2_char_t *ref_id2 = NULL;
    axis2_char_t *child_node_name = NULL;
    axiom_node_t *reffed_node = NULL;
    axiom_node_t *child_node = NULL, *cn = NULL;

    axis2_char_t *id_name = NULL;
    axiom_namespace_t *ns = NULL;
    axis2_char_t *ns_uri = NULL;
    axiom_attribute_t *attr = NULL;
    axutil_hash_t *attr_hash = NULL;
    axutil_hash_index_t *hi = NULL;
    axiom_element_t *element = NULL, *ce = NULL;
    axiom_child_element_iterator_t *ci = NULL;
    ref_id = oxs_token_get_ds_reference(env, ref_node);
    oxs_sign_part_set_id(sign_part, env, ref_id);

    /*Remove the # from the id*/
    ref_id2 = axutil_string_substring_starting_at(axutil_strdup(env, ref_id), 1);
    /*Look for the attribute with the Reference URI value*/
    if(scope_node)
    {
        element = axiom_node_get_data_element(scope_node, env);
        if(element)
            attr_hash = axiom_element_get_all_attributes(element, env);

        if(attr_hash)
        {
            for(hi = axutil_hash_first(attr_hash, env); hi; hi = axutil_hash_next(env, hi))
            {
                void *v = NULL;
                axutil_hash_this(hi, NULL, NULL, &v);
                if(v)
                {
                    axis2_char_t *attr_val = NULL;
                    axiom_attribute_t *attribute = (axiom_attribute_t*)v;
                    attr_val = axiom_attribute_get_value(attribute, env);
                    if(!axutil_strcmp(attr_val, ref_id2))
                    {
                        attr = attribute;
                        break;
                    }
                }
            }
        }
    }
    /* if we cannot find the Id in the scope node proceed to childs*/
    if(!attr)
    {
        element = axiom_node_get_data_element(scope_node, env);
        if(element)
        {
            ci = axiom_element_get_child_elements(element, env, scope_node);
            if(ci)
            {
                while(AXIS2_TRUE == axiom_child_element_iterator_has_next(ci, env))
                {
                    cn = axiom_child_element_iterator_next(ci, env);
                    ce = axiom_node_get_data_element(cn, env);
                    if(ce)
                        attr_hash = axiom_element_get_all_attributes(ce, env);

                    if(attr_hash)
                    {
                        for(hi = axutil_hash_first(attr_hash, env); hi; hi = axutil_hash_next(env,
                            hi))
                        {
                            void *v = NULL;
                            axutil_hash_this(hi, NULL, NULL, &v);
                            if(v)
                            {
                                axis2_char_t *attr_val = NULL;
                                axiom_attribute_t *attribute = (axiom_attribute_t*)v;
                                attr_val = axiom_attribute_get_value(attribute, env);
                                if(!axutil_strcmp(attr_val, ref_id2))
                                {
                                    attr = attribute;
                                    if(env)
                                        AXIS2_FREE(env->allocator, hi);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    if(attr)
    {
        id_name = axiom_attribute_get_localname(attr, env);
        ns = axiom_attribute_get_namespace(attr, env);
        if(ns)
            ns_uri = axiom_namespace_get_uri(ns, env);
        else
            ns_uri = "";
        reffed_node = oxs_axiom_get_node_by_id(env, scope_node, id_name, ref_id2, ns_uri);
    }
    else
    {
        reffed_node = oxs_axiom_get_node_by_id(env, scope_node, "Id", ref_id2, OXS_WSU_XMLNS);
        /*for endorsing, we have to check "Id", not "wsu:Id"*/
        if(!reffed_node)
        {
            reffed_node = oxs_axiom_get_node_by_id(env, scope_node, "Id", ref_id2, NULL);
        }
    }
    /*Find the node refered by this ref_id2 and set to the sign part*/

    if(reffed_node)
    {
        oxs_sign_part_set_node(sign_part, env, reffed_node);
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Cannot find node with Id=%s ", ref_id2);
        AXIS2_FREE(env->allocator, ref_id2);
        ref_id2 = NULL;
        return AXIS2_FAILURE; /*No such node. Its an error*/
    }
    AXIS2_FREE(env->allocator, ref_id2);
    ref_id2 = NULL;

    /*First child is optional Transforms element*/
    child_node = axiom_node_get_first_element(ref_node, env);
    child_node_name = axiom_util_get_localname(child_node, env);
    if(0 == axutil_strcmp(child_node_name, OXS_NODE_TRANSFORMS))
    {
        /*Transforms found*/
        axiom_node_t *tr_node = NULL;
        axutil_array_list_t *tr_list = NULL;

        /*Create a list to hold transforms*/
        tr_list = axutil_array_list_create(env, 1);
        tr_node = axiom_node_get_first_element(child_node, env);
        /*Iterate thru all the <ds:Transform> nodes in <ds:Transforms>*/
        while(tr_node)
        {
            axis2_char_t *node_name = NULL;

            node_name = axiom_util_get_localname(tr_node, env);
            if(0 == axutil_strcmp(OXS_NODE_TRANSFORM, node_name))
            {
                axis2_char_t *tr_id = NULL;
                oxs_transform_t *tr = NULL;

                tr_id = oxs_token_get_transform(env, tr_node);
                /*Get the transform given the id*/
                tr = oxs_transforms_factory_produce_transform(env, tr_id);
                if(!tr)
                {
                    /*The transform not supported*/
                    oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,
                        "Cannot produce the transform for %s", tr_id);
                    return AXIS2_FAILURE;
                }
                /*Add the transform to the list*/
                axutil_array_list_add(tr_list, env, tr);
            }
            else
            {
                /*<ds:Transforms> cant have any other element*/
                /*NOTE: Removed this check for interop testing*/
                /*oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_TRANSFORM_FAILED,"<ds:Transforms> cannot have node %s ", node_name );
                 return AXIS2_FAILURE;*/
            }
            /*Set the next node to be processed*/
            tr_node = axiom_node_get_next_sibling(tr_node, env);
            /*axiom_util_get_next_sibling_element(axiom_node_get_data_element(tr_node, env), env,
             tr_node, &tr_node);*/
        }/*eof while*/
        /*Set transforms for this signature part*/
        oxs_sign_part_set_transforms(sign_part, env, tr_list);

        /*At the end, set the next node as the child node*/
        /*child_node = axiom_node_get_next_sibling(child_node, env);*/
        axiom_util_get_next_sibling_element(axiom_node_get_data_element(child_node, env), env,
            child_node, &child_node);
    }
    else
    {
        /*There are no transforms for this sign part*/
    }

    /* Process mandatory ds:DigestMethod*/
    child_node_name = axiom_util_get_localname(child_node, env);
    if(0 == axutil_strcmp(child_node_name, OXS_NODE_DIGEST_METHOD))
    {
        axis2_char_t *digest_mtd = NULL;
        /*ds:DigestMethod found*/
        digest_mtd = oxs_token_get_digest_method(env, child_node);
        oxs_sign_part_set_digest_mtd(sign_part, env, digest_mtd);

        /*At the end, set the next node as the child node*/
        /*child_node = axiom_node_get_next_sibling(child_node, env);*/
        axiom_util_get_next_sibling_element(axiom_node_get_data_element(child_node, env), env,
            child_node, &child_node);
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Cannot find <ds:DigestMethod> ");
        return AXIS2_FAILURE;
    }

    /* Process mandatory ds:DigestValue*/
    child_node_name = axiom_util_get_localname(child_node, env);
    if(0 == axutil_strcmp(child_node_name, OXS_NODE_DIGEST_VALUE))
    {
        /*ds:DigestValue found*/
        axis2_char_t *digest_val = NULL;
        digest_val = oxs_token_get_digest_value(env, child_node);
        oxs_sign_part_set_digest_val(sign_part, env, digest_val);
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Cannot find <ds:DigestValue> ");
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;

}

/*Process Signature Node along with its most loving child ds:SignedInfo.
 * We need to populate 
 * 1. Sig_mtd
 * 2. C14N Mtd
 * 3. Sign parts
 *      3.1. Id
 *      3.2  Digest mtd
 *      3.3. Transforms*/

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_process_signature_node(
    const axutil_env_t *env,
    oxs_sign_ctx_t *sign_ctx,
    axiom_node_t *signature_node,
    axiom_node_t *scope_node)
{
    axiom_node_t *cur_node = NULL;
    axiom_node_t *signed_info_node = NULL;
    axiom_node_t *sig_val_node = NULL;
    axis2_status_t status = AXIS2_FAILURE;
    axutil_array_list_t *sign_part_list = NULL;

    signed_info_node = oxs_axiom_get_first_child_node_by_name(env, signature_node,
        OXS_NODE_SIGNEDINFO, OXS_DSIG_NS, OXS_DS);

    /*signed_info_node = oxs_axiom_get_first_child_node_by_name(env, signature_node,
     OXS_NODE_SIGNEDINFO, NULL,NULL);*/

    if(!signed_info_node)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Cannot find <ds:SignedInfo> ");
        return AXIS2_FAILURE;
    }
    /*Create the list for sign parts*/
    sign_part_list = axutil_array_list_create(env, 5);

    /*Process signed info element*/
    cur_node = axiom_node_get_first_element(signed_info_node, env);
    /*Iterate thru children of <SignedInfo>*/
    while(cur_node)
    {
        axis2_char_t *localname = NULL;

        localname = axiom_util_get_localname(cur_node, env);

        if(0 == axutil_strcmp(localname, OXS_NODE_CANONICALIZATION_METHOD))
        {
            axis2_char_t *c14n_mtd = NULL;
            c14n_mtd = oxs_token_get_c14n_method(env, cur_node);
            oxs_sign_ctx_set_c14n_mtd(sign_ctx, env, c14n_mtd);

        }
        else if(0 == axutil_strcmp(localname, OXS_NODE_SIGNATURE_METHOD))
        {
            axis2_char_t *sig_mtd = NULL;
            sig_mtd = oxs_token_get_signature_method(env, cur_node);
            oxs_sign_ctx_set_sign_mtd_algo(sign_ctx, env, sig_mtd);

        }
        else if(0 == axutil_strcmp(localname, OXS_NODE_REFERENCE))
        {
            oxs_sign_part_t *sign_part = NULL;

            /* There might be multiple references.
             * For each create a sign_part and add to sign_part_list in the sign_ctx*/
            sign_part = oxs_sign_part_create(env);
            status = oxs_xml_sig_process_ref_node(env, sign_part, cur_node, scope_node);
            if(status == AXIS2_FAILURE)
            {
                oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                    "<ds:Reference> node processing failed ");
                return AXIS2_FAILURE;
            }

            /*Now we have a new sign_part. Add it to the list.*/
            axutil_array_list_add(sign_part_list, env, sign_part);

        }
        else
        {
            /*We do not process*/
        }
        cur_node = axiom_node_get_next_sibling(cur_node, env);
        /*axiom_util_get_next_sibling_element(axiom_node_get_data_element(cur_node, env), env,
         cur_node, &cur_node);*/
    }

    oxs_sign_ctx_set_sign_parts(sign_ctx, env, sign_part_list);
    /*Finished processing SignedInfo. Now we are processing the Signature Value element*/
    /*The very next child of SignedInfo Should be the ds:SignatureValue*/
    /*sig_val_node = axiom_node_get_next_sibling(signed_info_node, env);*/
    axiom_util_get_next_sibling_element(axiom_node_get_data_element(signed_info_node, env), env,
        signed_info_node, &sig_val_node);
    if(0 == axutil_strcmp(OXS_NODE_SIGNATURE_VALUE, axiom_util_get_localname(sig_val_node, env)))
    {
        axis2_char_t *sig_val = NULL;
        axis2_char_t *newline_removed = NULL;

        sig_val = oxs_token_get_signature_value(env, sig_val_node);
        if(!sig_val)
        {
            oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                "Cannot find signature value. ");
            return AXIS2_FAILURE;
        }
        /*We now remove \n in this text.Otherwise verifications failed.*/
        newline_removed = oxs_util_get_newline_removed_string(env, sig_val);
        if(!newline_removed)
        {
            oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
                "Cannot Remove new lines. ");
            return AXIS2_FAILURE;
        }
        oxs_sign_ctx_set_sig_val(sign_ctx, env, newline_removed);

        /*We can free newline_removed string as sign_ctx duplicates it*/
        AXIS2_FREE(env->allocator, newline_removed);
        newline_removed = NULL;
    }
    else
    {
        /*Error the node should be the ds:SignatureValue*/
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Cannot find <ds:SignatureValue> ");
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_verify_sign_part(
    const axutil_env_t *env,
    oxs_sign_part_t *sign_part)
{
    axis2_char_t *id = NULL;
    axis2_char_t *digest_mtd = NULL;
    axis2_char_t *digest_val = NULL;
    axis2_char_t *new_digest = NULL;
    axiom_node_t *node = NULL;
    axutil_array_list_t *transforms = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    id = oxs_sign_part_get_id(sign_part, env);
    digest_mtd = oxs_sign_part_get_digest_mtd(sign_part, env);
    digest_val = oxs_sign_part_get_digest_val(sign_part, env);
    node = oxs_sign_part_get_node(sign_part, env);
    transforms = oxs_sign_part_get_transforms(sign_part, env);

    AXIS2_LOG_INFO(env->log, "[oxs][xml_sig] Verifying signature part %s ", id);

    /*Do transforms to the node*/
    new_digest = oxs_xml_sig_transform_n_digest(env, node, transforms, digest_mtd);

    /*Compare values*/
    if(0 == axutil_strcmp(new_digest, digest_val))
    {
        AXIS2_LOG_INFO(env->log, "[oxs][xml_sig] Digest verification success for node Id= %s ", id);
        status = AXIS2_SUCCESS;
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Digest verification failed for node Id= %s. Calculated digest is [%s] and given digest is [%s]", id, new_digest, digest_val);
        status = AXIS2_FAILURE;
    }

    /*FREE*/
    AXIS2_FREE(env->allocator, new_digest);
    new_digest = NULL;

    return status;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_verify_digests(
    const axutil_env_t *env,
    oxs_sign_ctx_t *sign_ctx)
{
    axis2_status_t status = AXIS2_FAILURE;
    axutil_array_list_t *sign_parts = NULL;
    int i = 0;

    /*Get the sign_part list*/
    sign_parts = oxs_sign_ctx_get_sign_parts(sign_ctx, env);
    /*For each and every signature part in sig ctx,*/
    for(i = 0; i < axutil_array_list_size(sign_parts, env); i++)
    {
        oxs_sign_part_t *sign_part = NULL;

        /*Get ith sign_part*/
        sign_part = (oxs_sign_part_t*)axutil_array_list_get(sign_parts, env, i);
        status = oxs_xml_sig_verify_sign_part(env, sign_part);
        if(AXIS2_FAILURE == status)
        {
            return AXIS2_FAILURE;
        }
    }

    return status;
}


AXIS2_EXTERN axis2_status_t AXIS2_CALL
oxs_xml_sig_verify(
    const axutil_env_t *env,
    oxs_sign_ctx_t *sign_ctx,
    axiom_node_t *signature_node,
    axiom_node_t *scope_node)
{
    axis2_status_t status = AXIS2_FAILURE;
    axiom_node_t *signed_info_node = NULL;
    axiom_document_t *doc = NULL;
    axis2_char_t *c14n_mtd = NULL;
    axis2_char_t *content = NULL;
    axis2_char_t *signature_val = NULL;

    /*Set operation to verify*/
    oxs_sign_ctx_set_operation(sign_ctx, env, OXS_SIGN_OPERATION_VERIFY);

    /*Populate the sign_ctx by inspecting the ds:Signature node*/
    status = oxs_xml_sig_process_signature_node(env, sign_ctx, signature_node, scope_node);
    if(status != AXIS2_SUCCESS)
    {
        /*Something went wrong while processing the Signature node!!! :(*/
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "<ds:Signature> node processing failed ");
        return AXIS2_FAILURE;
    }

    /*-----------------------------------------------------------------------------------------*/
    /*At this point we have a ready to process signature context. So start verification process*/
    /*-----------------------------------------------------------------------------------------*/

    /*Verify the integrity of the signed parts by comparing the digest values of each and every reference.*/
    status = oxs_xml_sig_verify_digests(env, sign_ctx);

    if(AXIS2_FAILURE == status)
    {
        return AXIS2_FAILURE;
    }
    else
    {
        AXIS2_LOG_INFO(env->log, "[oxs][xml_sig] Digests verification SUCCESS ");
    }

    /*At this point we have compared the digest. Next step is to compare the Signature value */
    /*First get the signature value from the context*/
    signature_val = oxs_sign_ctx_get_sig_val(sign_ctx, env);

    /*Then we apply the C14N for the ds:SignedInfo*/
    signed_info_node = oxs_axiom_get_first_child_node_by_name(env, signature_node,
        OXS_NODE_SIGNEDINFO, OXS_DSIG_NS, OXS_DS);

    /*signed_info_node = oxs_axiom_get_first_child_node_by_name(env, signature_node,
     OXS_NODE_SIGNEDINFO, NULL,NULL );*/

    c14n_mtd = oxs_sign_ctx_get_c14n_mtd(sign_ctx, env);
    doc = axiom_node_get_document(signed_info_node, env);

    IF_AXIS2_LOG_DEBUG_ENABLED(env->log)
    {
        axis2_char_t *node_value = NULL;
        node_value = axiom_node_to_string(signed_info_node, env);
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart] C14N (verif1)= %s ", node_value);
        AXIS2_FREE(env->allocator, node_value);
    }

    oxs_c14n_apply_algo(env, doc, &content, NULL, signed_info_node, c14n_mtd);

    AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[oxs][xml_sig] C14N (verif2)=\n\n%s\n\n", content);

    /*In the final step we Verify*/
    status = oxs_sig_verify(env, sign_ctx, content, signature_val);

    AXIS2_FREE(env->allocator, content);
    content = NULL;

    if(AXIS2_FAILURE == status)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_SIG_VERIFICATION_FAILED,
            "Signature is not valid ");
        return AXIS2_FAILURE;
    }
    else
    {
        return AXIS2_SUCCESS;
    }

}
