/*
 *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
 *
 *  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
 */

/**
 * @file   yaca_sign.h
 * @brief  Advanced API for the integrity handling - HMAC, CMAC and digital signature.
 */

#ifndef YACA_SIGN_H
#define YACA_SIGN_H

#include <stddef.h>
#include <yaca_types.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @addtogroup CAPI_YACA_INTEGRITY_MODULE
 * @{
 */

/**
 * @brief  Initializes a signature context for asymmetric signatures.
 *
 * @since_tizen 3.0
 *
 * @remarks  For verification use yaca_verify_initialize(), yaca_verify_update() and
 *           yaca_verify_finalize() functions with matching public key.
 *
 * @remarks  For RSA operations the default padding used is #YACA_PADDING_PKCS1. It can be
 *           changed using yaca_context_set_property() with #YACA_PROPERTY_PADDING.
 *
 * @remarks  For #YACA_DIGEST_SHA384 and #YACA_DIGEST_SHA512 the RSA key size must be bigger than
 *           #YACA_KEY_LENGTH_512BIT.
 *
 * @remarks  Using of #YACA_DIGEST_MD5 algorithm for DSA and ECDSA operations is prohibited.
 *
 * @remarks  Using of #YACA_DIGEST_MD5 or #YACA_DIGEST_SHA224 with #YACA_PADDING_X931 is prohibited.
 *
 * @remarks  The @a ctx should be released using yaca_context_destroy().
 *
 * @param[out] ctx      Newly created context
 * @param[in]  algo     Digest algorithm that will be used
 * @param[in]  prv_key  Private key that will be used, algorithm is deduced based
 *                      on key type, supported key types:
 *                      - #YACA_KEY_TYPE_RSA_PRIV,
 *                      - #YACA_KEY_TYPE_DSA_PRIV,
 *                      - #YACA_KEY_TYPE_EC_PRIV
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a algo or @a prv_key)
 * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see #yaca_key_type_e
 * @see #yaca_digest_algorithm_e
 * @see #yaca_padding_e
 * @see yaca_context_set_property()
 * @see yaca_sign_update()
 * @see yaca_sign_finalize()
 * @see yaca_verify_initialize()
 * @see yaca_verify_update()
 * @see yaca_verify_finalize()
 * @see yaca_context_destroy()
 */
int yaca_sign_initialize(yaca_context_h *ctx,
						 yaca_digest_algorithm_e algo,
						 const yaca_key_h prv_key);

/**
 * @brief  Initializes a signature context for HMAC.
 *
 * @since_tizen 3.0
 *
 * @remarks  For verification, calculate message HMAC and compare with received MAC using
 *           yaca_memcmp().
 *
 * @remarks  The @a ctx should be released using yaca_context_destroy().
 *
 * @param[out] ctx      Newly created context
 * @param[in]  algo     Digest algorithm that will be used
 * @param[in]  sym_key  Symmetric key that will be used, supported key types:
 *                      - #YACA_KEY_TYPE_SYMMETRIC,
 *                      - #YACA_KEY_TYPE_DES
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a algo or @a sym_key)
 * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see #yaca_key_type_e
 * @see #yaca_digest_algorithm_e
 * @see yaca_sign_update()
 * @see yaca_sign_finalize()
 * @see yaca_memcmp()
 * @see yaca_context_destroy()
 */
int yaca_sign_initialize_hmac(yaca_context_h *ctx,
							  yaca_digest_algorithm_e algo,
							  const yaca_key_h sym_key);

/**
 * @brief  Initializes a signature context for CMAC.
 *
 * @since_tizen 3.0
 *
 * @remarks  For verification, calculate message CMAC and compare with received MAC using
 *           yaca_memcmp().
 *
 * @remarks  The @a ctx should be released using yaca_context_destroy().
 *
 * @param[out] ctx      Newly created context
 * @param[in]  algo     Encryption algorithm that will be used
 * @param[in]  sym_key  Symmetric key that will be used, supported key types:
 *                      - #YACA_KEY_TYPE_SYMMETRIC,
 *                      - #YACA_KEY_TYPE_DES
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a algo or @a sym_key)
 * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see #yaca_key_type_e
 * @see #yaca_encrypt_algorithm_e
 * @see yaca_sign_update()
 * @see yaca_sign_finalize()
 * @see yaca_memcmp()
 * @see yaca_context_destroy()
 */
int yaca_sign_initialize_cmac(yaca_context_h *ctx,
							  yaca_encrypt_algorithm_e algo,
							  const yaca_key_h sym_key);

/**
 * @brief  Feeds the message into the digital signature or MAC algorithm.
 *
 * @since_tizen 3.0
 *
 * @param[in,out] ctx          Context created by yaca_sign_initialize(),
 *                             yaca_sign_initialize_hmac() or yaca_sign_initialize_cmac()
 * @param[in]     message      Message to be signed
 * @param[in]     message_len  Length of the message
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL, 0,
 *                                       invalid @a ctx)
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see yaca_sign_initialize()
 * @see yaca_sign_finalize()
 * @see yaca_sign_initialize_hmac()
 * @see yaca_sign_initialize_cmac()
 */
int yaca_sign_update(yaca_context_h ctx,
					 const char *message,
					 size_t message_len);

/**
 * @brief  Calculates the final signature or MAC.
 *
 * @since_tizen 3.0
 *
 * @remarks  Skipping yaca_sign_update() and calling only yaca_sign_finalize() will produce a
 *           signature or MAC of an empty message.
 *
 * @param[in,out] ctx              A valid sign context
 * @param[out]    signature        Buffer for the MAC or the message signature
 *                                 (must be allocated by client, see yaca_context_get_output_length())
 * @param[out]    signature_len    Length of the MAC or the signature,
 *                                 actual number of bytes written will be returned here
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a ctx)
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see yaca_sign_initialize()
 * @see yaca_sign_update()
 * @see yaca_sign_initialize_hmac()
 * @see yaca_sign_initialize_cmac()
 * @see yaca_context_get_output_length()
 */
int yaca_sign_finalize(yaca_context_h ctx,
					   char *signature,
					   size_t *signature_len);

/**
 * @brief  Initializes a signature verification context for asymmetric signatures.
 *
 * @since_tizen 3.0
 *
 * @remarks  For RSA operations the default padding used is #YACA_PADDING_PKCS1. It can be
 *           changed using yaca_context_set_property() with #YACA_PROPERTY_PADDING.
 *           For verify to succeed it has to be set to the same value it was signed with.
 *
 * @remarks  The @a ctx should be released using yaca_context_destroy().
 *
 * @param[out] ctx      Newly created context
 * @param[in]  algo     Digest algorithm that will be used
 * @param[in]  pub_key  Public key that will be used, algorithm is deduced based on
 *                      key type, supported key types:
 *                      - #YACA_KEY_TYPE_RSA_PUB,
 *                      - #YACA_KEY_TYPE_DSA_PUB,
 *                      - #YACA_KEY_TYPE_EC_PUB
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a algo or @a pub_key)
 * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see #yaca_key_type_e
 * @see #yaca_digest_algorithm_e
 * @see #yaca_padding_e
 * @see yaca_context_set_property()
 * @see yaca_verify_update()
 * @see yaca_verify_finalize()
 * @see yaca_context_destroy()
 */
int yaca_verify_initialize(yaca_context_h *ctx,
						   yaca_digest_algorithm_e algo,
						   const yaca_key_h pub_key);

/**
 * @brief  Feeds the message into the digital signature verification algorithm.
 *
 * @since_tizen 3.0
 *
 * @param[in,out] ctx          Context created by yaca_verify_initialize()
 * @param[in]     message      Message
 * @param[in]     message_len  Length of the message
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL, 0,
 *                                       invalid @a ctx)
 * @retval #YACA_ERROR_INTERNAL Internal error
 *
 * @see yaca_verify_initialize()
 * @see yaca_verify_finalize()
 */
int yaca_verify_update(yaca_context_h ctx,
					   const char *message,
					   size_t message_len);

/**
 * @brief  Performs the verification.
 *
 * @since_tizen 3.0
 *
 * @remarks  Skipping yaca_verify_update() and calling only yaca_verify_finalize() will verify
 *           the signature of an empty message.
 *
 * @param[in,out] ctx            A valid verify context
 * @param[in]     signature      Message signature to be verified
 * @param[in]     signature_len  Length of the signature
 *
 * @return #YACA_ERROR_NONE on success, negative on error
 * @retval #YACA_ERROR_NONE Successful
 * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL,
 *                                       invalid @a ctx)
 * @retval #YACA_ERROR_INTERNAL Internal error
 * @retval #YACA_ERROR_DATA_MISMATCH The verification failed
 *
 * @see yaca_verify_initialize()
 * @see yaca_verify_update()
 * @see yaca_sign_finalize()
 */
int yaca_verify_finalize(yaca_context_h ctx,
						 const char *signature,
						 size_t signature_len);

/**
 * @}
 */

#ifdef __cplusplus
} /* extern */
#endif

#endif /* YACA_SIGN_H */
