Understanding “verify return:1” in OpenSSL Certificate Chain Verification – Debugging SSL/TLS Connections


1 views

When working with OpenSSL's s_client command for SSL/TLS debugging, the verification output contains important information about the certificate chain validation process. The verify return:1 messages appear during the intermediate certificate validation steps before reaching the final verification result.

The output shows the complete certificate chain with verification status at each level:

depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2 verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com verify return:1

Each verify return:1 indicates successful verification of that specific certificate in the chain. The numeric value represents:

  • 1: The certificate was successfully verified at this step
  • 0: Final successful verification of the entire chain (shown at the end)
  • Negative values: Indicate various verification failures

Here's how to examine the verification process more thoroughly:

openssl s_client -connect example.com:443 -showcerts -CAfile cacert.pem -verify_return_error < /dev/null

Key flags to note:

  • -showcerts: Displays all certificates in the chain
  • -verify_return_error: Makes OpenSSL return error if verification fails
  • -CAfile: Specifies your trusted root certificates

When troubleshooting, you might see different return codes:

# Common error codes:
# 2 - unable to get issuer certificate
# 3 - unable to get certificate CRL
# 4 - unable to decrypt certificate's signature
# 5 - unable to decrypt CRL's signature
# 7 - certificate signature failure
# 8 - CRL signature failure

For more detailed verification output:

openssl verify -CAfile cacert.pem -verbose -show_chain cert.pem

This provides a complete chain analysis including:

  • Certificate expiration status
  • Signature algorithm verification
  • Key usage validation
  • Basic constraints checking

When examining OpenSSL's certificate verification output, you'll encounter lines like verify return:1 during the chain validation process. These messages represent successful intermediate validations, not the final verification result.

The verification process works as follows:

openssl s_client -connect example.com:443 -CAfile cacert.pem < /dev/null

Each verify return:1 indicates successful validation of that particular certificate in the chain against the trust store. The numbering represents depth levels:

  • depth=3: Root CA
  • depth=2: Intermediate CA
  • depth=1: Subordinate CA
  • depth=0: End-entity certificate

Let's examine a real-world verification scenario:

$ openssl s_client -connect github.com:443 -CAfile /etc/ssl/certs/ca-certificates.crt
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
verify return:1
depth=0 C = US, ST = California, L = San Francisco, O = "GitHub, Inc.", CN = github.com
verify return:1
---
Verify return code: 0 (ok)

The numeric values in the verification process have specific meanings:

Return Code Meaning
0 Verification successful (final result)
1 Intermediate validation successful
2 Verification failed

For deeper inspection, add the -showcerts flag:

openssl s_client -showcerts -connect example.com:443 -CAfile truststore.pem

This displays all certificates in the chain, helping identify where validation might fail.

When scripting with OpenSSL, you might want to capture verification results:

#!/bin/bash
result=$(openssl s_client -connect $1:443 -CAfile $2 < /dev/null 2>&1 | \
         grep -A1 'Verify return code:' | tail -1)

if [[ $result == *"0 (ok)"* ]]; then
    echo "Certificate verified successfully"
else
    echo "Verification failed: $result"
fi

For more control over verification:

openssl s_client -connect example.com:443 \
    -CAfile root.pem \
    -partial_chain \
    -verify_return_error \
    -verify 3

The -verify 3 sets the maximum depth for chain verification.