#endif
-int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature,
- void *asn, EVP_PKEY *pkey)
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
+ ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
{
EVP_MD_CTX ctx;
- const EVP_MD *type = NULL;
unsigned char *buf_in=NULL;
int ret= -1,inl;
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
- type=EVP_get_digestbynid(mdnid);
- if (type == NULL)
+ if (mdnid == NID_undef)
{
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
- goto err;
+ if (!pkey->ameth || !pkey->ameth->item_verify)
+ {
+ ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ goto err;
+ }
+ ret = pkey->ameth->item_verify(&ctx, it, asn, a,
+ signature, pkey);
+ /* Return value of 2 means carry on, anything else means we
+ * exit straight away: either a fatal error of the underlying
+ * verification routine handles all verification.
+ */
+ if (ret != 2)
+ goto err;
+ ret = -1;
}
-
- /* Check public key OID matches public key type */
- if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id)
+ else
{
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE);
- goto err;
- }
+ const EVP_MD *type;
+ type=EVP_get_digestbynid(mdnid);
+ if (type == NULL)
+ {
+ ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ goto err;
+ }
+
+ /* Check public key OID matches public key type */
+ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id)
+ {
+ ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+
+ if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
+ {
+ ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
+ ret=0;
+ goto err;
+ }
- if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
- {
- ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
- ret=0;
- goto err;
}
inl = ASN1_item_i2d(asn, &buf_in, it);