[openssl-users] Path Length Constraint ignored for Root and any self-issued certificate

Peter Magnusson blaufish.public.email at gmail.com
Mon Oct 8 12:51:06 UTC 2018


sorry, typo on the verify line, this was what I should have written:
VERIFY(max_path_length>0) error upon preparing transition from i=2
(EvilCA) to i=2 (EvilServer).
On Mon, Oct 8, 2018 at 2:47 PM Peter Magnusson
<blaufish.public.email at gmail.com> wrote:
>
> That is not correct behaviour as far as I can understand.
>
> RFC5280 Certification Path Validation algorithm process from root to
> leaf, i.e. (Root, EvilCA, EvilServer). 6.1.2 Initialization and 6.1.4
> Preparation for Certificate i+1 is expected to occur upon Root
> certificate, i.e. the following should be expected behaviour:
> * max_path_length=n (initialisation)
> * max_path_length=n-1 (first decrement)
> * max_path_length=0 (copied from root certificate constraint)
> * VERIFY(max_path_length>0) error upon preparing transition from i=1
> (Root) to i=2 (EvilCA).
>
> OpenSSL does everything in a slightly different reverse algorithm, but
> should perform the same controls and behaivor as the RFC imho.
>
> And aside from the RFC algorithm checking for this condition, it is
> also analog with the description of the expected behaviour:
>
>    The pathLenConstraint field is meaningful only if the cA boolean is
>    asserted and the key usage extension, if present, asserts the
>    keyCertSign bit (Section 4.2.1.3).  In this case, it gives the
>    maximum number of non-self-issued intermediate certificates that may
>    follow this certificate in a valid certification path.  (Note: The
>    last certificate in the certification path is not an intermediate
>    certificate, and is not included in this limit.  Usually, the last
>    certificate is an end entity certificate, but it can be a CA
>    certificate.)  A pathLenConstraint of zero indicates that no non-
>    self-issued intermediate CA certificates may follow in a valid
>    certification path.  Where it appears, the pathLenConstraint field
>    MUST be greater than or equal to zero.  Where pathLenConstraint does
>    not appear, no limit is imposed.
>
> So my understanding is that the OpenSSL algorithm is confused and
> fails to perform a check that is applicable to self-issued
> certificates. The decrement of max_path_length (aka plen++ in OpenSSL
> implementation) should not occur for self issued certificates, but the
> validation of max_path_length>0 (aka plen>(constraint+1)) should
> occur.
> On Mon, Oct 8, 2018 at 1:27 PM J Decker <d3ck0r at gmail.com> wrote:
> >
> > It was my interpretation that 0 pathlen on the root self signed meant infinite.
> > The pathlen only applies on the certs between root and the leaf (which obviously can be 0, and CA true or not, but bad form to say true I'd imagine.)
> >
> > On Mon, Oct 8, 2018 at 1:57 AM Peter Magnusson <blaufish.public.email at gmail.com> wrote:
> >>
> >> One more logic confusion in the OpenSSL Path Length Constraint check.
> >> Any Path Length Constraint set by Root (or any other Self-Issued
> >> Certificate) is ignored.
> >> Root cause appears to be !(x->ex_flags & EXFLAG_SI)=0 incorrectly
> >> applied to the checker (i.e. the checker and the calculation logic
> >> have been mixed up).
> >>
> >> https://github.com/blaufish/openssl-pathlen/tree/master/testcase_2
> >>
> >> openssl x509 -text -in root.pem | grep -a1 "X509v3 Basic"
> >>                 Certificate Sign, CRL Sign
> >>             X509v3 Basic Constraints: critical
> >>                 CA:TRUE, pathlen:0
> >> openssl x509 -text -in evilca.pem | grep -a1 "X509v3 Basic"
> >>                 Certificate Sign, CRL Sign
> >>             X509v3 Basic Constraints: critical
> >>                 CA:TRUE, pathlen:0
> >> openssl x509 -text -in evilserver.pem | grep -a1 "X509v3 Basic"
> >>         X509v3 extensions:
> >>             X509v3 Basic Constraints: critical
> >>                 CA:FALSE
> >> ----
> >> openssl x509 -text -in root.pem | egrep -a1 "X509v3 .* Key Identifier"
> >>         X509v3 extensions:
> >>             X509v3 Subject Key Identifier:
> >>                 49:39:72:82:78:39:E8:60:AD:17:79:83:DB:65:B8:5C:E6:A7:84:B5
> >> --
> >> --
> >>                 49:39:72:82:78:39:E8:60:AD:17:79:83:DB:65:B8:5C:E6:A7:84:B5
> >>             X509v3 Authority Key Identifier:
> >>
> >> keyid:49:39:72:82:78:39:E8:60:AD:17:79:83:DB:65:B8:5C:E6:A7:84:B5
> >> openssl x509 -text -in evilca.pem | grep -a1 "X509v3 .* Key Identifier"
> >>         X509v3 extensions:
> >>             X509v3 Subject Key Identifier:
> >>                 B6:B4:75:66:18:B5:D2:4F:57:10:53:93:4F:CD:51:71:A4:27:84:7C
> >> --
> >> --
> >>                 B6:B4:75:66:18:B5:D2:4F:57:10:53:93:4F:CD:51:71:A4:27:84:7C
> >>             X509v3 Authority Key Identifier:
> >>
> >> keyid:49:39:72:82:78:39:E8:60:AD:17:79:83:DB:65:B8:5C:E6:A7:84:B5
> >> openssl x509 -text -in evilserver.pem | egrep -a1 "X509v3 .* Key Identifier"
> >>                 TLS Web Server Authentication
> >>             X509v3 Subject Key Identifier:
> >>                 03:C6:48:91:09:73:F5:DF:EF:B5:9D:A4:66:00:16:C3:E9:DB:99:EE
> >> --
> >> --
> >>                 03:C6:48:91:09:73:F5:DF:EF:B5:9D:A4:66:00:16:C3:E9:DB:99:EE
> >>             X509v3 Authority Key Identifier:
> >>
> >> keyid:B6:B4:75:66:18:B5:D2:4F:57:10:53:93:4F:CD:51:71:A4:27:84:7C
> >> ----
> >> ../openssl-1.1.1/apps/openssl verify -show_chain -verbose -CAfile
> >> root.pem -untrusted evilca.pem evilserver.pem
> >> ******* important variables *******
> >> *** check_chain_extensions:524 i=0
> >> *** check_chain_extensions:525 plen=0
> >> *** check_chain_extensions:526 x->ex_pathlen=-1
> >> ******* if statement components *******
> >> *** check_chain_extensions:528 i > 1=0
> >> *** check_chain_extensions:529 !(x->ex_flags & EXFLAG_SI)=1
> >> *** check_chain_extensions:530 (x->ex_pathlen != -1)=0
> >> *** check_chain_extensions:531 (plen > (x->ex_pathlen +
> >> proxy_path_length + 1))=0
> >> ******* important variables *******
> >> *** check_chain_extensions:524 i=1
> >> *** check_chain_extensions:525 plen=1
> >> *** check_chain_extensions:526 x->ex_pathlen=0
> >> ******* if statement components *******
> >> *** check_chain_extensions:528 i > 1=0
> >> *** check_chain_extensions:529 !(x->ex_flags & EXFLAG_SI)=1
> >> *** check_chain_extensions:530 (x->ex_pathlen != -1)=1
> >> *** check_chain_extensions:531 (plen > (x->ex_pathlen +
> >> proxy_path_length + 1))=0
> >> ******* important variables *******
> >> *** check_chain_extensions:524 i=2
> >> *** check_chain_extensions:525 plen=2
> >> *** check_chain_extensions:526 x->ex_pathlen=0
> >> ******* if statement components *******
> >> *** check_chain_extensions:528 i > 1=1
> >> *** check_chain_extensions:529 !(x->ex_flags & EXFLAG_SI)=0
> >> *** check_chain_extensions:530 (x->ex_pathlen != -1)=1
> >> *** check_chain_extensions:531 (plen > (x->ex_pathlen +
> >> proxy_path_length + 1))=1
> >> evilserver.pem: OK
> >> Chain:
> >> depth=0: C = SE, ST = EvilServer, L = EvilServer, O = EvilServer, OU =
> >> EvilServer, CN = EvilServer (untrusted)
> >> depth=1: C = SE, ST = EvilCA, L = EvilCA, O = EvilCA, OU = EvilCA, CN
> >> = EvilCA (untrusted)
> >> depth=2: C = SE, ST = Root, L = Root, O = Root, OU = Root, CN = Root
> >> --
> >> openssl-users mailing list
> >> To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
> >
> > --
> > openssl-users mailing list
> > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users


More information about the openssl-users mailing list