blob: 71d8fb39c946178e0a09160d6ead590541a1af38 [file] [log] [blame]
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* 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 <oxs_axiom.h>
#include <axis2_qname.h>
#include <axiom_namespace.h>
#include <axiom_node.h>
#include <axiom_element.h>
#include <stdio.h>
#include <axis2_util.h>
#include <oxs_constants.h>
#include <oxs_token_encrypted_data.h>
#include <oxs_token_encrypted_key.h>
#include <oxs_token_encryption_method.h>
#include <oxs_ctx.h>
#include <oxs_error.h>
#include <oxs_buffer.h>
#include <oxs_enc_engine.h>
#include <oxs_cipher.h>
#include <openssl_cipher_ctx.h>
#include <openssl_crypt.h>
#include <openssl_constants.h>
#include <openssl_rsa.h>
#include <oxs_token_cipher_value.h>
#include <oxs_iv.h>
#include <openssl_util.h>
typedef struct oxs_enc_engine_impl
{
oxs_enc_engine_t enc_engine;
}
oxs_enc_engine_impl_t;
/** Interface to implementation conversion macro */
#define AXIS2_INTF_TO_IMPL(enc_engine) ((oxs_enc_engine_impl_t *)enc_engine)
/** private functions */
static void
oxs_enc_engine_init_ops(
oxs_enc_engine_t *enc_engine);
static axis2_status_t
oxs_enc_engine_cipher_data_node_read(
const axis2_env_t *env,
oxs_ctx_t * enc_ctx,
axiom_node_t* node);
static axis2_status_t
oxs_enc_engine_encrypted_data_node_read(
const axis2_env_t *env,
oxs_ctx_t * enc_ctx,
axiom_node_t* node);
/** public function */
axis2_status_t AXIS2_CALL
oxs_enc_engine_free(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env);
axis2_status_t AXIS2_CALL
oxs_enc_engine_prvkey_decrypt_data(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_buffer_t * input,
oxs_buffer_t * result,
axis2_char_t *filename);
axis2_status_t AXIS2_CALL
oxs_enc_engine_pubkey_encrypt_data(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_buffer_t * input,
oxs_buffer_t * result,
axis2_char_t *filename);
axis2_status_t AXIS2_CALL
oxs_enc_engine_get_encrypted_key(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t *enc_key_node,
oxs_key_t *prv_key,
oxs_key_t *session_key);
axis2_status_t AXIS2_CALL
oxs_enc_engine_crypt(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_ctx_t * enc_ctx,
oxs_buffer_t * input,
oxs_buffer_t * result);
axis2_status_t AXIS2_CALL
oxs_enc_engine_populate_cipher_value(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
oxs_buffer_t * databuf);
axis2_status_t AXIS2_CALL
oxs_enc_engine_decrypt_template(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
axis2_char_t** decrypted_data,
oxs_ctx_t * enc_ctx);
axis2_status_t AXIS2_CALL
oxs_enc_engine_encrypt_template(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
axis2_char_t* data,
oxs_ctx_t * enc_ctx);
/******* end of function headers ****************/
axis2_status_t AXIS2_CALL
oxs_enc_engine_free(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env)
{
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
if (enc_engine->ops)
{
AXIS2_FREE(env->allocator, enc_engine->ops);
enc_engine->ops = NULL;
}
if (enc_engine_impl)
{
AXIS2_FREE(env->allocator, enc_engine_impl);
enc_engine_impl = NULL;
}
return AXIS2_SUCCESS;
}
oxs_enc_engine_t *AXIS2_CALL
oxs_enc_engine_create(
const axis2_env_t *env)
{
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, NULL);
enc_engine_impl = (oxs_enc_engine_impl_t *) AXIS2_MALLOC(env->allocator,
sizeof(oxs_enc_engine_impl_t));
if (NULL == enc_engine_impl)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
return NULL;
}
enc_engine_impl->enc_engine.ops = AXIS2_MALLOC(env->allocator,
sizeof(oxs_enc_engine_ops_t));
if (NULL == enc_engine_impl->enc_engine.ops)
{
oxs_enc_engine_free(&(enc_engine_impl->enc_engine), env);
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
return NULL;
}
oxs_enc_engine_init_ops(&(enc_engine_impl->enc_engine));
return &(enc_engine_impl->enc_engine);
}
static void
oxs_enc_engine_init_ops(
oxs_enc_engine_t *enc_engine)
{
enc_engine->ops->free = oxs_enc_engine_free;
enc_engine->ops->prvkey_decrypt_data = oxs_enc_engine_prvkey_decrypt_data;
enc_engine->ops->pubkey_encrypt_data = oxs_enc_engine_pubkey_encrypt_data;
enc_engine->ops->get_encrypted_key = oxs_enc_engine_get_encrypted_key;
enc_engine->ops->crypt = oxs_enc_engine_crypt;
enc_engine->ops->populate_cipher_value = oxs_enc_engine_populate_cipher_value;
enc_engine->ops->decrypt_template = oxs_enc_engine_decrypt_template;
enc_engine->ops->encrypt_template = oxs_enc_engine_encrypt_template;
}
axis2_status_t AXIS2_CALL
oxs_enc_engine_get_encrypted_key(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t *enc_key_node,
oxs_key_t *prv_key,
oxs_key_t *session_key)
{
axis2_char_t *key_enc_algo = NULL;
axis2_char_t *encrypted_key_value = NULL;
axiom_node_t *enc_method_node = NULL;
axiom_node_t *cd_node = NULL;
axiom_node_t *cv_node = NULL;
axis2_status_t status = AXIS2_FAILURE;
oxs_buffer_t *encrypted_key_buf = NULL;
oxs_buffer_t *decrypted_key_buf = NULL;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*Verify*/
if (!enc_key_node)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_DECRYPT_FAILED,
"Passed encrypted key is NULL");
return AXIS2_FAILURE;
}
enc_method_node = (axiom_node_t*)oxs_axiom_get_first_child_node_by_name(env, enc_key_node, OXS_NodeEncryptionMethod, NULL, NULL);
if (!enc_method_node)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_DECRYPT_FAILED,
"Cannot find EncryptionMethodElement");
return AXIS2_FAILURE;
}
key_enc_algo = oxs_token_get_encryption_method(env, enc_method_node);
if (!key_enc_algo)
{
/*If not found use default*/
key_enc_algo = OXS_DEFAULT_KT_ALGO_HREF;
}
cd_node = (axiom_node_t*)oxs_axiom_get_first_child_node_by_name(env, enc_key_node, OXS_NodeCipherData, NULL, NULL);
if (!cd_node)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_DECRYPT_FAILED,
"Cannot find CipherData element");
return AXIS2_FAILURE;
}
cv_node = (axiom_node_t*)oxs_axiom_get_first_child_node_by_name(env, cd_node, OXS_NodeCipherValue, NULL, NULL);
if (!cv_node)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_DECRYPT_FAILED,
"Cannot find CipherValue element");
return AXIS2_FAILURE;
}
/*Encrypted key*/
encrypted_key_value = (axis2_char_t*)oxs_token_get_cipher_value(env, cv_node);
/*Create buffers for decryption*/
encrypted_key_buf = oxs_buffer_create(env);
status = OXS_BUFFER_POPULATE(encrypted_key_buf, env,
(unsigned char *)encrypted_key_value,
AXIS2_STRLEN(encrypted_key_value));
decrypted_key_buf = oxs_buffer_create(env);
/*Decrypt the encrypted key*/
status = oxs_enc_engine_prvkey_decrypt_data(enc_engine, env, encrypted_key_buf, decrypted_key_buf, OXS_KEY_GET_NAME(prv_key, env));
if (status == AXIS2_FAILURE)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"oxs_prvkey_decrypt_data failed");
return AXIS2_FAILURE;
}
/*Trim data to the key size*/
OXS_KEY_SET_DATA(session_key, env, OXS_BUFFER_GET_DATA(decrypted_key_buf, env));
OXS_KEY_SET_SIZE(session_key, env, OXS_BUFFER_GET_SIZE(decrypted_key_buf, env));
OXS_KEY_SET_USAGE(session_key, env, OXS_KEY_USAGE_DECRYPT);
return AXIS2_SUCCESS;
}
/*Decrypt data using the private key*/
axis2_status_t AXIS2_CALL
oxs_enc_engine_prvkey_decrypt_data(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_buffer_t *input,
oxs_buffer_t *result,
axis2_char_t *filename)
{
openssl_pkey_t *pkey = NULL;
axis2_char_t *decoded_encrypted_str = NULL;
unsigned char *decrypted = NULL;
int ret, declen;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
axis2_status_t status = AXIS2_FAILURE;
openssl_rsa_t *rsa = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*First do base64 decode*/
decoded_encrypted_str = AXIS2_MALLOC(env->allocator, axis2_base64_decode_len((char*)OXS_BUFFER_GET_DATA(input, env)));
ret = axis2_base64_decode(decoded_encrypted_str, (char*)OXS_BUFFER_GET_DATA(input, env));
printf("oxs_enc_engine_prvkey_decrypt_data\n");
/*Create a private key*/
pkey = openssl_pkey_create(env);
/*Load the private _key*/
status = OPENSSL_PKEY_LOAD(pkey, env, filename, "");/*TODO password*/
if (status == AXIS2_FAILURE)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"cannot load the private key from the file %s", filename);
return AXIS2_FAILURE;
}
/*Now we support only rsa*/
rsa = openssl_rsa_create(env);
declen = OPENSSL_RSA_PRV_DECRYPT(rsa, env, pkey, (unsigned char *)decoded_encrypted_str, &decrypted);
if (declen < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"decryption failed");
return AXIS2_FAILURE;
}
status = OXS_BUFFER_POPULATE(result, env, (unsigned char*)decrypted, declen);
return AXIS2_SUCCESS;
}
/*TODO better to have pk_ctx instead of individual parameters like filename, algorithm*/
axis2_status_t AXIS2_CALL
oxs_enc_engine_pubkey_encrypt_data(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_buffer_t *input,
oxs_buffer_t *result,
axis2_char_t *filename)
{
openssl_pkey_t *pkey = NULL;
axis2_char_t *encoded_str = NULL;
unsigned char *encrypted = NULL;
int ret, enclen, encodedlen ;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
openssl_rsa_t *rsa = NULL;
axis2_status_t status = AXIS2_FAILURE;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*Create a key*/
pkey = openssl_pkey_create(env);
/*Load the public key. Note: evp_pkey_load first try to load the private key. So need to provide the correct key*/
status = OPENSSL_PKEY_LOAD(pkey, env, filename, "");/*TODO password*/
if (status == AXIS2_FAILURE)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"cannot load the public key from the file %s", filename);
return AXIS2_FAILURE;
}
/*Now we support only rsa*/
rsa = openssl_rsa_create(env);
ret = OPENSSL_RSA_PUB_ENCRYPT(rsa, env, pkey, OXS_BUFFER_GET_DATA(input, env), &encrypted);
if (ret < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"openssl_rsa_pub_encrypt");
return AXIS2_FAILURE;
}
enclen = ret; /*return value is the length of the encrypted data*/
/*base64 encode*/
encodedlen = axis2_base64_encode_len(enclen);
encoded_str = AXIS2_MALLOC(env->allocator, encodedlen);
ret = axis2_base64_encode(encoded_str, (const char *)encrypted, enclen);
if (ret < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"axis2_base64_encode");
return AXIS2_FAILURE;
}
/*Attach the result to the result buf*/
status = OXS_BUFFER_POPULATE(result, env, (unsigned char*)AXIS2_STRDUP(encoded_str, env), encodedlen);
return AXIS2_SUCCESS;
}
/*Encrypt or decrypt an input depending on what is set in the enc_ctx*/
/*TODO Default IV*/
axis2_status_t AXIS2_CALL
oxs_enc_engine_crypt(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
oxs_ctx_t * enc_ctx,
oxs_buffer_t *input,
oxs_buffer_t *result)
{
unsigned char *out_main_buf = NULL;
openssl_cipher_ctx_t *oc_ctx = NULL;
axis2_char_t *iv = NULL;
axis2_char_t *key = NULL;
axis2_char_t *cipher_name = NULL;
axis2_char_t *encoded_str = NULL;
axis2_char_t *in_data = NULL;
int ret, enclen, encodedlen, decoded_len;
openssl_cipher_property_t *cprop = NULL;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*Initializations*/
ret = AXIS2_FAILURE;
enclen = -1;
encodedlen = -1;
/*Create the context*/
oc_ctx = openssl_cipher_ctx_create(env);
if (!oc_ctx)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"openssl_cipher_ctx_create failed");
return AXIS2_FAILURE;
}
/*Get cipher property*/
cprop = oxs_get_cipher_property_for_url(env, OXS_CTX_GET_ENC_MTD_ALGORITHM(enc_ctx, env));
/*Set the IV*/
iv = AXIS2_STRNDUP((axis2_char_t*)oxs_iv_generate_for_algo(env, OXS_CTX_GET_ENC_MTD_ALGORITHM(enc_ctx, env)),
OPENSSL_CIPHER_PROPERTY_GET_IV_SIZE(cprop, env),
env);
ret = OPENSSL_CIPHER_CTX_SET_IV(oc_ctx, env, iv);
/*Set the key*/
key = AXIS2_STRNDUP((axis2_char_t*)OXS_KEY_GET_DATA(OXS_CTX_GET_KEY(enc_ctx,
env),
env),
OPENSSL_CIPHER_PROPERTY_GET_KEY_SIZE(cprop, env),
env);
ret = OPENSSL_CIPHER_CTX_SET_KEY(oc_ctx, env, key);
/*Set the cipher*/
cipher_name = (axis2_char_t*)OPENSSL_CIPHER_PROPERTY_GET_NAME(cprop, env);
if (!cipher_name)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"oxs_get_cipher failed");
return AXIS2_FAILURE;
}
ret = OPENSSL_CIPHER_CTX_SET_CIPHER(oc_ctx,
env,
(EVP_CIPHER*)openssl_get_evp_cipher_by_name(env, (axis2_char_t*)cipher_name));
/****************Encryption or decryption happens here ************/
/*If this is to encrypt we simply pass the data to crypto function*/
if (OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_ENCRYPT)
{
enclen = openssl_block_cipher_crypt(env, oc_ctx,
OXS_BUFFER_GET_DATA(input, env),
OXS_BUFFER_GET_SIZE(input, env),
&out_main_buf, OPENSSL_ENCRYPT);
/*If this is to decrypt, then we need to base64decode first*/
}
else if (OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_DECRYPT)
{
in_data = AXIS2_MALLOC(env->allocator, axis2_base64_decode_len((char*)(OXS_CTX_GET_INPUT_DATA(enc_ctx, env))));
/*axis2_base64_decode(in_data, (char*)(enc_ctx->inputdata)); */
decoded_len = axis2_base64_decode_binary((unsigned char*)in_data, (char*)(OXS_CTX_GET_INPUT_DATA(enc_ctx, env)));
if (decoded_len < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"base64 decoding failed");
}
enclen = openssl_block_cipher_crypt(env, oc_ctx,
(unsigned char*)in_data, decoded_len, &out_main_buf, OPENSSL_DECRYPT);
}
else
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Invalid operation type %d", OXS_CTX_GET_OPERATION(enc_ctx, env));
return AXIS2_FAILURE;
}
if (enclen < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"openssl_block_cipher_crypt failed");
return AXIS2_FAILURE;
}
#if 0
FILE *outf;
outf = fopen("outbuf", "wb");
fwrite(out_main_buf, 1, enclen, outf);
#endif
/*If the operation is to encrypt we will encode the encrypted data*/
if (OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_ENCRYPT)
{
encodedlen = axis2_base64_encode_len(enclen);
encoded_str = AXIS2_MALLOC(env->allocator, encodedlen);
ret = axis2_base64_encode(encoded_str, (const char *)out_main_buf, enclen);
if (ret < 0)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"axis2_base64_encode");
return AXIS2_FAILURE;
}
/*Attach the result to the result buf*/
ret = OXS_BUFFER_POPULATE(result, env, (unsigned char*)AXIS2_STRDUP(encoded_str, env), encodedlen);
}
else if (OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_DECRYPT)
{
ret = OXS_BUFFER_POPULATE(result, env, AXIS2_STRMEMDUP(out_main_buf, enclen, env), enclen);
}
else
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Invalid operation type %d", OXS_CTX_GET_OPERATION(enc_ctx, env));
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}
axis2_status_t AXIS2_CALL
oxs_enc_engine_populate_cipher_value(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
oxs_buffer_t *databuf)
{
axis2_status_t ret = AXIS2_FAILURE;
axiom_element_t *template_ele = NULL;
axiom_element_t *cv_ele = NULL;
axiom_element_t *cd_ele = NULL;
axiom_node_t *cv_node = NULL;
axiom_node_t *cd_node = NULL;
axis2_qname_t *qname = NULL;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
template_ele = AXIOM_NODE_GET_DATA_ELEMENT(template_node, env);
if (!template_ele)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Cannot retriew element from the template given");
return AXIS2_FAILURE;
}
/*Get CipherData*/
qname = axis2_qname_create(env, OXS_NodeCipherData, NULL, NULL);
cd_ele = AXIOM_ELEMENT_GET_FIRST_CHILD_WITH_QNAME(template_ele, env, qname, template_node, &cd_node);
if (!cd_ele)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Cannot retriew CipherData element from %s", AXIOM_ELEMENT_GET_LOCALNAME(template_ele, env));
return AXIS2_FAILURE;
}
AXIS2_QNAME_FREE(qname, env);
qname = NULL;
/*Get CipherValue*/
qname = axis2_qname_create(env, OXS_NodeCipherValue, NULL, NULL);
cv_ele = AXIOM_ELEMENT_GET_FIRST_CHILD_WITH_QNAME(cd_ele, env, qname, cd_node, &cv_node);
if (!cv_ele)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Cannot retriew CipherValue element from %s", AXIOM_ELEMENT_GET_LOCALNAME(cd_ele, env));
return AXIS2_FAILURE;
}
ret = AXIOM_ELEMENT_SET_TEXT(cv_ele, env, (axis2_char_t *)OXS_BUFFER_GET_DATA(databuf, env) , cv_node);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Cannot set data to the CipherValue element");
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}
/*We expect user to provide a template as below*/
axis2_status_t AXIS2_CALL
oxs_enc_engine_decrypt_template(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
axis2_char_t** decrypted_data,
oxs_ctx_t * enc_ctx
)
{
axis2_status_t ret = AXIS2_FAILURE;
oxs_buffer_t *input = NULL;
oxs_buffer_t *result = NULL;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*Populate enc_ctx*/
OXS_CTX_SET_OPERATION(enc_ctx, env, OXS_CTX_OPERATION_DECRYPT);
OXS_CTX_SET_MODE(enc_ctx, env, OXS_CTX_MODE_ENCRYPTED_DATA);
ret = oxs_enc_engine_encrypted_data_node_read(env, enc_ctx, template_node);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"reading encrypted data failed");
return ret;
}
/*Now look for data to be decrypted*/
input = oxs_buffer_create(env);
ret = OXS_BUFFER_POPULATE(input, env, (unsigned char *)OXS_CTX_GET_INPUT_DATA(enc_ctx, env),
AXIS2_STRLEN(OXS_CTX_GET_INPUT_DATA(enc_ctx, env)));
/*Initialize the result buffer*/
result = oxs_buffer_create(env);
ret = oxs_enc_engine_crypt(enc_engine, env, enc_ctx, input, result);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_DECRYPT_FAILED,
"oxs_enc_decrypt failed");
return ret;
}
*decrypted_data = AXIS2_MALLOC(env->allocator, OXS_BUFFER_GET_SIZE(result, env));
*decrypted_data = (axis2_char_t*)OXS_BUFFER_GET_DATA(result, env);
return ret;
}
/*We expect user to provide a template as below*/
/**/
axis2_status_t AXIS2_CALL
oxs_enc_engine_encrypt_template(
oxs_enc_engine_t *enc_engine,
const axis2_env_t *env,
axiom_node_t* template_node,
axis2_char_t* data,
oxs_ctx_t * enc_ctx
)
{
axis2_status_t ret = AXIS2_FAILURE;
oxs_buffer_t *input = NULL;
oxs_buffer_t *result = NULL;
oxs_enc_engine_impl_t *enc_engine_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
enc_engine_impl = AXIS2_INTF_TO_IMPL(enc_engine);
/*Populate enc_ctx*/
OXS_CTX_SET_OPERATION(enc_ctx, env, OXS_CTX_OPERATION_ENCRYPT);
OXS_CTX_SET_MODE(enc_ctx, env, OXS_CTX_MODE_ENCRYPTED_DATA);
ret = oxs_enc_engine_encrypted_data_node_read(env, enc_ctx, template_node);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"openssl_block_cipher_crypt failed");
return ret;
}
/*We've populated the context*/
/*Create the input buffer*/
input = oxs_buffer_create(env);
ret = OXS_BUFFER_POPULATE(input, env, (unsigned char *)data, AXIS2_STRLEN(data));
result = oxs_buffer_create(env);
ret = oxs_enc_engine_crypt(enc_engine, env, enc_ctx, input, result);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"oxs_enc_encrypt failed");
return ret;
}
ret = oxs_enc_engine_populate_cipher_value(enc_engine, env, template_node, result);
if (ret != AXIS2_SUCCESS)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"oxs_enc_engine_populate_cipher_value failed");
return ret;
}
return AXIS2_SUCCESS;
}
static axis2_status_t
oxs_enc_engine_cipher_data_node_read(const axis2_env_t *env,
oxs_ctx_t * enc_ctx, axiom_node_t* node_cipher_data)
{
axiom_node_t* cur = NULL;
axiom_element_t *ele = NULL;
axis2_char_t *data = NULL;
/*We've a cipher data node here.
The child element is either a CipherReference or a CipherValue element*/
cur = AXIOM_NODE_GET_FIRST_CHILD(node_cipher_data, env);
if (!cur)
{
return AXIS2_FAILURE;
}
if (oxs_axiom_check_node_name(env, cur, OXS_NodeCipherValue, OXS_EncNs))
{
/*Got a cipher value*/
if (OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_DECRYPT)
{
OXS_CTX_SET_CIPHER_VALUE_NODE(enc_ctx, env, cur);
ele = AXIOM_NODE_GET_DATA_ELEMENT(cur, env);
/*Read data from the CipherValue node and set it to the context*/
data = AXIOM_ELEMENT_GET_TEXT(ele, env, cur);
OXS_CTX_SET_INPUT_DATA(enc_ctx, env, AXIS2_STRDUP(data, env));
}
}
else if (oxs_axiom_check_node_name(env, cur, OXS_NodeCipherReference, OXS_EncNs))
{
/*Got a cipher reference*/
/*TODO : Support Cipher references*/
/*Check cipher reference and set it to ctx->cipher_value_node*/
}
return AXIS2_SUCCESS;
}
/**
* We have EncryptedData of EncryptedKey node by now.
* So process it and populate the ctx.
*/
static axis2_status_t
oxs_enc_engine_encrypted_data_node_read(const axis2_env_t *env,
oxs_ctx_t * enc_ctx, axiom_node_t* node)
{
axiom_node_t* cur = NULL;
axiom_element_t *ele = NULL;
int ret;
/* Operation is either encrypt or decrypt */
if (!((OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_ENCRYPT) ||
(OXS_CTX_GET_OPERATION(enc_ctx, env) == OXS_CTX_OPERATION_DECRYPT)))
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"Operation is NOT either encrypt or decrypt");
return AXIS2_FAILURE;
}
/*Check which mode we are in.
1. Encrypted Data
2. Encrypted Key
*/
switch (OXS_CTX_GET_MODE(enc_ctx, env))
{
case OXS_CTX_MODE_ENCRYPTED_DATA:
if (!(oxs_axiom_check_node_name(env, node, OXS_NodeEncryptedData, OXS_EncNs)))
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"No %s node found", OXS_NodeEncryptedData);
return AXIS2_FAILURE;
}
break;
case OXS_CTX_MODE_ENCRYPTED_KEY:
if (!(oxs_axiom_check_node_name(env, node, OXS_NodeEncryptedKey, OXS_EncNs)))
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"No %s node found", OXS_NodeEncryptedKey);
return AXIS2_FAILURE;
}
break;
}
OXS_CTX_SET_ENC_DATA_NODE(enc_ctx, env, node);
/*Element is either Encrypted Data or Encrypted Key*/
ele = AXIOM_NODE_GET_DATA_ELEMENT(node, env);
if (!ele)
{
oxs_error(ERROR_LOCATION, OXS_ERROR_INVALID_DATA,
"No element found");
return AXIS2_FAILURE;
}
/*Populate ctx with id, type, mime and encoding types if found*/
OXS_CTX_SET_ID(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrId));
OXS_CTX_SET_TYPE(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrType));
OXS_CTX_SET_MIME_TYPE(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrMimeType));
OXS_CTX_SET_ENCODING(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrEncoding));
if (OXS_CTX_GET_MODE(enc_ctx, env) == OXS_CTX_MODE_ENCRYPTED_KEY)
{
OXS_CTX_SET_RECIPIENT(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrRecipient));
}
cur = AXIOM_NODE_GET_FIRST_CHILD(node, env);
/* first node is optional EncryptionMethod, we'll read it later */
if ((cur) && (oxs_axiom_check_node_name(env, cur, OXS_NodeEncryptionMethod, OXS_EncNs)))
{
OXS_CTX_SET_ENC_METHOD_NODE(enc_ctx, env, cur);
cur = AXIOM_NODE_GET_NEXT_SIBLING(cur, env);
}
/* next node is optional KeyInfo, we'll process it later */
if ((cur) && (oxs_axiom_check_node_name(env, cur, OXS_NodeKeyInfo, OXS_DSigNs)))
{
OXS_CTX_SET_KEY_INFO_NODE(enc_ctx, env, cur);
cur = AXIOM_NODE_GET_NEXT_SIBLING(cur, env);
}
/* next is required CipherData node */
if ((cur == NULL) || (!oxs_axiom_check_node_name(env, cur, OXS_NodeCipherData, OXS_EncNs)))
{
return AXIS2_FAILURE;
}
ret = oxs_enc_engine_cipher_data_node_read(env, enc_ctx, cur);
if (ret < 0)
{
return AXIS2_FAILURE;
}
/* now read the encryption method node */
if (OXS_CTX_GET_ENC_METHOD_NODE(enc_ctx, env))
{
ele = AXIOM_NODE_GET_DATA_ELEMENT(OXS_CTX_GET_ENC_METHOD_NODE(enc_ctx, env), env);
OXS_CTX_SET_ENC_MTD_ALGORITHM(enc_ctx, env, AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(ele, env, OXS_AttrAlgorithm));
}
/*If you need to populate the context more this is the place*/
return AXIS2_SUCCESS;
}