Discussion:
TLS server/client with self-signed certificate
(too old to reply)
Harald Latzko
2012-08-02 07:03:01 UTC
Permalink
Hell,

I've got a question regarding self-signed X509v3 certificates used in a TLS1.0 server/client environment. A communication partner uses a self-signed certificate as attached to this mail (can be retrieved from the TLS server 87.236.105.37:6619). My TLS client uses the following options:
SSL_CTX_load_verify_locations(ctx, NULL, tls_root_certpath)
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
SSL_CTX_set_verify_depth(ctx, 9);
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TICKET );

The server certificate is trusted in a directory where trusted certificates reside. In my application, a connect try ends with the following error:

certificate verify error 20: unable to get local issuer certificate: depth=0, subject: /emailAddress=***@johndeere.com/CN=jd_edi_gw.deere.com/OU=EDI/O=John Deere/L=Mannheim/ST=BW/C=DE, issuer: /emailAddress=***@johndeere.com/CN=jd_edi_gw.deere.com/OU=EDI/O=John Deere/L=Mannheim/ST=BW/C=DE

My opinion is that the self-signed certificate has the X509v3 basic constraint CA flag set to "false": (openssl x509 -in John_Deere_OFTP2_Prod_3.cer -noout -text)

X509v3 Basic Constraints: critical
CA:FALSE

A connect via "openssl s_client" also fails with this message:

openssl s_client -connect 87.236.105.37:6619 -tls1 -msg -debug -verify 9 -CApath /tmp/rootcerts/
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 501A2574C23B04543CC2CEAE6B930BB34B9A7A7A752213E32469399F77690FC8
Session-ID-ctx:
Master-Key: 72CE5564EC8B591BE7E7B9156610379E73177615F26FCDEE0B58D81AB3C301DED5B0B4AF7881489E9E4D4D654554B72C
Key-Arg : None
Start Time: 1343890805
Timeout : 7200 (sec)
Verify return code: 21 (unable to verify the first certificate)
---

Is my assumption correct that the "CA"-flag must be set to "true" in order to work as a self-signed server certificate? I don't want to change my verify_callback function just in order to get it work (which could be easy). Conformity should be the first goal.


Regards,
Harald
Dave Thompson
2012-08-03 01:55:50 UTC
Permalink
Sent: Thursday, 02 August, 2012 03:03
<snip> self-signed certificate as attached to this mail (can be retrieved
from the TLS server 87.236.105.37:6619). My TLS client uses the
SSL_CTX_load_verify_locations(ctx, NULL, tls_root_certpath)
<snip>

Aside: it's a good thing you gave the server, because Outlook
(which we use) blocks *.cer. I wish it didn't, but it does.
The server certificate is trusted in a directory where trusted
certificates
Is the server cert in the directory named by tls_root_certpath
*with a hashlink (or hashname)*? For the correct major version
of OpenSSL? (hashes for 1.0.0+ are different from 0.9.8)
certificate verify error 20: unable to get local issuer certificate: <snip>
My opinion is that the self-signed certificate has the X509v3 basic
constraint
CA flag set to "false": <snip>
A connect via "openssl s_client" also fails with <snip: verify error 21>
You show only the last part (resulting SSL-Session).
I got as the first thing (except DN trimmed for posting):
CONNECTED(00000003)
depth=0 emailAddress = ***@johndeere.com, ...
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 emailAddress = ***@johndeere.com, ...
verify error:num=21:unable to verify the first certificate
verify return:1

