/* * Returns only 0 or 1. If 1 it means that the CRL * was successfuly verified. * * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. * * Output will hold information about the verification * procedure. */ static int _gnutls_verify_crl2 (gnutls_x509_crl_t crl, const gnutls_x509_crt_t * trusted_cas, int tcas_size, unsigned int flags, unsigned int *output) { /* CRL is ignored for now */ gnutls_datum_t crl_signed_data = { NULL, 0 }; gnutls_datum_t crl_signature = { NULL, 0 }; gnutls_x509_crt_t issuer; int result, hash_algo; if (output) *output = 0; if (tcas_size >= 1) issuer = find_crl_issuer (crl, trusted_cas, tcas_size); else { gnutls_assert (); if (output) *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; return 0; } /* issuer is not in trusted certificate * authorities. */ if (issuer == NULL) { gnutls_assert (); if (output) *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; return 0; } if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) { if (gnutls_x509_crt_get_ca_status (issuer, NULL) != 1) { gnutls_assert (); if (output) *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; return 0; } } result = _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signature (crl->crl, "signature", &crl_signature); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_get_signature_algorithm(crl->crl, "signatureAlgorithm.algorithm"); if (result < 0) { gnutls_assert (); goto cleanup; } hash_algo = gnutls_sign_get_hash_algorithm(result); result = _gnutls_x509_verify_data (hash_algo, &crl_signed_data, &crl_signature, issuer); if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) { gnutls_assert (); /* error. ignore it */ if (output) *output |= GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNATURE_FAILURE; result = 0; } else if (result < 0) { gnutls_assert (); goto cleanup; } { int sigalg; sigalg = gnutls_x509_crl_get_signature_algorithm (crl); if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || ((sigalg == GNUTLS_SIGN_RSA_MD5) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) { if (output) *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; result = 0; } } cleanup: _gnutls_free_datum (&crl_signed_data); _gnutls_free_datum (&crl_signature); return result; }
/** * gnutls_x509_crl_verify: * @crl: is the crl to be verified * @trusted_cas: is a certificate list that is considered to be trusted one * @tcas_size: holds the number of CA certificates in CA_list * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. * @verify: will hold the crl verification output. * * This function will try to verify the given crl and return its verification status. * See gnutls_x509_crt_list_verify() for a detailed description of * return values. Note that since GnuTLS 3.1.4 this function includes * the time checks. * * Note that value in @verify is set only when the return value of this * function is success (i.e, failure to trust a CRL a certificate does not imply * a negative return value). * * Before GnuTLS 3.5.7 this function would return zero or a positive * number on success. * * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a * negative error value. **/ int gnutls_x509_crl_verify(gnutls_x509_crl_t crl, const gnutls_x509_crt_t * trusted_cas, unsigned tcas_size, unsigned int flags, unsigned int *verify) { /* CRL is ignored for now */ gnutls_datum_t crl_signed_data = { NULL, 0 }; gnutls_datum_t crl_signature = { NULL, 0 }; gnutls_x509_crt_t issuer = NULL; int result, hash_algo; time_t now = gnutls_time(0); unsigned int usage; if (verify) *verify = 0; if (tcas_size >= 1) issuer = find_crl_issuer(crl, trusted_cas, tcas_size); result = _gnutls_x509_get_signed_data(crl->crl, &crl->der, "tbsCertList", &crl_signed_data); if (result < 0) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_INVALID; goto cleanup; } result = _gnutls_x509_get_signature(crl->crl, "signature", &crl_signature); if (result < 0) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_INVALID; goto cleanup; } result = _gnutls_x509_get_signature_algorithm(crl->crl, "signatureAlgorithm.algorithm"); if (result < 0) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_INVALID; goto cleanup; } hash_algo = gnutls_sign_get_hash_algorithm(result); /* issuer is not in trusted certificate * authorities. */ if (issuer == NULL) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; } else { if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) { if (gnutls_x509_crt_get_ca_status(issuer, NULL) != 1) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; } result = gnutls_x509_crt_get_key_usage(issuer, &usage, NULL); if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { if (result < 0) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_INVALID; } else if (!(usage & GNUTLS_KEY_CRL_SIGN)) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE | GNUTLS_CERT_INVALID; } } } result = _gnutls_x509_verify_data(mac_to_entry(hash_algo), &crl_signed_data, &crl_signature, issuer); if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) { gnutls_assert(); /* error. ignore it */ if (verify) *verify |= GNUTLS_CERT_SIGNATURE_FAILURE; result = 0; } else if (result < 0) { gnutls_assert(); if (verify) *verify |= GNUTLS_CERT_INVALID; goto cleanup; } else if (result >= 0) { result = 0; /* everything ok */ } } { int sigalg; sigalg = gnutls_x509_crl_get_signature_algorithm(crl); if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || ((sigalg == GNUTLS_SIGN_RSA_MD5) && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) { if (verify) *verify |= GNUTLS_CERT_INSECURE_ALGORITHM; result = 0; } } if (gnutls_x509_crl_get_this_update(crl) > now && verify) *verify |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE; if (gnutls_x509_crl_get_next_update(crl) < now && verify) *verify |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED; cleanup: if (verify && *verify != 0) *verify |= GNUTLS_CERT_INVALID; _gnutls_free_datum(&crl_signed_data); _gnutls_free_datum(&crl_signature); return result; }