SSL application verify_fun and extensions.

6 views
Skip to first unread message

Stanislav Ledenev

unread,
Jul 1, 2021, 5:56:19 AMJul 1
to erlang-questions
Hi,

Can anyone explain reasons behind default implementations of verify_fun function
in the ssl application? Particularly the "extensions" part.

According to the documentation (https://erlang.org/doc/man/ssl.html#type-custom_verify)
default implementations are:

"Default option verify_fun in verify_peer mode:

{fun(_,{bad_cert, _} = Reason, _) ->
{fail, Reason};
    (_,{extension, _}, UserState) ->
{unknown, UserState};
    (_, valid, UserState) ->
{valid, UserState};
    (_, valid_peer, UserState) ->
         {valid, UserState}
 end, []}


Default option verify_fun in mode verify_none:

{fun(_,{bad_cert, _}, UserState) ->
{valid, UserState};
    (_,{extension, #'Extension'{critical = true}}, UserState) ->
{valid, UserState};
    (_,{extension, _}, UserState) ->
{unknown, UserState};
    (_, valid, UserState) ->
{valid, UserState};
    (_, valid_peer, UserState) ->
         {valid, UserState}
 end, []}
"

Why's with verify_peer mode all extensions are treated as "unknown" and
for verify_none only critical extensions are treated as valid?
I understand that according to RFC5280 any extension can be inserted into the
certificate and of course those "any" extensions are "unknown".

But RFC5280 also describes extensions which can be considered as standard,
for example: keyUsage and extKeyUsage. Why those "standard" extensions are
"unknown" too?

Why am I forced to write my own verify_fun even for "standard" extensions.

In practice my problem is this.
I have my own written CA which issues certificates.
Certificates are:
    Root CA ->
        Intermediate Root CA ->
            Web server certificate
            Client certificate.

Server-Client interaction required to have two-way authentication.

Client certificate has extKeyUsage with value id-kp-clientAuth and marked as critical.
Web server's certificate is used with cowboy web server.
Client's certificate is used with curl (for testing purposes) like this:
curl  --insecure -v
    --key-type der
    --key ./client.key
    --cert-type der
    --cert ./client.cer
    --cacert ./ca_cert.pem https://localhost:8443

And when extKeyUsage is marked as critical, the connection could not be established.
Curl's output:
--------------------------------------------------------------------------------
* connect to ::1 port 8443 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 149996 ms for 3 (transfer 0x55a42be3efb0)
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: ./ca_cert.pem
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS alert, unknown CA (560):
* error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
* Closing connection 0
curl: (35) error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
--------------------------------------------------------------------------------

Cowboy's output:
--------------------------------------------------------------------------------
1> =NOTICE REPORT==== 1-Jul-2021::12:47:25.204660 ===
TLS server: In state certify at ssl_handshake.erl:1887 generated SERVER ALERT: Fatal - Unknown CA
--------------------------------------------------------------------------------




Reply all
Reply to author
Forward
0 new messages