diff --git a/src/common/errcode.c b/src/common/errcode.c index 9671ee581c86e04d53300508b5b008f255218fbd..10b6546e828d0aeb81ab171f01a7d1e6ab29e358 100644 --- a/src/common/errcode.c +++ b/src/common/errcode.c @@ -97,13 +97,14 @@ const error_table_t knot_error_msgs[] = { { KNOT_KEY_EPRIVATE_KEY_OPEN, "Cannot open private key file." }, { KNOT_KEY_EPUBLIC_KEY_INVALID, "Public key file is invalid." }, - /* Key signing errors. */ + /* Key signing/verification errors. */ { KNOT_DNSSEC_ENOTSUP, "Signing algorithm is not supported." }, { KNOT_DNSSEC_EINVALID_KEY, "The signing key is invalid." }, { KNOT_DNSSEC_EASSIGN_KEY, "Cannot assign the key." }, { KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT, "Cannot create digest context." }, { KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE, "Unexpected signature size." }, { KNOT_DNSSEC_EDECODE_RAW_SIGNATURE, "Cannot decode the raw signature." }, + { KNOT_DNSSEC_EINVALID_SIGNATURE, "Signature is invalid." }, { KNOT_DNSSEC_ESIGN, "Cannot create the signature." }, /* NSEC3 errors. */ diff --git a/src/common/errcode.h b/src/common/errcode.h index 92f68d5374b74cce0debbec0f1a5c85545c95ca7..038cb16d6965c36b6912db8a989d2cf89401b686 100644 --- a/src/common/errcode.h +++ b/src/common/errcode.h @@ -123,6 +123,7 @@ enum knot_error { KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT, KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE, KNOT_DNSSEC_EDECODE_RAW_SIGNATURE, + KNOT_DNSSEC_EINVALID_SIGNATURE, KNOT_DNSSEC_ESIGN, /* NSEC3 errors. */ diff --git a/src/libknot/dnssec/sign.c b/src/libknot/dnssec/sign.c index a165f66a857f10c165bbc253e667eafe21c9b236..f91737f7726bbf2ad0c89e03f33ea0c689fbe93a 100644 --- a/src/libknot/dnssec/sign.c +++ b/src/libknot/dnssec/sign.c @@ -56,6 +56,8 @@ struct algorithm_functions { int (*sign_add)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t); //! \brief Callback: finish the signing and write out the signature. int (*sign_write)(const knot_dnssec_sign_context_t *, uint8_t *); + //! \brief Callback: finish the signing and validate the signature. + int (*sign_verify)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t); }; /** @@ -97,7 +99,7 @@ static int any_sign_add(const knot_dnssec_sign_context_t *context, assert(context); assert(data); - if (!EVP_SignUpdate(context->digest_context, data, data_size)) + if (!EVP_DigestUpdate(context->digest_context, data, data_size)) return KNOT_DNSSEC_ESIGN; return KNOT_EOK; @@ -114,7 +116,7 @@ static int any_sign_add(const knot_dnssec_sign_context_t *context, * * \return Error code, KNOT_EOK if successful. */ -static int any_sign_finish(const knot_dnssec_sign_context_t *context, +static int any_sign_write(const knot_dnssec_sign_context_t *context, uint8_t **signature, size_t *signature_size) { assert(context); @@ -142,6 +144,30 @@ static int any_sign_finish(const knot_dnssec_sign_context_t *context, return KNOT_EOK; } +/*! + * \brief Verify the DNSSEC signature for supplied data. + * + * \param context DNSSEC signature context. + * \param signature Pointer to signature. + * \param signature_size Size of the signature. + * + * \return Error code. + * \retval KNOT_EOK The signature is valid. + * \retval KNOT_DNSSEC_EINVALID_SIGNATURE The signature is invalid. + */ +static int any_sign_verify(const knot_dnssec_sign_context_t *context, + const uint8_t *signature, size_t signature_size) +{ + assert(context); + assert(signature); + + int result = EVP_VerifyFinal(context->digest_context, + signature, signature_size, + context->key->data->private_key); + + return result == 1 ? KNOT_EOK : KNOT_DNSSEC_EINVALID_SIGNATURE; +} + /*- RSA specific -------------------------------------------------------------*/ /*! @@ -201,7 +227,7 @@ static int rsa_sign_write(const knot_dnssec_sign_context_t *context, size_t raw_signature_size; const knot_dnssec_key_t *key = context->key; - result = any_sign_finish(context, &raw_signature, &raw_signature_size); + result = any_sign_write(context, &raw_signature, &raw_signature_size); if (result != KNOT_EOK) { return result; } @@ -270,7 +296,7 @@ static int dsa_sign_write(const knot_dnssec_sign_context_t *context, uint8_t *raw_signature; size_t raw_signature_size; - result = any_sign_finish(context, &raw_signature, &raw_signature_size); + result = any_sign_write(context, &raw_signature, &raw_signature_size); if (result != KNOT_EOK) { return result; } @@ -380,7 +406,7 @@ static int ecdsa_sign_write(const knot_dnssec_sign_context_t *context, uint8_t *raw_signature; size_t raw_signature_size; - result = any_sign_finish(context, &raw_signature, &raw_signature_size); + result = any_sign_write(context, &raw_signature, &raw_signature_size); if (result != KNOT_EOK) { return result; } @@ -428,14 +454,16 @@ static const algorithm_functions_t rsa_functions = { rsa_create_pkey, any_sign_size, any_sign_add, - rsa_sign_write + rsa_sign_write, + any_sign_verify }; static const algorithm_functions_t dsa_functions = { dsa_create_pkey, dsa_sign_size, any_sign_add, - dsa_sign_write + dsa_sign_write, + any_sign_verify }; #ifndef OPENSSL_NO_ECDSA @@ -443,7 +471,8 @@ static const algorithm_functions_t ecdsa_functions = { ecdsa_create_pkey, ecdsa_sign_size, any_sign_add, - ecdsa_sign_write + ecdsa_sign_write, + any_sign_verify }; #endif @@ -559,7 +588,7 @@ static int create_digest_context(const knot_dnssec_key_t *key, if (!context) return KNOT_ENOMEM; - if (!EVP_SignInit_ex(context, digest_type, NULL)) { + if (!EVP_DigestInit_ex(context, digest_type, NULL)) { EVP_MD_CTX_destroy(context); return KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT; } @@ -738,19 +767,20 @@ size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key) return key->data->functions->sign_size(key); } -/*! - * \brief Get DNSSEC key used by given signing context. +/** + * \brief Clean DNSSEC signing context to start a new signature. */ -const knot_dnssec_key_t *knot_dnssec_sign_key(knot_dnssec_sign_context_t *context) +int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context) { if (!context) - return NULL; + return KNOT_EINVAL; - return context->key; + destroy_digest_context(&context->digest_context); + return create_digest_context(context->key, &context->digest_context); } /*! - * \brief Add data into DNSSEC signature. + * \brief Add data to be covered by DNSSEC signature. */ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context, const uint8_t *data, size_t data_size) @@ -762,7 +792,7 @@ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context, } /** - * \brief Finish DNSSEC signing and write out the signature. + * \brief Write down the DNSSEC signature for supplied data. */ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signature) { @@ -773,13 +803,14 @@ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signatu } /** - * \brief Clean DNSSEC signing context to start a new signature. + * \brief Verify the DNSSEC signature for supplied data. */ -int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context) +int knot_dnssec_sign_verify(knot_dnssec_sign_context_t *context, + const uint8_t *signature, size_t signature_size) { - if (!context) + if (!context || !context->key || !signature) return KNOT_EINVAL; - destroy_digest_context(&context->digest_context); - return create_digest_context(context->key, &context->digest_context); + return context->key->data->functions->sign_verify(context, signature, + signature_size); } diff --git a/src/libknot/dnssec/sign.h b/src/libknot/dnssec/sign.h index b302f85f6850ab59b7166c2e8158e1dfe16a8de0..2e4950921fa82117ec4a7e69395206ff0cd6685a 100644 --- a/src/libknot/dnssec/sign.h +++ b/src/libknot/dnssec/sign.h @@ -103,8 +103,19 @@ void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context); */ size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key); +/** + * \brief Clean DNSSEC signing context to start a new signature. + * + * Need not be called after knot_dnssec_sign_init(). + * + * \param context DNSSEC signing context. + * + * \return Error code, KNOT_EOK if successful. + */ +int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context); + /*! - * \brief Add data into DNSSEC signature. + * \brief Add data to be covered by DNSSEC signature. * * \param context DNSSEC signing context. * \param data Pointer to data to be added. @@ -116,7 +127,7 @@ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context, const uint8_t *data, size_t data_size); /** - * \brief Finish DNSSEC signing and write out the signature. + * \brief Write down the DNSSEC signature for supplied data. * * \param context DNSSEC signing context. * \param signature Pointer to signature to be written. @@ -127,15 +138,18 @@ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signature); /** - * \brief Clean DNSSEC signing context to start a new signature. - * - * Need not be called after knot_dnssec_sign_init(). + * \brief Verify the DNSSEC signature for supplied data. * - * \param context DNSSEC signing context. + * \param context DNSSEC signing context. + * \param signature Signature. + * \param signature_size Size of the signature. * - * \return Error code, KNOT_EOK if successful. + * \return Error code. + * \retval KNOT_EOK The signature is valid. + * \retval KNOT_DNSSEC_EINVALID_SIGNATURE The signature is not valid. */ -int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context); +int knot_dnssec_sign_verify(knot_dnssec_sign_context_t *context, + const uint8_t *signature, size_t signature_size); #endif // _KNOT_DNSSEC_SIGN_H_