/******************************************************************************* * Ledger Nano S - Secure firmware * (c) 2022 Ledger * * 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 lcx_eddsa.h * @brief EDDSA (Edwards Curve Digital Signature Algorithm) * * EDDSA is a digital signature scheme relying on Edwards curves, especially * Ed25519 and Ed448. Refer to RFC8032 * for more details. */ #ifdef HAVE_EDDSA #include "lcx_ecfp.h" #include "lcx_wrappers.h" #ifndef LCX_EDDSA_H #define LCX_EDDSA_H /** * @brief Signs a message digest. * * @details The signature is done according to the EDDSA specification * RFC8032 . * * @param[in] pvkey Private key. * This shall be initialized with #cx_ecfp_init_private_key_no_throw. * * @param[in] hashID Message digest algorithm identifier. * Algorithms supported: * - SHA512 * - SHA3 * - Keccak * * @param[in] hash Pointer to the message digest. * * @param[in] hash_len Length of the digest. * * @param[out] sig Buffer where to store the signature. * * @param[in] sig_len Length of the signature. * * @return Error code: * - CX_OK on success * - CX_EC_INVALID_CURVE * - CX_INVALID_PARAMETER * - INVALID_PARAMETER * - CX_NOT_UNLOCKED * - CX_INVALID_PARAMETER_SIZE * - CX_MEMORY_FULL * - CX_NOT_LOCKED * - CX_INVALID_PARAMETER_SIZE * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT * - CX_INTERNAL_ERROR * - CX_INVALID_PARAMETER_VALUE */ cx_err_t cx_eddsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, cx_md_t hashID, const uint8_t * hash, size_t hash_len, uint8_t * sig, size_t sig_len); /** * @brief Signs a message digest. * * @details The signature is done according to the EDDSA specification * RFC8032 . * This function throws an exception if the computation doesn't * succeed. * * @warning It is recommended to use #cx_eddsa_sign_no_throw rather than * this function. * * @param[in] pvkey Private key. * This shall be initialized with #cx_ecfp_init_private_key_no_throw. * * @param[in] mode Mode. This parameter is not used. * * @param[in] hashID Message digest algorithm identifier. * Algorithms supported: * - SHA512 * - SHA3 * - Keccak * * @param[in] hash Pointer to the message digest. * * @param[in] hash_len Length of the digest. * * @param[in] ctx Pointer to the context. This parameter is not used. * * @param[in] ctx_len Length of *ctx*. This parameter is not used. * * @param[out] sig Buffer where to store the signature. * * @param[in] sig_len Length of the signature. * * @param[in] info Additional information. This parameter is not used. * * @return Length of the signature. * * @throws CX_EC_INVALID_CURVE * @throws CX_INVALID_PARAMETER * @throws INVALID_PARAMETER * @throws CX_NOT_UNLOCKED * @throws CX_INVALID_PARAMETER_SIZE * @throws CX_MEMORY_FULL * @throws CX_NOT_LOCKED * @throws CX_INVALID_PARAMETER_SIZE * @throws CX_EC_INVALID_POINT * @throws CX_EC_INFINITE_POINT * @throws CX_INTERNAL_ERROR * @throws CX_INVALID_PARAMETER_VALUE */ static inline size_t cx_eddsa_sign ( const cx_ecfp_private_key_t * pvkey, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, const unsigned char * ctx, unsigned int ctx_len, unsigned char * sig, unsigned int sig_len, unsigned int * info ) { UNUSED(ctx); UNUSED(ctx_len); UNUSED(mode); UNUSED(info); CX_THROW(cx_eddsa_sign_no_throw(pvkey, hashID, hash, hash_len, sig, sig_len)); size_t size; CX_THROW(cx_ecdomain_parameters_length(pvkey->curve, &size)); return 2 * size; } /** * @brief Verifies a signature. * * @details The verification is done according to the specification * RFC8032 . * * @param[in] pukey Public key. * This shall be initialized with #cx_ecfp_init_public_key_no_throw. * * @param[in] hashID Message digest algorithm identifier. * Algorithms supported: * - SHA512 * - SHA3 * - Keccak * * @param[in] hash Pointer to the message digest. * * @param[in] hash_len Length of the digest. * * @param[out] sig Pointer to the signature. * * @param[in] sig_len Length of the signature. * * @return 1 if the signature is verified, otherwise 0. */ bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, cx_md_t hashID, const uint8_t * hash, size_t hash_len, const uint8_t * sig, size_t sig_len); /** * @brief Verifies a signature. * * @details The verification is done according to the specification * RFC8032 . * This function throws an exception if the computation doesn't * succeed. * * @param[in] pukey Public key. * THis shall be initialized with #cx_ecfp_init_public_key_no_throw. * * @param[in] mode Mode. This parameter is not used. * * @param[in] hashID Message digest algorithm identifier. * Algorithms supported: * - SHA512 * - SHA3 * - Keccak * * @param[in] hash Pointer to the message digest. * * @param[in] hash_len Length of the digest. * * @param[in] ctx Pointer to the context. This parameter is not used. * * @param[in] ctx_len Length of the context. This parameter is not used. * * @param[out] sig Pointer to the signature. * * @param[in] sig_len Length of the signature. * * @return 1 if the signature is verified, otherwise 0. */ static inline int cx_eddsa_verify ( const cx_ecfp_public_key_t * pukey, int mode, cx_md_t hashID, const unsigned char * hash, unsigned int hash_len, const unsigned char * ctx, unsigned int ctx_len, const unsigned char * sig, unsigned int sig_len ) { UNUSED(mode); UNUSED(ctx); UNUSED(ctx_len); return cx_eddsa_verify_no_throw(pukey, hashID, hash, hash_len, sig, sig_len); } /** * @brief Encodes the curve point coordinates. * * @param[in, out] coord A pointer to the point coordinates in the form x|y. * * @param[in] len Length of the coordinates. * * @param[in] sign Sign of the x-coordinate. * */ void cx_encode_coord(uint8_t * coord, int len, int sign); /** * @brief Decodes the curve point coordinates. * * @param[in, out] coord A pointer to the point encoded coordinates. * * @param[in] len Length of the encoded coordinates. * * @return Sign of the x-coordinate. */ int cx_decode_coord(uint8_t * coord, int len); #endif #endif // HAVE_EDDSA