blob: d05f3a19c33ce5bbe7376b2489d20d79278a6f11 [file] [log] [blame]
/*
* 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*/
AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[RAMPART]Signature received [%s]", signature);
AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[RAMPART]Signature calculated [%s]", signed_val);
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;
}
}