Note that you get error=20 first, and only after s_client overrides
(which your app presumably doesn't) then you get error=21.

Error=20 means it didn't find the cert in the truststore.
As above, check it is in the directory with the correct hash.

Errors in cert attributes (like BC) give other error codes.
Is my assumption correct that the "CA"-flag must be set to "true"
in order to work as a self-signed server certificate? I don't want
to change my verify_callback function just in order to get it work
(which could be easy). Conformity should be the first goal.
No. CA:true, and (usually) KeyUsage:certSign, are required
IF a cert (often, but not necessarily, selfsigned) is used
to issue *other* (child) certs.

______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Harald Latzko
2012-08-03 07:02:16 UTC
Permalink
Hello Dave,
Post by Dave Thompson
Aside: it's a good thing you gave the server, because Outlook
(which we use) blocks *.cer. I wish it didn't, but it does.
I've reached this "great" functionality last week, too. There's a possibility to allow filename extensions ins outlook, so you might add "cer" (or was it ".cer"?) as allowed extension by adding a registry key named "Level1Remove" (type string) to
HKEY_CURRENT_USER/Software/Microsoft/Office <your version here>/Outlook/Security (Outlook 2002)

It's a comma-seperated list of allowed attachements which will be allowed to be displayed and downloaded in Outlook.
Post by Dave Thompson
Post by Harald Latzko
The server certificate is trusted in a directory where trusted
certificates
Is the server cert in the directory named by tls_root_certpath
*with a hashlink (or hashname)*? For the correct major version
of OpenSSL? (hashes for 1.0.0+ are different from 0.9.8)
Yes, the hash link (<hash>.0) exists and after the first connect failed, I double-checked the linked openSSL version against the commandline tool version. I also added an unneeded link named the old hashing method (parameter "-subject_hash_old" for openssl commandline tool). Since I've got a bunch of working connection via various CAs, I assume this mechanism works normally.
Post by Dave Thompson
Post by Harald Latzko
certificate verify error 20: unable to get local issuer certificate: <snip>
My opinion is that the self-signed certificate has the X509v3 basic constraint
CA flag set to "false": <snip>
A connect via "openssl s_client" also fails with <snip: verify error 21>
You show only the last part (resulting SSL-Session).
CONNECTED(00000003)
verify error:num=20:unable to get local issuer certificate
verify return:1
verify error:num=21:unable to verify the first certificate
verify return:1
Note that you get error=20 first, and only after s_client overrides
(which your app presumably doesn't) then you get error=21.
You're right, my apps doesn't override error 20 (X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) because it's seen critically as a security hole if it would allow the client connect to an unknown communication partner. It this is not an usual security practice, please let me know (my app is designed to be "as-secure-as-possible").
Post by Dave Thompson
Error=20 means it didn't find the cert in the truststore.
As above, check it is in the directory with the correct hash.
See above: it's the case actually.
Post by Dave Thompson
Errors in cert attributes (like BC) give other error codes.
Are there any more errors? I can't see any. Another point to be examined could be if the self-signed certificate isn't really self-signed, but signd with a key whose certificate's subject is just equally the same value, but whose private key is a different that the one used for generating the self-signed certificate itself (say: if there's a mistake in self-signing, and something evil happened during the creation of the self-signed certificate, another instance signed the certificate which uses the same subject). Possible?
Post by Dave Thompson
Post by Harald Latzko
Is my assumption correct that the "CA"-flag must be set to "true"
in order to work as a self-signed server certificate? I don't want
to change my verify_callback function just in order to get it work
(which could be easy). Conformity should be the first goal.
No. CA:true, and (usually) KeyUsage:certSign, are required
IF a cert (often, but not necessarily, selfsigned) is used
to issue *other* (child) certs.
My assumption of a chain of trust is that the end of a trust chain is reached (=a server or client certificate is seen as valid and secure) if the whole chain of certificates ends in an entifiy where subject=issuer and CA:true (and mathematically verification of the signed certificate is true). In the past, this was a perfectly explainable environment for all issues about certificate chains and trust. How is then trust handled (if the above mentioned method for linking trust via subject hash is used) for self-signed certificate in general?

Greetings,
Harald______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Jakob Bohm
2012-08-03 07:52:48 UTC
Permalink
Post by Harald Latzko
Hello Dave,
Post by Dave Thompson
Aside: it's a good thing you gave the server, because Outlook
(which we use) blocks *.cer. I wish it didn't, but it does.
I've reached this "great" functionality last week, too. There's a
possibility to allow filename extensions ins outlook, so you might add
"cer" (or was it ".cer"?) as allowed extension by adding a registry
key named "Level1Remove" (type string) to
HKEY_CURRENT_USER/Software/Microsoft/Office <your version
here>/Outlook/Security (Outlook 2002)
It's a comma-seperated list of allowed attachements which will be
allowed to be displayed and downloaded in Outlook.
Post by Dave Thompson
Post by Harald Latzko
The server certificate is trusted in a directory where trusted
certificates
Is the server cert in the directory named by tls_root_certpath
*with a hashlink (or hashname)*? For the correct major version
of OpenSSL? (hashes for 1.0.0+ are different from 0.9.8)
Yes, the hash link (<hash>.0) exists and after the first connect
failed, I double-checked the linked openSSL version against the
commandline tool version. I also added an unneeded link named the old
hashing method (parameter "-subject_hash_old" for openssl commandline
tool). Since I've got a bunch of working connection via various CAs, I
assume this mechanism works normally.
Post by Dave Thompson
Post by Harald Latzko
certificate verify error 20: unable to get local issuer
certificate: <snip>
Post by Dave Thompson
Post by Harald Latzko
My opinion is that the self-signed certificate has the X509v3 basic
constraint
Post by Dave Thompson
Post by Harald Latzko
CA flag set to "false": <snip>
A connect via "openssl s_client" also fails with <snip: verify
error 21>
Post by Dave Thompson
You show only the last part (resulting SSL-Session).
CONNECTED(00000003)
verify error:num=20:unable to get local issuer certificate
verify return:1
verify error:num=21:unable to verify the first certificate
verify return:1
Note that you get error=20 first, and only after s_client overrides
(which your app presumably doesn't) then you get error=21.
You're right, my apps doesn't override error 20
(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) because it's seen
critically as a security hole if it would allow the client connect to
an unknown communication partner. It this is not an usual security
practice, please let me know (my app is designed to be
"as-secure-as-possible").
Post by Dave Thompson
Error=20 means it didn't find the cert in the truststore.
As above, check it is in the directory with the correct hash.
See above: it's the case actually.
Post by Dave Thompson
Errors in cert attributes (like BC) give other error codes.
Are there any more errors? I can't see any. Another point to be
examined could be if the self-signed certificate isn't really
self-signed, but signd with a key whose certificate's subject is just
equally the same value, but whose private key is a different that the
one used for generating the self-signed certificate itself (say: if
there's a mistake in self-signing, and something evil happened during
the creation of the self-signed certificate, another instance signed
the certificate which uses the same subject). Possible?
Post by Dave Thompson
Post by Harald Latzko
Is my assumption correct that the "CA"-flag must be set to "true"
in order to work as a self-signed server certificate? I don't want
to change my verify_callback function just in order to get it work
(which could be easy). Conformity should be the first goal.
No. CA:true, and (usually) KeyUsage:certSign, are required
IF a cert (often, but not necessarily, selfsigned) is used
to issue *other* (child) certs.
My assumption of a chain of trust is that the end of a trust chain is
reached (=a server or client certificate is seen as valid and secure)
if the whole chain of certificates ends in an entifiy where
subject=issuer and CA:true (and mathematically verification of the
signed certificate is true). In the past, this was a perfectly
explainable environment for all issues about certificate chains and
trust. How is then trust handled (if the above mentioned method for
linking trust via subject hash is used) for self-signed certificate in
general?
This rule is no longer entirely true.

The new rule is to stop when reaching a cert in your local trusted
or banned list, self-signed or otherwise, and to not check if the
self-signature (if any) is valid.

This is because of the following real world issues:

1. Some CAs are available both as self-signed and as cross-signed
by another CA (which you may or may not trust). Both variants of
such a CA have the same public key, algorithm, subject etc. but
have different issuer, signature, dates etc. Your trust list
may contain either variant, or only the other CA (in which case
you would see the CA as just another intermediary cert). For
example, at least one major CA has its root certs cross-signed by
the old "Equifax" root CA, to support clients with an old CA list.
As another example, signatures for Windows drivers are issued by
well-known CAs (Symantec, GlobalTrust), but are trusted via
a cross-cert issued by a dedicated Microsoft CA whose cert is
hard coded in the Windows boot loader (this is before "secure
boot" is added to the mix).

2. Some major valid CA roots were self-signed using algorithms
that are no longer secure (such as MD2), but currently issued
certificates from those roots are not. If you trust the CA
because its complete cert and public key are in your trust
list, it doesn't matter how it was self-signed.

3. Some Intermediary CAs (such as some from the Netherlands)
have been so thoroughly compromised they have been revoked
not only via CRLs, but also via hard coded untrust-lists in
various software (including OpenSSL). Thus if you hit one
of those in a certificate chain, you must stop the search
and declare the result (failure), and not continue to the
next higher cert, which is still trusted.


Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. http://www.wisemo.com
Transformervej 29, 2730 Herlev, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Harald Latzko
2012-08-03 16:25:28 UTC
Permalink
Hello Jakob,
Post by Jakob Bohm
Post by Harald Latzko
My assumption of a chain of trust is that the end of a trust chain is reached (=a server or client certificate is seen as valid and secure) if the whole chain of certificates ends in an entifiy where subject=issuer and CA:true (and mathematically verification of the signed certificate is true). In the past, this was a perfectly explainable environment for all issues about certificate chains and trust. How is then trust handled (if the above mentioned method for linking trust via subject hash is used) for self-signed certificate in general?
This rule is no longer entirely true.
The new rule is to stop when reaching a cert in your local trusted
or banned list, self-signed or otherwise, and to not check if the
self-signature (if any) is valid.
Thank you for your information update, this is a very useful information for me.
May I ask if my understanding of your words are correct: if a self-signed certificate is being found in the certificate chain (which is normally the case instantly), the validation stops as seen in the technical tests with the given error? Is there a programmable way to allow single self-signed certificates (like using the trust mechanism) without "opening" security for *all* self-signed certificates (so the administrator of the system may import one special, but decline to use others)?

Regards,
Harald______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Dave Thompson
2012-08-04 00:35:06 UTC
Permalink
Sent: Friday, 03 August, 2012 03:02
Yes, the hash link (<hash>.0) exists and after the first
connect failed, I double-checked the linked openSSL version
against the commandline tool version. <snip>
Good.

(original problem in app was)
Post by Dave Thompson
Post by Harald Latzko
certificate verify error 20: unable to get local issuer
certificate: <snip>
verify error 21>
Post by Dave Thompson
You show only the last part (resulting SSL-Session).
CONNECTED(00000003)
verify error:num=20:unable to get local issuer certificate
verify return:1
verify error:num=21:unable to verify the first certificate
verify return:1
Note that you get error=20 first, and only after s_client overrides
(which your app presumably doesn't) then you get error=21.
You're right, my apps doesn't override error 20
(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) because it's
seen critically as a security hole if it would allow the
client connect to an unknown communication partner. It this
is not an usual security practice, please let me know (my app
is designed to be "as-secure-as-possible").
Yes, to be safe your app should treat this as an error.
I was pointing out s_client first gets the *same* error (20),
and later gets a different error (21) only because it overrides,
because s_client was designed mostly as a manual test&debug tool.
I.e. the error is 20 not 21. I put the cert in a file
and did commandline verify, and that also says error 20.
So I debugged that, and it sort of isn't 20; see below.
Post by Dave Thompson
Error=20 means it didn't find the cert in the truststore.
As above, check it is in the directory with the correct hash.
See above: it's the case actually.
Post by Dave Thompson
Errors in cert attributes (like BC) give other error codes.
Are there any more errors? I can't see any. Another point to
There are lots of other errors possible from X509_verify_cert.
See X509_V_ERR_* in x509_vfy.h.
be examined could be if the self-signed certificate isn't
really self-signed, but signd with a key whose certificate's
subject is just equally the same value, but whose private key
is a different that the one used for generating the
self-signed certificate itself (say: if there's a mistake in
self-signing, and something evil happened during the creation
of the self-signed certificate, another instance signed the
certificate which uses the same subject). Possible?
If a supposedly selfsigned cert wasn't actually signed by its
own key, yes that would be bad. But this specific cert is okay:
sha1 of the TBS portion (SEQUENCE starting at 4)
is fa1e7834c1abf2d21cd453810ca0af941e861595 and
rsautl -verify of the signature starting at 776
using the pubkey in the body is
0000 - 30 21 30 09 06 05 2b 0e-03 02 1a 05 00 04 14 fa 0!0...+.........
0010 - 1e 78 34 c1 ab f2 d2 1c-d4 53 81 0c a0 af 94 1e .x4......S......
0020 - 86 15 95 ...
which matches. (It's SEQUENCE of AlgId plus OCTETSTRING hash.)
Post by Dave Thompson
Post by Harald Latzko
Is my assumption correct that the "CA"-flag must be set to "true"
in order to work as a self-signed server certificate? I don't want
to change my verify_callback function just in order to get it work
(which could be easy). Conformity should be the first goal.
No. CA:true, and (usually) KeyUsage:certSign, are required
IF a cert (often, but not necessarily, selfsigned) is used
to issue *other* (child) certs.
I was only half-right. OpenSSL X509_check_issued is called to
check *both* self-issued and parent-issued, and (always) requires
that KeyUsage contain certSign or be absent. But this cert
has KeyUsage without certSign. _check_issued actually returns
a specific error code 32 _NO_CERTSIGN, but that gets swallowed
by the chain-build logic and returns as 20 UNABLE*GET*LOCAL
My assumption of a chain of trust is that the end of a trust
chain is reached (=a server or client certificate is seen as
valid and secure) if the whole chain of certificates ends in
an entifiy where subject=issuer and CA:true (and
mathematically verification of the signed certificate is
true). In the past, this was a perfectly explainable
environment for all issues about certificate chains and
trust. How is then trust handled (if the above mentioned
method for linking trust via subject hash is used) for
self-signed certificate in general?
As Jacob says, many now agree that the chain can stop at any
"anchor" which is manually approved, whether that is a root
(selfsigned) or not, but OpenSSL (at least through 1.0.0i)
still implements going to a root.

The trust linking is done by matching child.issuer to parent.subject,
and if present also child.AKI to parent.SKI or parent.(issuer&serial).
The subject-hash links (or names) are only used in CApath mode
to find the file(s) that should contain the parent cert.

For a self-signed entity cert, that cert is its own chain.
It is either in the truststore or not, but it can't link
trust to a parent because it has no parent.


______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-***@openssl.org
Automated List Manager ***@openssl.org
Loading...