Re: Question about migrating from d2i_ECPrivateKey() to d2i_PrivateKey(EVP_PKEY_EC, ...)

2022-11-24 Thread Viktor Dukhovni
On Tue, Nov 22, 2022 at 11:09:07AM -0600, Nico Williams wrote:

> > Not exactly, PKCS#8-based typing is used in d2i_PKCS8_PRIV_KEY_INFO()
> > (for unencrypted PKCS#8 blobs, so no password callback).  The
> > d2i_PrivateKey() function takes an explicit pkey_type instead.
> 
> Hmmm, well, d2i_PrivateKey() takes an explicit pkey_type, yes, but it's
> not sufficiently informative for ECDH, being just EVP_PKEY_EC.  Or are
> there more informative type values I've not discovered yet?  When I call
> d2i_PrivateKey(EVP_PKEY_EC, ...) it wants a PKCS#8 encoded private key.

Actually, it supports *both* the PKCS#8 and the legacy type-specific formats.

The algorithm-specific PEM key formats may not be defined for some newer
key types and are deprecated, so sure, you're supposed to use PKCS#8
whenever possible.

For EC private keys, the underlying legacy DER codecs are:

d2i_ECPrivateKey()
i2d_ECPrivateKey()

with signatures:

EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len);
int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out);

for d2i_ECPrivateKey(), you get back an EC_KEY() which you can convert
to an EVP_PKEY via the deprecated (copy vs. take ownership):

EVP_PKEY_set1_EC_KEY(3), or EVP_PKEY_assign_EC_KEY(3)

which direct you to EVP_PKEY_fromdata(3) (much scaffolding...).

However, d2i_PrivateKey(EVP_PKEY_EC, ...) given non-PKCS#8 input
internally tries:

static int old_ec_priv_decode(EVP_PKEY *pkey,
  const unsigned char **pder, int derlen)
{
EC_KEY *ec;

if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL)
return 0;
EVP_PKEY_assign_EC_KEY(pkey, ec);
return 1;
}

which does the expected thing without much fuss.  That said, you
mentioned ECDH in passing, so I'm not sure we're taking about the same
things...

-- 
Viktor.


Re: How to read encrypted PKCS#8 format key file

2022-11-23 Thread Viktor Dukhovni
On Thu, Nov 24, 2022 at 09:48:42AM +0530, Satyam Mehrotra wrote:

> I have encrypted pkcs#8 key file . Is there any openssl command buy which I
> can view the algorithm used to encrypt it ( i mean aes or des3 )

Removing blank lines and passing to "asn1parse" you get:

$ openssl asn1parse -in /tmp/foo.pem | less
0:d=0  hl=4 l=1302 cons: SEQUENCE  
4:d=1  hl=2 l=  72 cons: SEQUENCE  
6:d=2  hl=2 l=   9 prim: OBJECT:PBES2
   17:d=2  hl=2 l=  59 cons: SEQUENCE  
   19:d=3  hl=2 l=  35 cons: SEQUENCE  
   21:d=4  hl=2 l=   9 prim: OBJECT:PBKDF2
   32:d=4  hl=2 l=  22 cons: SEQUENCE  
   34:d=5  hl=2 l=  16 prim: OCTET STRING  [HEX 
DUMP]:54BE686300BD75A2A58678D3AA746803
   52:d=5  hl=2 l=   2 prim: INTEGER   :0800
   56:d=3  hl=2 l=  20 cons: SEQUENCE  
   58:d=4  hl=2 l=   8 prim: OBJECT:des-ede3-cbc
   68:d=4  hl=2 l=   8 prim: OCTET STRING  [HEX DUMP]:39557361E14C06F5
   78:d=1  hl=4 l=1224 prim: OCTET STRING  [HEX 
DUMP]:0DFC7C23573AC5C76C368927B27178E5F877E15359E01CABE280FEAF572535985A8C7981075B995A94633193CF425432CAF9B6AE5BE978443B010CD453CF19C434DB6CD11B65ACC06F6C573EFC7FE3F667EAA4EFEC7088E953CD01AC6ADD38214275852765FF0309FB777E99EBE3A12FADC5E7DCF2A7A68F47DD018C39B1430B34C4A4329EA94E21D23B3D8B34F6F828F1340321685EC6F4E2F878A7B95EE710E8CD570109DDE90EC8D553C5A93E36E5F374E6670828DAA4F096183B77063E6F865F83E353861D864702AA18984A413B345D39464C055B8C7EB2D339AE04FEE4932F629E9736A3FA2D770528C07DCAE9950AD9CDE2EC838DABFE4BF40C745B447CF5D461B5B7EBD3BD1C050F129FC989684589CE6D780C126395C5749536A8E82902332EA9DB7174768780378D644029986FF2463184CD33B8DD1D4692ADF6CE0A9902A3459353102572A0AF981F96C66B6C2D8EF31BDAD438AB9E1D6CF897985713E6F5B5E2178A6F65AE582DEA2778E9041C2BC3C9B33EEDBFB19C439F5754FBACB61521711D7992CE2CCD5DC7A0AA543D3A93401031EFD39ABD435385C287A1F503686707A02E3AA2D5183CF9F2DA6436C7B51B46BFE31999592D35B099DE7FE68914610D09854E3B02A0773EB2367B7FA04205FC4500FED6AD0FF84E8A0EB183AFC84D2ABB1C43E8097C169097F3E2D744E3D31339AD024CD613733CC185F49C44B538ECA4BC63E7FA95E5F9A50E2DBD05DFC09724C6F729B5ACF41B5889C0C74B6979AEBEA3B5C73CA68AF8983DF69BEAC9BB8C1267E048B1AFE1D61757FA5D9543CE7FC4BA22D5A498FD9A1FB2A3430A56214F43D27A41B68C784F875AC29047608FEF4E3CFA69629C14558BABBA26063404D598AE927D34C642517AB9B458D51095EBFCFF67901ADF7151C6BCC336F447B437997E9C1C4DB3EF79D6A1CB7F673D32FED0010B6B6BE532F1E96F0DE04F20618615958628CB444CF952992FB5A3BF440501A768E9C91272B560E3F526306EE8FA61A46A7F1FB04B2B9D3954255AD4FF80C96950D20181657ED45F79C33186362686E969FE474B51E53F97F9FAA9F2FD40DDCE65C8406BE873418ED1EA6872C14420BE4A050F5715901AB5F8F21D256017B2C459F9289E00B8437C80A9DEBF857F87CDD18B29B131707984067D41B7C6B09B19CE942B9625CE69DD2F6F40F175568DBE69AD0DCD6971E87E9342DCAB8E7484C875FC2888D4EC13AB4748115DC9ECCE34B6D3C228C519FBD2BECB921946616A3F37E91F9DA275E0087D3C1AE74EF69E7EA57B94CE6A103122007D89E2C10277C0D56AD2BD18BC93B0D68DD43A4B9DF80368DD87AF55463A044CA2E603617BEA25DD37A15F8EB565FFA46160ABFAE2A47D5B9DE2AC6C8A79501389BEF33605EA95FA78521FB6561632006E45DCC4A6A9E68914CC63B3B27E1C29959A4224BE4DFB3CBEAD00C4DA6B004B5A30148543D4E83FF6AA0782A08DE95E42DEEA3B91EF45B9B14C9D28CD77DE8508CCDE4B10F2C36272C4D3CE348D4C268EE44C275F26556C66EB99BA2565D07F604BA6320FC5186847541162A0BAAA3250ECADC21DDED850B221517379BAA0241E537971325A96434C818A7FA2C3746E5DBC71074365BC6805F94A8ECAB84F6C4A9A9A1D9795667D3D342A37DECB8936ADFEC1232DA06A764DFF8166C040E62E7C0F09DCA4055200CEAC771D1139EA464CD51A947E360A

This is a PKCS#8 key using PKCS#5 PBES2 encryption, via PBKDF2 with salt
0x54BE686300BD75A2A58678D3AA746803 and 2048 iterations and an implicit
HMAC-SHA-1 PRF, encrypted with 3DES in CBC mode with 0x39557361E14C06F5
as the IV.

https://www.rfc-editor.org/rfc/rfc8018#section-6.2.1

   PBKDF2-params ::= SEQUENCE {
   salt CHOICE {
 specified OCTET STRING,
 otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
   },
   iterationCount INTEGER (1..MAX),
   keyLength INTEGER (1..MAX) OPTIONAL,
   prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
   }

   SupportingAlgorithms ALGORITHM-IDENTIFIER ::= {
  {NULL IDENTIFIED BY id-hmacWithSHA1}   |
  {OCTET STRING (SIZE(8)) IDENTIFIED BY desCBC}  |
  {OCTET STRING (SIZE(8)) IDENTIFIED BY des-EDE3-CBC}|
  {RC2-CBC-Parameter IDENTIFIED BY rc2CBC}   |
  {RC5-CBC-Parameters IDENTIFIED BY rc5-CBC-PAD},|
  {OCTET STRING (SIZE(16)) IDENTIFIED BY aes128-CBC-PAD} |
  {OCTET STRING (SIZE(16)) IDENTIFIED BY aes192-CBC-PAD} |
  {OCTET STRING (SIZE(16)) IDENTIFIED BY aes256-CBC-PAD},
   ...
   }

-- 
Viktor.


Re: Question about migrating from d2i_ECPrivateKey() to d2i_PrivateKey(EVP_PKEY_EC, ...)

2022-11-22 Thread Viktor Dukhovni
On Tue, Nov 22, 2022 at 11:09:07AM -0600, Nico Williams wrote:

> > Not exactly, PKCS#8-based typing is used in d2i_PKCS8_PRIV_KEY_INFO()
> > (for unencrypted PKCS#8 blobs, so no password callback).  The
> > d2i_PrivateKey() function takes an explicit pkey_type instead.
> 
> Hmmm, well, d2i_PrivateKey() takes an explicit pkey_type, yes, but it's
> not sufficiently informative for ECDH, being just EVP_PKEY_EC.  Or are
> there more informative type values I've not discovered yet?  When I call
> d2i_PrivateKey(EVP_PKEY_EC, ...) it wants a PKCS#8 encoded private key.

Do you mean ECDH or ECDSA?  These are not exactly the same use case.
What are you actually doing?  Are you really doing static ECDH key
agreement?

-- 
VFiktor.


ASN1 function declarations

2022-11-22 Thread Viktor Dukhovni
On Tue, Nov 22, 2022 at 11:09:07AM -0600, Nico Williams wrote:

> Also, the prototype for i2d_PUBKEY() does not appear in any header,
> public or private, but i2d_PUBKEY() _is_ documented -- is this a bug?

The d2i_* and i2d_* functions are mostly generated by macros that
declare all or some of the functions for a given ASN1 type:

openssl/x509.h:DECLARE_ASN1_ENCODE_FUNCTIONS_only(EVP_PKEY, PUBKEY)
openssl/x509.h:DECLARE_ASN1_FUNCTIONS(X509)

This can admittedly be a bit annoying when searching the right header is
more convenient that finding the right manpage, but search engines are
pretty good these days, and the openssl.org website has a doc index:

https://www.openssl.org/docs/manpages.html
https://www.openssl.org/docs/man3.0/man3/
...

-- 
Viktor.


Re: Question about migrating from d2i_ECPrivateKey() to d2i_PrivateKey(EVP_PKEY_EC, ...)

2022-11-20 Thread Viktor Dukhovni
On Sun, Nov 20, 2022 at 02:12:34PM -0600, Nico Williams wrote:

> > Generally, I would expect d2i_... to automatically detect the algorithm
> > when tagged with a suitable OIDs, and so d2i_AutoPrivateKey() could
> > often work, but if you know the expected key type, you can ask for
> > that explicitly with d2i_PrivateKey().
> 
> So, d2i_PrivateKey() wants a PKCS#8 wrapper so it can figure out what
> the type of the private key blob is.

Not exactly, PKCS#8-based typing is used in d2i_PKCS8_PRIV_KEY_INFO()
(for unencrypted PKCS#8 blobs, so no password callback).  The
d2i_PrivateKey() function takes an explicit pkey_type instead.

> On the other hand, d2i_PublicKey() wants the input key to indicate the
> type of public key to import.  A strange asymmetry, but it works.
> Staring at Postfix and OpenSSL code helped.

For X.509 SPKI public keys (the ones you generally want to use) the right
interface is d2i_PUBKEY, not d2i_PublicKey().

-- 
Viktor.


Re: Question about migrating from d2i_ECPrivateKey() to d2i_PrivateKey(EVP_PKEY_EC, ...)

2022-11-18 Thread Viktor Dukhovni
On Fri, Nov 18, 2022 at 11:33:08PM -0600, Nico Williams wrote:
> On Fri, Nov 18, 2022 at 04:53:44PM -0600, Nico Williams wrote:
> > I can't use d2i_PrivateKey() because that requires an existing
> > EVP_PKEY * that has the group already set.
> 
> Although, that's just what's documented.  From code inspection, if the
> parameters are found in the encoded private key, then the group will be
> set internally and no error will be returned.

Often, if you want a clear example of OpenSSL API usage, one place to
look is the Postfix "tls" library.  In this case:


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L245-L266

https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L363-L370

Postfix does not do much with low-level crypto, but it exercises a
non-trivial chunk of the certificate and TLS API surface, ECDH/DH
setup and digests.

Generally, I would expect d2i_... to automatically detect the algorithm
when tagged with a suitable OIDs, and so d2i_AutoPrivateKey() could
often work, but if you know the expected key type, you can ask for
that explicitly with d2i_PrivateKey().

You don't need to pass an existing key.  Just pass NULL for
(EVP_PKEY **) pointer, and let OpenSSL return a freshly allocated
key:

EVP_PKEY *key;

key = d2i_PrivateKey(type, NULL, ...);
key = d2i_AutoPrivateKey(NULL, ...);

I strive to also check that the buffer pointer advanced by the expected
length (no "left-over" data):


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L293-L306

-- 
Viktor.


Re: Regarding TLS call failure on Openssl3.0 with cipher : ECDH-ECDSA-AES256-SHA384

2022-11-17 Thread Viktor Dukhovni
On Fri, Nov 18, 2022 at 05:12:09AM +, Raman, Ina wrote:

> I was trying to test TLS call with cipher suite :
> tls_ecdh_ecdsa_with_aes_256_cbc_sha384 but it fails.

You probably actually wanted "ecdhe" not "ecdh", but see below.

> It fails on SSL_set_cipher_list API.

This API, and the cipher you had in mind apply only to TLS 1.2, with TLS
1.3 there is a separate API for setting the data encryption ciphers,
which are configured separately from signature schemes, and key
exchange "groups", but see below.

> The list contains the mentioned cipher but still it is failing to set
> that.

Actually the list does not contain that cipher:

- The available TLS 1.2 ciphers are ECDHE not ECDH.

$ openssl ciphers -stdname -s -tls1_2 | awk '{print $1}' | grep ECDH
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CCM
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CCM
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

- The standard names are "output only" when configuring ciphers you
  need to use the OpenSSL names.

$ openssl ciphers -stdname -s -tls1_2 -v ECDHE-ECDSA-AES256-GCM-SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - ECDHE-ECDSA-AES256-GCM-SHA384 
TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD

$ openssl ciphers -stdname -s -tls1_2 -v 
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Error in cipher list
C0F16339DF7F:error:0AB9:SSL routines:SSL_CTX_set_cipher_list:no 
cipher match:ssl/ssl_lib.c:2746:

- Cipher names are case-sensitive.

$ openssl ciphers -stdname -s -tls1_2 -v $(echo 
ECDHE-ECDSA-AES256-GCM-SHA384 | tr A-Z a-z)
Error in cipher list
C0F1755DCB7F:error:0AB9:SSL routines:SSL_CTX_set_cipher_list:no 
cipher match:ssl/ssl_lib.c:2746:

- TLS 1.3 uses none of the above:

$ openssl ciphers -s -v -tls1_3
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any  Au=any   Enc=AESGCM(256) 
   Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256   TLSv1.3 Kx=any  Au=any   
Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any  Au=any   Enc=AESGCM(128) 
   Mac=AEAD
TLS_AES_128_CCM_SHA256 TLSv1.3 Kx=any  Au=any   Enc=AESCCM(128) 
   Mac=AEAD

> I wanted to know if this cipher is supported with openssl 3.0 or not .

Multiple mistakes:

* Wrong API for TLS 1.3
* Desired cipher not applicable to TLS 1.3 anyway
* Typo "ecdh" instead of "ecdhe"
* Cipher name was lower case
* Cipher name was the RFC name, not the OpenSSL name.

Any one mistake it sufficient, but 5 is impressive. :-)

-- 
Viktor.


Re: Worried about the vulnerabilities recently found in OpenSSL versions 3.0.0 - 3.0.6.

2022-11-02 Thread Viktor Dukhovni
On Wed, Nov 02, 2022 at 11:17:31PM +, Steven_M.irc via openssl-users wrote:

> I'm really worried about the vulnerabilities recently found in OpenSSL
> versions 3.0.0 - 3.0.6.

Just upgrade any affected systems and you'll be fine.

> If I understand things correctly (and please do correct me if I'm
> wrong), it doesn't matter which version of OpenSSL clients are
> running, only which version of OpenSSL *servers* are running.

Your information source is either wrong or misleading.  The only
software version that matters is the one your system is running,
whether client or server.

-- 
Viktor.


Re: issues with OpenSSL 1.1.1n

2022-11-01 Thread Viktor Dukhovni
On Tue, Nov 01, 2022 at 06:08:10PM -0500, Ray Crumrine wrote:

> Oh my gosh! Thank you. I am a newbie when it comes to certificates. I
> am only using tls for outbound calls. I thought I shouldn't need a
> certificate when doing outbound only [a client] but was getting some
> weird error. After I read your email I simply commented out both
> "certificate" lines in my configuration and it works!!!

You don't need (and generally should not configure) client certificates
for connections to random servers that are not specifically expected to
authenticate your client certificates.

> One last question. I don't need certbot at all then, right?

If you're not running any TLS-enabled servers, and no server expects
hostname-based TLS client certificates from your client, then indeed you
do not need certbot.  It vends TLS server/client certificates for domain
names based on trust-on-first-use verified DNS domain control.

-- 
Viktor.


Re: issue with 1.1.1n

2022-11-01 Thread Viktor Dukhovni
On Tue, Nov 01, 2022 at 05:55:08AM -0500, Ray Crumrine wrote:

> SSL SSL_ERROR_SSL (Handshake): Level: 0 err: <336151573>  routines-ssl3_read_bytes-sslv3 alert certificate expired>

Is this logged by the TLS client or server?  In other words are you
running a client application making outgoing connections or a server
application receiving incoming connections?

> but not all of the time. Only when I try to access
> us-east-va.sip.flowroute using tlsv1.2.

This sounds like "client".  TLS alerts are sent by the other end of the
connection, so if you're getting "certificate expired" alerts from a
server, that means that your client is *sending* an expired certificate
to the server (which must have solicited, possibly optional, client
certificates).  The server in question does send certificate requests:

Transport Layer Security
TLSv1.2 Record Layer: Handshake Protocol: Certificate Request (fragment)
Content Type: Handshake (22)
Version: TLS 1.2 (0x0303)
Length: 16384
Handshake Protocol: Certificate Request (fragment)
...

> I have tried two other sites using the same configuration and they work 
> fine. Is there a simple configuration change or do I need Openssl v3.0?

The other sites presumably don't solicit client certificates.  The
simplest choice is to not configure a client certificate unless you're
sure you're going to need one.

> Checking with 
> https://decoder.link/sslchecker/us-east-va.sip.flowroute.com/5061 
> everything checks fine???

The probe does not send expired client certs.

-- 
Viktor.


Re: OpenSSL 1.1.1 Windows dependencies

2022-10-26 Thread Viktor Dukhovni
On Wed, Oct 26, 2022 at 11:50:16AM -0400, Viktor Dukhovni wrote:
> On Wed, Oct 26, 2022 at 11:15:25AM +0100, Matt Caswell wrote:
> 
> > > I'm not promising anything. But if you send me the captures I can take a 
> > > look at them.
> > 
> > I've taken a look at the captures for the working and non-working scenarios.
> > 
> > Do I understand correctly that your application is acting as the server 
> > in this setup?
> > 
> > I have compared the working and non-working captures. In both cases the 
> > ClientHello is successfully received, and the server responds with a 
> > ServerHello, Certificate, ServerKeyExchange and ServerHelloDone message. 
> > Aside from normal variations between one session and another, AFAICT, 
> > the ClientHello and the server's response messages all look identical 
> > other than the server obviously has a different Certificate. The 
> > Certificates themselves also look identical to each other other than the 
> > subject/subjectaltname being for a different server. The intermediate 
> > certs are the same in both cases.
> >
> > Following the server's ServerHelloDone the client continues with a 
> > ClientKeyExchange message in the working case. In the non-working case 
> > the the client immediately closes the TCP connection without sending any 
> > kind of alert.
> 
> See longish thread at:
> 
> https://marc.info/?l=postfix-users=166584042429636=2
> 
> which describes a remarkably similar set of symptoms observed after a
> Microsoft patch update.  Today the OP posted that a more follow-on patch
> appears to have resolved the problem.

TL;DR: progress on identifying the issue begins with:

https://marc.info/?l=postfix-users=166585652703462=2

-- 
Viktor.


Re: OpenSSL 1.1.1 Windows dependencies

2022-10-26 Thread Viktor Dukhovni
On Wed, Oct 26, 2022 at 11:15:25AM +0100, Matt Caswell wrote:

> > I'm not promising anything. But if you send me the captures I can take a 
> > look at them.
> 
> I've taken a look at the captures for the working and non-working scenarios.
> 
> Do I understand correctly that your application is acting as the server 
> in this setup?
> 
> I have compared the working and non-working captures. In both cases the 
> ClientHello is successfully received, and the server responds with a 
> ServerHello, Certificate, ServerKeyExchange and ServerHelloDone message. 
> Aside from normal variations between one session and another, AFAICT, 
> the ClientHello and the server's response messages all look identical 
> other than the server obviously has a different Certificate. The 
> Certificates themselves also look identical to each other other than the 
> subject/subjectaltname being for a different server. The intermediate 
> certs are the same in both cases.
>
> Following the server's ServerHelloDone the client continues with a 
> ClientKeyExchange message in the working case. In the non-working case 
> the the client immediately closes the TCP connection without sending any 
> kind of alert.

See longish thread at:

https://marc.info/?l=postfix-users=166584042429636=2

which describes a remarkably similar set of symptoms observed after a
Microsoft patch update.  Today the OP posted that a more follow-on patch
appears to have resolved the problem.


> This really looks like a problem on the client side to me.

Yes, the client just hangs up.  A known.  Disabling session tickets on
server appears to help in some cases (for no obvious reason).  Applying
the follow-on update is a better solution if applicable.

-- 
Viktor.


Re: Question about thread safety and SSL_CTX* and its SSL*

2022-09-27 Thread Viktor Dukhovni
On Tue, Sep 27, 2022 at 06:35:47PM +0200, Thomas Bailleux wrote:

> However, I am still facing issues when I use `SSL_CTX` and `SSL` objects.
> 
> I use `SSL_CTX` and `SSL` inside a threaded application. Threads are managed 
> using pthread primitives.
> 
> Basically, I create a `SSL_CTX`, and I fill it depending on the TLS method.
> At this point, the `SSL_CTX` is final. I never change it again.
> 
> Then, I create n `SSL`s from the `SSL_CTX`, and I spawn n pthreads.
> Each pthread takes the ownership of a single `SSL`. Finally, each
> pthread is going to use its `SSL` object for establishing some TLS
> connections.  `SSL` objects never get destroyed, instead I use
> `SSL_clear` for kind of recycling them.

Perhaps you're freeing some objects that are owned by the library, or
continuting to use objects that the library owned and freed.

> My question is: Is my app thread safe ? I wonder, because I am facing
> random null deref.  If I create a `SSL_CTX` for each thread,
> everything is fine.

What you're doing should work, if implemented correctly, but my advice
is to not use SSL_clear(), rather create a fresh (SSL *) handle for
each connection.  These are cheap enough to not warrant recycling.

-- 
Viktor.


Re: Query minimum RSA key size?

2022-09-26 Thread Viktor Dukhovni
On Mon, Sep 26, 2022 at 10:46:40AM -0400, Felipe Gasper wrote:

> > The security levels are documented.  You can set the security level
> > in the cipher string:
> > 
> >DEFAULT:@SECLEVEL=1
> > 
> > or via the API.
> 
> Ahh, OK. Indeed, when I set that as the cipher string the error goes away. 
> Thank you!

You can, if you wish, change the default security level in openssl.cnf.
IIRC the default from the upstream OpenSSL software is 1.  If your
system default is 2 or higher, that was done by your OS package
maintainers.

> I see that the API exposes SSL_CTX_get_security_level(); is that the
> best way to determine minimum RSA key size, or would there be anything
> more explicit?

The documentation for that function reads in part:

Level 0
Everything is permitted. This retains compatibility with
previous versions of OpenSSL.

Level 1
The security level corresponds to a minimum of 80 bits of
security. Any parameters offering below 80 bits of security are
excluded. As a result RSA, DSA and DH keys shorter than 1024
bits and ECC keys shorter than 160 bits are prohibited. Any
cipher suite using MD5 for the MAC is also prohibited.  Any
cipher suites using CCM with a 64 bit authentication tag are
prohibited. Note that signatures using SHA1 and MD5 are also
forbidden at this level as they have less than 80 security bits.
Additionally, SSLv3, TLS 1.0, TLS 1.1 and DTLS 1.0 are all
disabled at this level.

Level 2
Security level set to 112 bits of security. As a result RSA, DSA
and DH keys shorter than 2048 bits and ECC keys shorter than 224
bits are prohibited. In addition to the level 1 exclusions any
cipher suite using RC4 is also prohibited. Compression is
disabled.

Level 3
Security level set to 128 bits of security. As a result RSA, DSA
and DH keys shorter than 3072 bits and ECC keys shorter than 256
bits are prohibited. In addition to the level 2 exclusions
cipher suites not offering forward secrecy are prohibited.
Session tickets are disabled.

Level 4
Security level set to 192 bits of security. As a result RSA, DSA
and DH keys shorter than 7680 bits and ECC keys shorter than 384
bits are prohibited. Cipher suites using SHA1 for the MAC are
prohibited.

Level 5
Security level set to 256 bits of security. As a result RSA, DSA
and DH keys shorter than 15360 bits and ECC keys shorter than
512 bits are prohibited.

Levels 4 and 5 are tantamount to making RSA and DSA unavailable.  Even
level 3 is too distruptive for interoperable use on the public Internet.

As you observed, Level 2 disables 1024-bit RSA.  The symmetric
equivalent bit strength of a particular public key can be queried via:
EVP_PKEY_security_bits(3):

EVP_PKEY_security_bits() returns the number of security bits of the
given pkey, bits of security is defined in NIST SP800-57.

-- 
Viktor.


Re: Query minimum RSA key size?

2022-09-26 Thread Viktor Dukhovni
On Mon, Sep 26, 2022 at 09:52:29AM -0400, Felipe Gasper wrote:

> OpenSSL 1.1.0k introduced behaviour that rejects 1,024-bit RSA key sizes.

No such change was made.  Perhaps your OS distribution has bumped the
default (TLS) security level from 1 (80-bit or more) to 2 (~112 bit or
more).  You can look in the system-wide openssl.cnf file.

> Is the new minimum key size queryable? It appears to be 2,048, but in
> the event that that changes again I’d ideally love just to grab that
> value from OpenSSL itself rather than hard-coding it.

The security levels are documented.  You can set the security level
in the cipher string:

DEFAULT:@SECLEVEL=1

or via the API.

-- 
VIktor.


Re: PEM to EVP_PKEY

2022-09-25 Thread Viktor Dukhovni
On Sun, Sep 25, 2022 at 04:12:57PM -0700, Kory Hamzeh wrote:

> So I have a PEM formatted file that contains an EC certificate and a
> private key. I need to load that PEM file and converted to an
> EVP_PKEY. The goal of this exercise is so that I can do an ECDH
> pairwise consistency test (SP 800-56Ar3 Section 5.6.2.1.4) on the key
> pair by calling EVP_PKEY_pairwise_check(). I need some help in getting
> from the PEM file to an EVP_PKEY.

For an "atomic" interface, that reads both from the same file, even
if the file is replaced (atomically, via rename(2)) while the key and
cert are being read:

1. 
https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L344-L378
2. 
https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L245-L266

For a simpler interface that is subject to races vs. atomic updates:


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L245-L266

-- 
Viktor.


Re: Problem with Asymetric, two-key encryption and Certificate Requests.

2022-09-18 Thread Viktor Dukhovni
On Mon, Sep 19, 2022 at 01:32:40AM +, A Z wrote:

> A#) openssl req -x509 -nodes -newkey rsa:4096 -keyout private.key -out 
> public.key
> 
> B#) openssl smime -encrypt -binary -aes-256-cbc -in message.txt -out 
> encrypted.dat -outform DER public.key
> 
> C#) openssl smime -decrypt -in encrypted.dat -binary -inform DEM -inkey 
> private.key -out decrypted.txt
> 
> How can I complete step A#), so that step B#)  will work, without
> involving a Certificate Request, which requires a non-blank two digit
> nation code,
> 
> 'You can set an empty issuer/subject DN, or use "-keyid" to avoid
> copying these into the CMS message.'
> 
> Can someone please update my included A#), B#) or C#) instructions,
> included above here, to acheive this suggestion, so that no
> certificate information is put into 'encrypted.dat', including the
> nation, so that 'encrypted.dat' includes no plain text whatsoever, and
> so that A#) + B#) + C#) all work as desired, for small, medium and
> large files, of 'message.txt'?  I am struggling to correct what I have
> done so far, so that there are no errors, and so that all the steps
> work: (generation of a private and public key, encryption of the file,
> and decrypt of the file).  ?

1.  Generate the self-signed certificate using a configuration that
sets a subject key id.
2.  Also set an empty subject name via "-subj /".  The example also
sets a 100 year expiration time.

$ openssl req \
-nodes -newkey rsa:4096 -keyout pkey.pem \
-x509 -out cert.pem \
-days 36500 -subj / \
-addext "subjectKeyIdentifier=hash"

3.  Use "openssl cms" insteadm of "openssl smime", and set the "-keyid"
option when encrypting.

$ openssl cms -keyid -encrypt -binary -aes-256-cbc \
-in /some/file -out /some/file.cms -outform DER \
-recip cert.pem

[ There appears to be a bug in the implementation of the
  "-keyid" option in OpenSSL 1.1.1.  It works with OpenSSL
  3.0.5. ]

 You're not *signing* the content.  It is trivially spoofed, because
 unless the public certificate is also kept secret, anyone can
 encrypt a substitute file, and decryption will later succeed. 

 Instead of worrying about insignificant plaintext metadata, you
 should be worrying about data integrity, and related actually
 relevant issues, some noted below.

4.  Again use "openssl cms" to decrypt.

$ openssl cms -decrypt -in /some/file.cms -binary -inform DER \
-inkey pkey.pem -out /some/file.dat

[ But see above, you have zero guarantee that the file has not
  been tampered with by some with access to the non-secret public
  key. ]

It is rather puzzling why it would be a problem to set some correct or
bogus 2-letter country code.  It in no way compromises the security of
the data.  That said, you can avoid this if it really bugs you.

As to the goal of encrypting "large files", note that neither CMS, nor
SMIME are particularly well suited in that regard.  Decryption of CMS
messages brings the entire encrypted object into memory, this does not
scale well for "large files".

For large file encryption you'd ideally want to break the file into
chunks (say 4MB each), separately encrypt and MAC (HMAC is harder to
misuse than AEAD) each block's sequence number and data under a
symmetric key.

Then separately encrypt (and sign!) a data structure with any relevant
file metadata and symmetric key with CMS.  (The metadata should
typically include the file name, modification time, ... so that
malicious substitution of some other file is later easier to detect).

A final < 4MB length block would signal the end of the file.

Decryption needs to verify the signature, decrypt the metadata, recover
the symmetric key, and then decrypt all or some of the blocks, verifying
the sequence numbers, and (if recovering the whole file) that the last
block (possibly empty) is shorter than the chunk size.

Decryption can then proceed one block at a time, with each block
verified independently without having to buffer the entire file.

A proper encrypted backup design requires more care than just naive use
of CMS (or its precursor S/MIME).  You're fixating on entirely the wrong
set of issues.

-- 
Viktor.


Re: Problem with Asymetric, two-key encryption and Certificate Requests.

2022-09-17 Thread Viktor Dukhovni
On Thu, Sep 08, 2022 at 02:08:40AM +, A Z wrote:

> I have wanted to get into public/private two key encryption, of
> computer files of any type and any size and type.  I am working on
> Windows 10 64 bit.I found the ensuing approach by my own
> experimenting, but it has a key disadvantage.

What threat model requires you to obscure all traces of cleartext
metadata in the encrypted message?  In most common formats, in order to
facilitate algorithm agility, at least the encryption algorithm
identifier (often an ASN.1 OID) is included in the clear.

> In order for the encryption step to work by means of the public key,
> I have found the following approach with relies on the generation of a
> Certificate Request.  The problem is however, that by doing things like this,
> 
> A#) openssl req -x509 -nodes -newkey rsa:16384 -keyout private.key -out 
> public.key

This actually generates a self-signed X.509 certificate.  You can the

-subj / -days 3650

options to set empty subject and issuer DNs and (given self-signed cert)
a 10-year or longer validity.  Use of RSA 16384 is ludicrous.  Anything
longer than 4096 bits is just posturing and even that is overkill,
once/if 2048-bit RSA is broken, the rest will surely follow in quick
succession...

> B#) openssl smime -encrypt -binary -aes-256-cbc -in message.txt -out 
> encrypted.dat -outform DER public.key

In S/MIME (or its more modern incarnation as CMS) each recipient's
wrapped key carries a suitable recipient identifier:

https://www.rfc-editor.org/rfc/rfc5652#section-6.2

  KeyTransRecipientInfo ::= SEQUENCE {
version CMSVersion,  -- always set to 0 or 2
rid RecipientIdentifier,
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
encryptedKey EncryptedKey }

  RecipientIdentifier ::= CHOICE {
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] SubjectKeyIdentifier }

If you want to use a key identifier instead of (issuerDN + serial), you
can use the "-keyid" option of the cms(1) command, having first made
sure that the certificate you generate carries a subject key identifier.

> I can get plain text injected into the encrypted text, which I want to
> totally avoid every part of.

Your aversion to "plaintext" here looks poorly motivated.  It is just
CMS (S/MIME) recipient metadata.  CMS is not deniable encryption, the
outer layers of encapsulation are not encryption.

> How can I complete step A#), so that step B#)  will work, without involving a 
> Certificate Request, which requires
> a non-blank two digit nation code,

You can set an empty issuer/subject DN, or use "-keyid" to avoid copying
these into the CMS message.

-- 
Viktor.


Re: AW: [EXTERNAL] Stricter pathlen checks in OpenSSL 1.1.1 compared to 1.0.2?.

2022-09-16 Thread Viktor Dukhovni
On Fri, Sep 16, 2022 at 02:11:38PM +, Andrew Lynch via openssl-users wrote:

> http://sm-pkitest.atos.net/cert/Atos-Smart-Grid-Test.CA.2.crt
> 
> I’ve also asked my colleagues why the download is http instead of https…

You should look to multiple independent sources to validate the
authenticity of a trust anchor public key.  Trusting "https" to prove
the validity of a WebPKI trust anchor is a bit too circular.

Also "https" is redundant for CRL and intermediate CA distribution,
since these are signed by the issuing CA.  That said, the same ".crt"
file is availabe via "https":

https://sm-pkitest.atos.net/cert/Atos-Smart-Grid-Test.CA.2.crt

Trust anchor certificates are often delivered as an operating system
"package", and ideally the package maintainers apply proper due
diligence.

-- 
Viktor.


Re: AW: [EXTERNAL] Stricter pathlen checks in OpenSSL 1.1.1 compared to 1.0.2?.

2022-09-16 Thread Viktor Dukhovni
On Fri, Sep 16, 2022 at 08:32:27AM +, Andrew Lynch via openssl-users wrote:

> So is this a possible bug or a feature of OpenSSL 1.1.1?  (using
> 1.1.1n right now)

OpenSSL 1.1.1 is doing the right thing.

> If I set up the content of CAfile or CApath so that E <- D <- C <- A
> is the only path that can be taken then the validation fails with

There are two intermediate CA certificates (C and D) in this path.  This
path should be rejected when the path length constraint of A is set to 1.

> If I create the first root certificate (A) with pathlen:2 instead of
> pathlen:1 then validation succeeds

As expected.

> So it appears to me that OpenSSL 1.1.1n is definitely taking the
> pathlen constraint of certificate A into account.

As expected.  While A's self-signed certificate is not counted in the
path length, its path length constraint is honoured and applied to the
rest of the non-EE (and not self-issued) CA certificates in the chain.

On Fri, Sep 16, 2022 at 12:23:12PM +, Corey Bonnell via openssl-users wrote:

> Can you provide the actual subject DNs for each certificate? RFC 5280
> specifies that self-issued certificates (i.e., issuer DN == subject
> DN) are not considered in the pathLen calculation, so knowing whether
> these certificates are self-issued or not may be helpful in better
> diagnosing the issue.

There's no need.  Everything is working as expected.

-- 
Viktor.


Re: Stricter pathlen checks in OpenSSL 1.1.1 compared to 1.0.2?

2022-09-15 Thread Viktor Dukhovni
On Thu, Sep 15, 2022 at 05:34:07PM +, Andrew Lynch via openssl-users wrote:

> Why is OpenSSL 1.0.2 verifying successfully?  Does it not check the
> path length constraint or is it actually picking the depth 2 chain
> instead of the depth 3?

There are two important differences between 1.0.2 and 1.1.1:

- In 1.1.1 the trust store is always checked before any
  untrusted certificates provided by the peer.  In 1.0.2
  one would have to explicitly set the "trusted first"
  flag in the store context to get the same behaviour.

  This can result in different chains being built from
  the same data.

- In 1.1.1 the same checks are applied to both certificates from the
  peer and the trust store.  In 1.0.2, IIRC some checks may have
  been (incorrectly I believe) applied only to certificates from the
  peer.  I don't recall whether this could affect how path length
  limits are enforced, or whether 1.0.2 got updated at some point to
  treat both sources equivalently.

Finally, an RFC5280 trust anchor is a public key.  Any associated
self-signed CA certificate is still CA certificate.  Implementations can
honour any path length constraint stored in such a certificate.

-- 
VIktor.


Re: Strange problem: openssl verify not working on Proxmox VM, works on a bare metal system

2022-09-04 Thread Viktor Dukhovni
On Sun, Sep 04, 2022 at 08:55:26AM +0100, Roger James via openssl-users wrote:

> As I mentioned in an earlier post you need version 1.1 or later of openssl 
> to successfully validate post September 30, 2021 Lets Encrypt certificates. 
> The version on your Centos system is 1.0.

This is not quite true when using verify(1), because one has complete
control over the chain presented for verification via a combination
of the:

* -trusted anchors.pem, and
* -untrusted chain.pem

options.  The change to "trusted first always" behaviour in OpenSSL 1.1
is relevant to TLS clients validating some Let's Encrypt certificate
chains, where the untrusted chain comes from the server, and the DST
cross certificate may not find an unexpired trust anchor in the trust
store.  All that being true, it is not the situation faced by the OP.

FWIW, the EE certificate in question can also be verified with OpenSSL
1.0.2, given the right set of untrusted intermediates and trust
anchor.

-- 
Viktor.


Re: Strange problem: openssl verify not working on Proxmox VM, works on a bare metal system

2022-09-03 Thread Viktor Dukhovni
On Sat, Sep 03, 2022 at 05:47:25PM -0600, Shawn Heisey via openssl-users wrote:

> > Post the output of:
> >
> > $ openssl crl2pkcs7 -nocrl -certfile 
> > /etc/ssl/certs/local/DOMAIN.wildcards.pem |
> > openssl pkcs7 -print_certs -noout |
> > perl -ne 'BEGIN{$/="\n\n\n"} s/\n+/\n/g; print $_, "\n"'
> 
> subject=CN = DOMAIN
> issuer=C = US, O = Let's Encrypt, CN = R3
> 
> subject=C = US, O = Let's Encrypt, CN = R3
> issuer=C = US, O = Internet Security Research Group, CN = ISRG Root X1

Your cert file holds the EE certificate and its R3 intermediate issuer.
It does not include a trusted root, therefore when used as the sole
trust store, it is not sufficient to verify your EE certificate.

If your system's default CApath (also consulted) happens to contain the
"ISRG Root X1" issuer CA of "R3", then the certificate validates,
otherwise it does not.  If that ISRG X1 is only in the default CA file,
verification fails, because you've specified your chain as the CAfile
instead.

> The combined cert file that I have built does NOT contain the root 
> cert.  I only need to send the server cert and the issuing cert. The 
> browser will have the root cert, so there is no need to send it.

This is typically true (unless you've published DANE TLSA records for
the root CA), but to match the browser's behaviour, your trust store
needs to include the ISRG X1 root, and it does not when you override
the CAfile, and CApath fails to bridge the gap.

> If I use a file that DOES contain the root cert (one of the files 
> downloaded by certbot) then I can get it to pass with -untrusted, but 
> not -CAfile:
> 
> [root@certs ~]# openssl verify -untrusted 
> /etc/letsencrypt/live/DOMAIN/chain.pem /etc/letsencrypt/live/DOMAIN/cert.pem
> /etc/letsencrypt/live/DOMAIN/cert.pem: OK

The chain file probably contains the cross-certificate for X1 signed by
DST (Digital Signature Trust), and the latter root is in your default
system-wide CAfile or CApath.

> [root@certs ~]# openssl verify -CAfile /etc/letsencrypt/live/DOMAIN/chain.pem 
> /etc/letsencrypt/live/DOMAIN/cert.pem
> C = US, O = Internet Security Research Group, CN = ISRG Root X1
> error 2 at 2 depth lookup: unable to get issuer certificate
> error /etc/letsencrypt/live/DOMAIN/cert.pem: verification failed

This invocation does not add the cross certificate.

> I suspect this is because the contents of /etc/ssl/certs is so 
> different.

Some already list the ISRG X1 root in the system CAfile or CApath,
others do not.  OpenSSL does not ship any trusted certificates.
Your issue has nothing to do with OpenSSL as such.  It is all about
the content of the vendor provided trust store and the command-line
options you're choosing.

-- 
Viktor.


Re: Strange problem: openssl verify not working on Proxmox VM, works on a bare metal system

2022-09-03 Thread Viktor Dukhovni
On Fri, Sep 02, 2022 at 09:42:13PM -0600, Shawn Heisey via openssl-users wrote:

> On an AlmaLinux 8.6 VM hosted in Proxmox:
> 
> [root@certs ~]# openssl verify -CAfile 
> /etc/ssl/certs/local/DOMAIN.wildcards.pem 
> /etc/ssl/certs/local/DOMAIN.wildcards.pem
> C = US, O = Let's Encrypt, CN = R3
> error 2 at 1 depth lookup: unable to get issuer certificate
> error /etc/ssl/certs/local/DOMAIN.wildcards.pem: verification failed

Post the output of:

$ openssl crl2pkcs7 -nocrl -certfile 
/etc/ssl/certs/local/DOMAIN.wildcards.pem |
openssl pkcs7 -print_certs -noout |
perl -ne 'BEGIN{$/="\n\n\n"} s/\n+/\n/g; print $_, "\n"'

> If I copy the PEM file to a bare metal system running Ubuntu Server 
> 20.04, it verifies:

Note that OpenSSL verify also looks in the default CApath, and this may
vary from system to system.  The results may depend on what's installed
there.

The verify(1) command will attempt to construct a chain to a trusted
root using the specified or default CAfile and CApath.  You should
really be using the "-untrusted" option not the "-CAfile" option:

# cert=/etc/ssl/certs/local/DOMAIN.wildcards.pem
# openssl verify -untrusted "$cert" "$cert"

This adds the untrusted intermediate certs from the cert file to
the dataset, without shadowing the default CAfile.

-- 
Viktor.


Re: Session ID is coming as NULL in openSSL 3.0.2 and TLS 1.2 version

2022-09-02 Thread Viktor Dukhovni
On Fri, Sep 02, 2022 at 07:23:41AM +, Sethuraman Venugopal wrote:

> The SSL session is getting created successfully, but the session ID is
> coming as NULL, due to which the handshake is failing between the
> client and server.

Successful handshakes need not issue a non-empty session id.  The server
may not support resumption, or may support only ticket-based resumption
and have no session cache.

Absence of a session id is NOT a failure, and your code must not require
one.

https://datatracker.ietf.org/doc/html/rfc5077#section-3.4

> Please suggest me a solution for this issue.

Don't require a session id.

-- 
Viktor.


Re: enforcing mutual auth from the client

2022-09-01 Thread Viktor Dukhovni
On Fri, Sep 02, 2022 at 12:22:35AM +, Wall, Stephen wrote:

> > A compromised server could easily still request the client certificate, no?
> 
> > But as noted, even a compromised server can ask for client credentials and 
> > then
> 
> Yes, that's true.  If the intruder knew to do so.  Also, a thief can
> break your window and get into your car, so you might as well leave
> them rolled down all the time.
> 
> The question wasn't "Should I care that..."  or "Is it a good idea
> to...".  It was "Can OpenSSL 3 do this".

At the conclusion of the handshake you can enquire whether the
server sent a CertificateRequest by asking for the list of peer_CA_DNs,
via SSL_get0_peer_CA_list(3).

If I am not mistaken, the documentation fails to make clear that NULL is
returned when the server did not solicit a client certificate, and a
non-null (possibly empty) stack of X509_NAME is returned otherwise.

Of course this test should only be applied for a full handshake, reused
sessions piggyback on the certificates exchanged in the original full
handshake.

-- 
Viktor.


Re: enforcing mutual auth from the client

2022-09-01 Thread Viktor Dukhovni
On Thu, Sep 01, 2022 at 09:36:36PM +, Wall, Stephen wrote:

> Does OpenSSL 3.0 provide a way for client side software to verify that
> the server actually sent a request for the client’s certificate?

It is not clear what threat model warrants taking special action when
the client certificate is not requested.  It could equally be requested
and then largely ignored.

Note that if resumption takes place the handshake might even happen
without presenting the server certificate to the client.

-- 
Viktor.


Re: parsing invalid DER

2022-09-01 Thread Viktor Dukhovni
On Thu, Sep 01, 2022 at 08:21:21AM -0400, Dave Coombs via openssl-users wrote:

> These are the 2 invalid encodings I have seen:
> 
> First, a bit-string used for flags, encoded as (hex) 030108.  That is,
> the number of unused bits is set to 8, and no other content, presumably
> indicating no flags are set.  DER would have this be 030100 instead. 
> My d2i is resulting in ASN1_R_INVALID_BIT_STRING_BITS_LEFT in
> c2i_ASN1_BIT_STRING().

This is likely not even valid BER, so you'll need a custom decoder to
deal with this.

> Second, a positive integer with leading 00 padding which is not
> necessary, encoded as 80020042.  (It has an implicit [0] tag.)  DER
> would have this be 800142.  My d2i is resulting in
> ASN1_R_ILLEGAL_PADDING in c2i_ibuf().

This is at least BER, so a BER decoder should be able to handle it.

But the "d2i*" routines expect DER, so the above breakage is not
d2i-compatible.

-- 
Viktor.


Re: RSA signed ECDSA certificate still uses ECDSA for authentication

2022-08-26 Thread Viktor Dukhovni
On Fri, Aug 26, 2022 at 01:28:21PM -0700, radiatejava wrote:

> >> and then the same ECDSA key verified by the CA to sign a hash over the 
> >> transcript of the handshake itself
>
> Which part of the TLS handshake you are talking about? Are you talking
> about the three messages from the client to server messages that are -
> ClientKeyExchange, ChangeCipherSpec, ClientFinished? In my
> understanding, ClientKeyExchange, ChangeCipherSpec are not encrypted
> and the last one ClientFinished is encrypted but using the keys
> derived from ECDHE key exchange algorithm. Is that not right?

Other than with TLS 1.0--1.2 anon-DHE and anon-ECDHE ciphersuites, the
server key exchange message parameters are signed with the server's
public key.  If a client certificate is solicited, the client's
ClientVerify message is signed with the client's public key.

I am not aware of any anon-DHE or anon-ECDHE ciphers for TLS 1.3.  I'd
advocate for these to be added (for unauthenticated opportunistic TLS),
if I did not suspect that there would be little support for them at
present.

-- 
Viktor.


Re: OpenSSL errno=104

2022-08-26 Thread Viktor Dukhovni
On Fri, Aug 26, 2022 at 03:59:02AM +, Danilo Singh wrote:

> The URL we are trying to connect to is notacarioca.rio.gov.br.  When
> trying to run an openssl s_client -connect, we get error 104, with the
> following return:

> write:errno=104

That is a write system call errno value, which translates to:

$ perl -le '$! = 104; print "$!"'
Connection reset by peer

The server is resetting the TCP connection just after receiving the TLS
CLIENT HELLO message.  Or more likely some oddball firewall in front of
the server is doing that.

The server refuses to negotiate any ciphers other RSA key exchange
(which by the way precludes use of TLS 1.3), and is rather sensitive
to the order in which the 'kRSA' ciphers appear in the cipher list.

Removing all 'SHA1' ciphers seems to help, but also removing non
RSA key-exchange ciphers (while leaving SHA1 enabled) helps.

... -cipher 'DEFAULT:!SHA1' ...
... -cipher 'kRSA:!COMPLEMENTOFDEFAULT' ...

So rather unclear what exactly makes the server unhappy, but it does
when it works, it seems to choose:

0x00,0x9D - TLS_RSA_WITH_AES_256_GCM_SHA384 TLSv1.2 Kx=RSA Au=RSA 
Enc=AESGCM(256) Mac=AEAD

otherwise known as 'AES256-GCM-SHA384', which also works if you set it
to be the only client cipher.

> Currently the OpenSSL configuration on our server looks like this. We
> tried several ways, but none worked. As we have little experience with
> OpenSSL we don't know what is wrong.
> 
> CipherString = DEFAULT@SECLEVEL=0

The preferred syntax for this is "DEFAULT:@SECLEVEL=0".

> Ciphersuites = 
> TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:TLS_RSA_WITH_AES_128_CBC_SHA256:TLS_RSA_WITH_AES_256_CBC_SHA256:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384

Perhaps leave these defaulted.

> MinProtocol = TLSv1.0
> MaxProtocol = TLSv1.3

> SignatureAlgorithms = 
> ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_rsae_sha256:rsa_pss_pss_sha384:rsa_pss_rsae_sha384:rsa_pss_pss_sha512:rsa_pss_rsae_sha512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:ECDSA+SHA1:RSA+SHA1

Perhaps leave these defaulted.

-- 
Viktor.


Re: What is 'trusted certificate'

2022-07-16 Thread Viktor Dukhovni
On Sat, Jul 16, 2022 at 08:45:22AM +0200, David von Oheimb wrote:

> To me the below warnings looks strange because usually at depth 0 and 1
> of a cert chain (i.e., at the positions of the end entity cert and any
> subsequent intermediate cert) it is normal to have untrusted certs.
> Usually only at the end of the chain you have a trusted cert that
> represents the trust anchor for the chain.

The certificate in question appears to be issued by a private CA, so the
immediate issuer may well be the trust-anchor.  That said, yes, there is
not enough information in the OP's message to determine even whether
there is a problem, or what it might be.

> > I have freeradius server configured to use EAP-TLS (certificate
> > baset authn) Since some time I have warning in logs:
> > 
> > --8<---cut here---start->8---
> > Fri Jul 15 22:29:04 2022 : Warning: (TLS) untrusted certificate with
> > depth [1] subject name
> > /C=PL/ST=Mazowieckie/L=Warszawa/O=beta/OU=wifi/CN=beta-wifi-ca
> > Fri Jul 15 22:29:04 2022 : Warning: (TLS) untrusted certificate with
> > depth [0] subject name
> > /C=PL/ST=Mazowieckie/O=beta/OU=wifi/CN=salamandra
> > --8<---cut here---end--->8---
> > 
> > I took a look into code and it seems to be related to
> > "X509_STORE_CTX_get0_untrusted(ctx)" function.

That's almost certainlky a red herring.  It returns the list of non
helper certificates that are used to build a chain to the root of trust.
These are typically the certificates provided by the peer.  Trusted
certificates come from the local trust store (CAfile, CApath, ...).

> > I tried to search, but without success.  Can anyone tell me when
> > certificate is "trusted" in this context?  (How to get rid this
> > warning) or point to documentation/search keys

A trusted certificate is a typically self-signed CA certificate stored
in a file which is used to hold trusted certificates.

-- 
VIktor.


Re: DH parameter reading in OPENSSL 3

2022-07-13 Thread Viktor Dukhovni
On Wed, Jul 13, 2022 at 06:47:15PM +0200, Dirk Stöcker wrote:

> > https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_dh.c#L148-L205
> 
> Thanks a lot. Works in principle now with one exception. The previous 
> approach worked for a file, where first comes the PEM certificate and 
> afterwards the DH params. The new approach only works when the file has 
> nothing than the DH params inside. Is there a chance to get that behaviour 
> back or do I need to load the file and strip the certificate myself?

The work-around is to put the DH parameters first.  Otherwise, you'd
need to resort to the more general OSSL_STORE API, which loads objects
of various types, and you can then ignore the ones you don't care for.

Another option is to iterate through the PEM file via the generic PEM
API, and then decode just the desired objects:


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L344-L378.

-- 
Viktor.


Re: DH parameter reading in OPENSSL 3

2022-07-13 Thread Viktor Dukhovni
On Wed, Jul 13, 2022 at 04:35:42PM +0200, Dirk Stöcker wrote:

> when upgrading to openssl3 my code states that some functions are 
> deprecated in openssl 3, but even after reading documentation I was 
> unable to find a non-deprecated replacement.


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_dh.c#L148-L205

> Now it seems the default can be replaced by
> 
>   SSL_CTX_set_dh_auto(context, 1);

This is preferred over all explicit parameter choices, as it allows the
server and client to negotiate a common known-strong group.

-- 
Viktor.


Re: error: wrong version number

2022-07-10 Thread Viktor Dukhovni
On Sun, Jul 10, 2022 at 02:41:23PM +, loic nicolas wrote:

> I am trying to connect my client to my server but I always receive an
> error.(ssl3_get_record:wrong version
> number:../ssl/record/ssl3_record.c:331)
> 
> How can I get more information about the error and fix it? (the error
> is probably in my client)

Indeed, the client's packet to the server is not a TLS Record.

> openssl s_server -accept 127.0.0.1:3000 -key server.key -cert server.cert -msg
> 
> <<< ??? [length 0005]
> 20 ae c0 2e d6

Whatever the client is doing, it isn't starting a TLS session with a
TLS handshake record containing a TLS client HELLO.

-- 
VIktor.


Re: baffled on old Red Hat Enterprise Linux 6 with OpenSSL 3.0.3

2022-06-10 Thread Viktor Dukhovni
On Fri, Jun 10, 2022 at 09:43:45AM -0400, Dennis Clarke via openssl-users wrote:

> I am surprised that people are not hitting this wall on all
> platforms. Pushing out a new release jsut for an expired test
> certificate seems a tad silly but perhaps ALL the test certs can
> be updated at the same time. Whatever works.

Most of the test certificates were generated via my "mkcert" script,
which creates 100-year certificates, and will not expire until some time
after 2316.

The particular problem certificates were generated manually, by the
author of the SCT (certificate transparency) code, and sadly were not
created with nearly as long a lifetime.  I hope their replacements don't
have that issue.

-- 
Viktor.


Re: How to figure out if .P12 is RSA or ECC crypted

2022-06-09 Thread Viktor Dukhovni
On Thu, Jun 09, 2022 at 10:16:24AM +, Beilharz, Michael wrote:

> I retrieve .P12 certificates, they can be RSA or ECC crypted

PKCS#12 objects are encrypted with a *symmetric* password: 3DES, AES,
...  Perhaps you're confusing the public key algorithm in the
certificate (or corresponding private key) with the encryption algorithm
of the PKCS#12 object?

> so I offer two methods, to convert them into .PEMs.

The extraction of PEM formatted (PKCS#8) private keys and certificate
chains (a sequence of X.509 certificate objects) from a PKCS#12 object
does not require any public key algorithm-dependent techniques.  The
same basic steps work for both RSA and ECDSA.

> I would like to detect, if a P12 is RSA or ECC crypted, so that I
> offer only one Method and the method itself decide the correct way to
> convert the P12.

What actual problem are you trying to solve?

-- 
Viktor.


Re: using TLS (>1.2) with more than one certificate

2022-05-24 Thread Viktor Dukhovni
On Tue, May 24, 2022 at 04:10:00PM +0100, Angus Robertson - Magenta Systems Ltd 
wrote:

> I do see a lot of SSL connection errors in my logs, but assume these
> are mostly hackers or trackers with software not able to support
> TLS/1.2, usually with a blank SNI and ALPN and often no extensions in
> the client hello.  One had 'Versions: TLSv1.1, TLSv1.3 Key Share Data'
> so got unsupported protocol.  

Various less popular, but still deployed SMTP servers are not updated
nearly as often as desktop browsers, ... and some still support only
RSA.  Depending on where your users' mail comes from you may need to
support RSA for SMTP.  This is not a strong recommendation, but it is
something to keep in mind.

-- 
Viktor.


Re: Help needed with X509_STORE_CTX structure

2022-05-09 Thread Viktor Dukhovni
On Mon, May 09, 2022 at 06:00:14AM +, Srinivas, Saketh (c) wrote:

> I need to set the current_issuer field in an object of the
> X509_STORE_CTX structure. Can any suggest the setter function for
> this.

You almost certainly don't *need* to do this.  What is the actual
high-level task you're trying to achieve.

X509_STORE_CTX is used with X509_verify_cert():

https://www.openssl.org/docs/manmaster/man3/X509_verify_cert.html

to verify a certificate chain.  The "current_issuer" field is filled in
so it can be read by callbacks, setting it in user code makes little
sense.

Note that the X509_STORE_CTX structure is not opaque, and you can just
set its fields, but in this is case it is likely a bad idea to do that.

> Also, current_crl_score and current_reasons also are needed to be 0
> for me. Can you suggest setters for these variables.

Ditto.

-- 
Viktor.


Re: X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS

2022-04-19 Thread Viktor Dukhovni
On Tue, Apr 19, 2022 at 10:07:15PM -0400, Viktor Dukhovni wrote:

> This is an apples/oranges dichotomy.  "*" wildcards are "presented
> identifiers" in the certificate.
> 
> If the documentation is not sufficiently clear (too subtle) on this
> point, would you like to suggest some text to clarify the documentation?
> A pull request?

Note that paragraph three of the DESCRIPTION reads:

    When name [bold font] starts with a dot (e.g. ".example.com"),
   it will be matched by a certificate valid for any sub-domain of name,
   (see also X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS below).

where it should ideally be clear that we're talking about the peer name
specified by the application (reference identifier in terms of RFC 6125),
not a DNS-ID in the certificate (presented identifier).

-- 
Viktor.


Re: X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS

2022-04-19 Thread Viktor Dukhovni
On Tue, Apr 19, 2022 at 03:25:03PM -0700, Hal Murray wrote:

> man X509_check_host says:
>If set, X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS restricts name values
>which start with ".", that would otherwise match any sub-domain in the
>peer certificate, to only match direct child sub-domains.  Thus, for
>instance, with this flag set a name of ".example.com" would match a
>peer certificate with a DNS name of "www.example.com", but would not
>match a peer certificate with a DNS name of "www.sub.example.com"; this
>flag only applies to X509_check_host.
> 
> I haven't see the idea of ".example.com" being special in any of the RFCs 
> I've 
> been looking at.  Can somebody give me a lesson in this area?

You perhaps did not notice that this describes syntax in "reference
identifiers" (arguments to SSL_set1_host(3), ...), rather "presented
identifiers" (contents of the peer certificate).

As such these a local matter (API detail) that lies outside any RFC.
A verifier than asks for a specific hostname is not affected by this
feature.  But a verifier that asks OpenSSL to verify ".example.com"
against a certificate is specifying a "fuzzy" match.

> Is there any way to turn it off totally while still allowing * type wildcards?

This is an apples/oranges dichotomy.  "*" wildcards are "presented
identifiers" in the certificate.

If the documentation is not sufficiently clear (too subtle) on this
point, would you like to suggest some text to clarify the documentation?
A pull request?

-- 
Viktor.


Re: freefunc - name clash with Python.h

2022-04-19 Thread Viktor Dukhovni
> On 21 Jun 2020, at 1:20 pm, Dan Kegel  wrote:
> 
> Openssl should probably stop using generic identifiers like freefunc
> in its header files, out of sheer self-defense.

I'd long held an apparently minority opinion among OpenSSL team members
that prototypes in header files MUST NOT name any variables, and should
only mention their types, precisely to avoid this sort of issue.  Thus,
e.g.:

int foo(char *, int);

rather than:

int foo(char *buf, int len);

Variable names in header files are no substitute for documentation, and
are all too prone to precisely this sort of conflict.

-- 
Viktor.



Re: How does a client get the server's SAN/DNS strings

2022-04-17 Thread Viktor Dukhovni
> On 17 Apr 2022, at 11:29 am, Michel  wrote:
> 
> What a beautiful source code !
> If only all software could be written like this !

The Postfix project aims for code quality, security and backwards
compatibility over hastily deployed shiny new features.  You'll
find many examples of careful/correct use of OpenSSL in:

https://github.com/vdukhovni/postfix/tree/master/postfix/src/tls

The main "limitation" to keep in mind is that the Postfix concurrency
model is multi-process no multi-thread.  So issues related to thread-safety
don't arise and are not addressed.

-- 
Viktor.



Re: How does a client get the server's SAN/DNS strings

2022-04-16 Thread Viktor Dukhovni
On Sat, Apr 16, 2022 at 03:02:16PM -0700, Hal Murray wrote:
> openssl-us...@dukhovni.org said:
> > Can you explain *why* you want the list of DNS names?
> > Is this just for logging..
> 
> Yes, just for logging.


https://github.com/vdukhovni/postfix/blob/postfix-3.5/postfix/src/tls/tls_client.c#L756-L794

-- 
Viktor.


Re: How does a client get the server's SAN/DNS strings

2022-04-16 Thread Viktor Dukhovni
On Sat, Apr 16, 2022 at 01:18:57PM -0700, Hal Murray wrote:

> I can get the subject and issuer with
>   X509_get_subject_name and X509_get_issuer_name
> 
> I'm looking for something similar to get the SAN/DNS strings used to verify 
> that this certificate is valid for the hostname provided via SSL_set1_host
> 
> Any API will be slightly complicated since there may be more than one SAN/DNS 
> string.

Can you explain *why* you want the list of DNS names?  What's wrong with
letting OpenSSL doing the validation for you?  Is this just for logging,
or do you intend to supplant the built-in name checks?

-- 
Viktor.


Re: CVE-2022-0778 - Impact of ECC cipher with valid server ECC certificate

2022-03-26 Thread Viktor Dukhovni
On Sat, Mar 26, 2022 at 12:32:03PM +0530, Vipul Mehta wrote:

> If we consider ECDHE_ECDSA cipher based TLS handshake, then it is possible
> that the client can send invalid public session key to the server causing
> the vulnerability. Is this assumption correct ?

The CVE only affects situations in which the untrusted peer can specify
malign "explicit" curve *parameters*, not just the public point.

> If yes, then I think disabling ECC cipher suites should prevent the
> vulnerability if we don't want to upgrade openssl considering there is no
> other cryptographic operation except w.r.t. TLS.

Unless I'm missing something, there's no need to disable ECC ciphers,
since with TLS 1.0 through 1.2 the curve parameters are chosen by the
server.

With the TLS 1.3, the client typically sends a key share first, which
consists of a named group and again a public point.  There is no
mechanism for conveying "explicit" ECC parameters

https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8
https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.2

So either way, TLS servers are safe if they don't solicit client
certificates, or otherwise in some form consume X.509 SPKI public keys
(which with ECC do signal either a named group or provide explicit
parameters).

-- 
Viktor.


Re: Verify signature usage

2022-03-21 Thread Viktor Dukhovni
> On 21 Mar 2022, at 2:36 pm, buy  wrote:
> 
> It works great.  Instead of using an actual signature.file, is there
> a way to tell openssl to use a string instead?

Use "bash" or a similar shell that supports <(cmd ...) pseudo-files.

For a printable string signature:

-signature <(printf "%s" "$sig")

If the signature is binary data, perhaps:

-signature <(echo $sig | openssl base64 -A -d)

or whatever it takes to produce the desired content.

-- 
Viktor.



Re: Certificate authority changes with OpenSSL

2022-03-17 Thread Viktor Dukhovni
On Thu, Mar 17, 2022 at 07:51:43PM +0100, egoitz--- via openssl-users wrote:

> I think that is the problem, the sha1.

That's the specific issue being reported.

> So... I have built Openssl 3.0.2

There's no reason for OpenSSL 3.0.2, that might just tighten the
restrictions further.  OpenSSL 1.0.0 and up all support SHA2-256,
you can create and consume SHA-2 certificates with OpenSSL 1.1.1.

> I have seen that the own CA uses sha1WithRSAEncryption signature
> algorithm.

Yes, fix that.

> I assume this is one of the things to change, so I have planned to
> convert the whole PKI, the whole CA to another supported Signature
> algorithm that had no issues with SECLEVEL2. 

Just set the default digest to sha256, and reissue all the intermediate
and leaf certificates.  The root CA can stay unchanged, its
self-signature is not relevant.

> 1 - Is it possible to update a whole CA with 2048 bit public and private
> keys (I used in req section of openssl.conf, the default_bits to 2048)
> to a Signature algorithm that don't bother the SECLEVEL 2?.

SHA2-256 is sufficient.

> I mean to have two versions of the same certificate. One for SECLEVEL1
> and one for SECLEVEL2?. I preserve all csr and so 

It is isn't "the same certificate".  You can issue new certificates,
that all clients can verify, by using SHA2-256.

> 2 - I was wondering too another question... although this is not urgent
> now. If the CA key pair, is almost expiring what's the proper process of
> doing what is supposed to be done?. I assume, it could be : 

Keys don't expired, certificates do.  You can reissue a CA certiifcate
with the same key and subject name, but a different expiration time and
serial number.

> But... I assume I would have to use a different CN for the new CA?.

No, you would typically use the same CN if just extending the validity.

> Perhaps is this same process the one I need to do for converting
> certificates from SECLEVEL 1 friendly to SECLEVEL 2 friendly?. 

Certificate don't have seclevels, they have a signature algorithm,
SHA2-256 has long been support by all clients.

-- 
Viktor.


Re: openssl-users Digest, Vol 88, Issue 18

2022-03-14 Thread Viktor Dukhovni
On Mon, Mar 14, 2022 at 12:47:26PM -0700, Edward Tsang via openssl-users wrote:

> I guess I need to explicitly set X509_STORE_CTX_set_error(ctx,
> X509_V_OK) before return 1 in the example if I need caller
> SSL_get_verify_result to return X509_V_OK?

Yes, but I'd like to strongly suggest that this is a bad idea.  Instead,
abort the handshake on errors you're unwiling to accept, and then the
only possible errors at the conclusion of the handshake are those you're
willing to accept.

You can then still observe and log the fact that the handshake was not
in fact fully authenticated, and an error condition was tolerated.

Note that by setting the error condition to X509_V_OK you might be
losing information about earlier error conditions which also returned
"ok = 1", but are not intended to be acceptable at the conclusion of the
handshake.  This poses significate security risks.

In other words, if sometimes (or always) return "ok = 1" even for error
conditions that you don't intend to clear, by clearing "expiration" and
treating the connection as verified on X509_V_OK you're opening up a
major security hole.  The only way to make this safe is to be sure to
return "ok = 0" on all other error conditions.  But, in that case, 
there's no point in doing anything drastic with SSL_get_verify_result(),
any error conditions that did not terminate the handshake must have
been acceptable.

You're skating on thin ice, and need to think very carefully about
possible subtle issues with your design choices.

-- 
Viktor.


Re: Question about examples in openssl doc X509_STORE_CTX_verify_cb

2022-03-14 Thread Viktor Dukhovni
On Mon, Mar 14, 2022 at 11:25:51AM -0700, Edward Tsang via openssl-users wrote:

> https://www.openssl.org/docs/man1.1.1/man3/X509_STORE_CTX_verify_cb.html
> 
> I am trying to figure out how this example works but it does not seem to
> bypass the (use the second example of  X509_V_ERR_CERT_HAS_EXPIRED)
> 
> However the caller code 
> long res = SSL_get_verify_result( sslCtx ); still reports res NOT as
> X509_V_OK, which it should be oper the example since it is returning as 1.

This is correct and expected.  Returning "ok = 1" from the verify
callback allows the handshake to continue, rather than be aborted,
but it does not and should not mark the certificate as verified.

> I don't think I need to use X509_STORE_CTX_set_error(ctx, X509_V_OK);
> before return 1 in the X509_STORE_CTX_verify_cb example.
> Or am I missing something?

You're missing something.  It is best to not suppress the error code,
since this will also mean that resumed sessions are unaware of the
error, ... Rather if you want to tolerate expired certificates record
and admit that error both in the callback and after the handshake.

-- 
Viktor.


Re: SSL_ERROR_WANT_READ after the handshake

2022-03-12 Thread Viktor Dukhovni
> On 12 Mar 2022, at 6:08 pm, loic nicolas  wrote:
> 
> After the handshake, is it really necessary to check SSL_ERROR_WANT_READ and 
> SSL_ERROR_WANT_WRITE? (whether on the server or client side)
> I don't want to accept a renegotiation, is it really possible that OpenSSL 
> sends me these events without them being linked to a renegotiation?
> 
> I did several tests on more or less long connections and I never receive them 
> but I would like to be sure.

Yes, you can encounter WANT_READ or WANT_WRITE even
after the handshake, especially when using non-blocking
sockets.

-- 
Viktor.



Re: Openssl s_client verify_ip usage on ip wildcard matching

2022-03-11 Thread Viktor Dukhovni
On Fri, Mar 11, 2022 at 04:40:24PM -0800, Edward Tsang via openssl-users wrote:

> Does verify_ip supports leftmost wildcard?

I am not aware of any RFC specifying wildcard matching in iPAddress
X.509 SANs, and no such feature is implemented in OpenSSL.

The SAN syntax is raw binary data in network byte order with 4 bytes for
IPv4 and 16 bytes for IPv6, with no place to signal a wildcard:

https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6

IP address SANs in certiificates must match exactly.

-- 
Viktor.


Re: Multi root certs support

2022-03-11 Thread Viktor Dukhovni
> On 11 Mar 2022, at 8:49 am, Tomas Mraz  wrote:
> 
> Yes, this is a fully supported scenario.
> 
> You can even test it with the openssl s_server command - use -cert, -
> key, and -cert_chain for the first certificate and -dcert, -dkey, and -
> dcert_chain with the second one.

Note that with e.g. SMTP, where some sites also publish DANE
TLSA records, when multiple certificates are configured, multiple
corresponding TLSA records need to be published:

 https://mail.sys4.de/pipermail/dane-users/2017-August/000416.html
 https://mail.sys4.de/pipermail/dane-users/2017-August/000417.html

At the API level you can call `SSL_CTX_use_cert_and_key(3)` multiple
times, once per algorithm.  If `replace` is zero and keys for the same
algorithm are provided more than once an error is reported.  For example:

  
https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_certkey.c#L152-L181
  https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_use_cert_and_key.html

The keys, cert and chain are copied by OpenSSL, so you need to free your
copy when no longer needed.

-- 
Viktor.



Re: is there any working example of how to use verify_hostname in command line?

2022-03-03 Thread Viktor Dukhovni
> On 3 Mar 2022, at 11:55 pm, Edward Tsang via openssl-users 
>  wrote:
> 
> the openssl I'm using is in mac
> openssl version -a
> LibreSSL 2.8.3

LibreSSL is not OpenSSL.  This is not the right forum for LibreSSL
questions.

-- 
Viktor.



Re: is there any working example of how to use verify_hostname in command line?

2022-03-03 Thread Viktor Dukhovni
On Thu, Mar 03, 2022 at 08:05:34PM -0800, Edward Tsang via openssl-users wrote:
> Ok here is what I tried but still complaining about unknown options
> -verify_hostname

> openssl s_client -connect google.com -CAfile etc/auth/cacert.pem 
> -verify_hostname google.com -verify_return_error

Perhaps you're using some other "openssl" that isn't from the
OpenSSL project, or an OpenSSL version that predates 1.0.2 which
introduced the "verify_hostname" option.

With the real OpenSSL 1.1.1 I get:

$ openssl s_client -connect google.com:443 -CAfile /etc/ssl/cert.pem 
-verify_hostname google.com -verify_return_error -brief 

Re: is there any working example of how to use verify_hostname in command line?

2022-03-03 Thread Viktor Dukhovni
> On 3 Mar 2022, at 6:09 pm, Edward Tsang via openssl-users 
>  wrote:
> 
> openssl s_client  -CApath . -CAfile ./cacert.pem -verify_hostname example.com
> 
> All I get is "unknown option -verify_hostname
> usage: s_client args"
> 
> Have tried combinations of that and check out of doc... really not helping.

You need to specify a server to connect to via the "-connect" option.  It
takes a hostname or IP address as a required argument, with an optional
":port" suffix.

-connect www.example.com:443
-connect 192.0.2.1:443
-connect [::1]:443
...

You may also want "-brief" and "-verify_return_error".

-- 
Viktor.



Re: Fwd: Trying to generate a RSA private key

2022-02-16 Thread Viktor Dukhovni
On Wed, Feb 16, 2022 at 11:16:03AM +0100, mary mary wrote:

> But now the issue would become different, and I'll try to share it
> possibly even if the subject changes, in case i could get advice.  I
> needed the private key for adding it in wireshark for decoding some
> encrypted messages exchanged between "my" server and a client.  If the
> private key does not exist, how we could decode the messages?

Well, now that we're past the XY problem, there's good news and bad
news.

Good news:

* If you control the server, the server's private key is typically
  stored in the server's private key file (possible same as its
  certificate file).  If the server is OpenSSL rather than Java
  based, it would typically already be in PEM format, ...

Bad news:

* Even with the server's private key, you generally can't decrypt TLS
  traffic, when, as is typical and best-practice, the negotiated
  cipher has forward-secrecy (uses DH or ECDH key exchange).

To actually decode the traffic, you'd need to configure the server or
client to record the session "master secret".  A client-side example
is discussed in:


https://resources.infosecinstitute.com/topic/decrypting-ssl-tls-traffic-with-wireshark/

Alternatively, In the blog post at:


https://blog.didierstevens.com/2020/12/14/decrypting-tls-streams-with-wireshark-part-1/

there's an example which downgrades the client TLS parameters to use at
most TLS 1.2 and RSA key transport (instead of DH), which then makes it
it possible to use the server's private key to decrypt the traffic.

-- 
Viktor.


Re: Best Practice of Creating TLS Client /Server in C?

2022-02-11 Thread Viktor Dukhovni
On Fri, Feb 11, 2022 at 09:13:05PM +, Joseph Chen via openssl-users wrote:

> Could someone point me to some good reads or C code examples for
> creating a TLS client/server with best practices?

Best practices vary between application applications.  For example, a
Web browser retrieving an HTTPS URL and an MTA SMTP client doing
opportunistic STARTTLS face rather different requirements.

In Postfix, you'll find clean, well commented code that handles
the SMTP use-case, and supports strict verification modes, but
defaults to unauthenticated TLS.  So you'd have to understand
which knobs to set to get the behaviour you want.

The upside is that the range of possible behaviours is broad, so it can
be tuned to meet the needs of most applications.  The downside, is that
there's a lot of application code there above OpenSSL to support all
those options.

In particular the resumption support depends on a peer application
service that caches serialised sessions and handles session ticket
rollover.  The SNI support uses key/value lookup tables, where the table
value is a serialised PEM file with the private key and cert chain.
Loading of private key and cert chain is atomic when both are in the
same file (file opened just once)...  All this requires custom code.

So this codebase is a "maximal viable" variant.  If you want "minimal
viable", you'll need to look elsewhere.


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_client.c

https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_server.c

-- 
Viktor.


Re: [OpenSSL 1.1.1l] Hi Team, my SSL/TLS server crashed with the attached call stack. Your advice will be highly appreciated.

2022-02-10 Thread Viktor Dukhovni
On Thu, Feb 10, 2022 at 11:48:06PM +, Ma Zhenhua wrote:
> Hi Team,
> 
> My SSL/TLS server crashed with the following call stack.
> I'm using OpenSSL 1.1.1l. I compared 1.1.1l with 1.1.1 master branch and 
> didn't find related fixes in crypto/asn1.
> Your advice will be highly appreciated.

You need to run your code under valgrind, and see where the heap is
being corrupted.  Most likely your application code freed something it
did not own, or double-freed something it did own.

-- 
VIktor.


Re: How to distinguish between encrypted/unencrypted key in a PEM file

2022-01-27 Thread Viktor Dukhovni
> On 26 Jan 2022, at 9:14 am, Bartlomiej  wrote:
> 
> I have a PEM file on the device which can contain an encrypted/non-encrypted 
> private key. When it's encrypted, it's using PBES/PBKDF. The file is accessed 
> from a C++ application which uses the OpenSSL library. If the key is 
> encrypted, then it should be PKCS#8, but checking it is PKCS#8 by using e.g. 
> `PEM_read_PKCS8` is not enough to confirm it is actually encrypted, since an 
> unencrypted key can also be stored as PKCS#8. Is there a way to check whether 
> the key is encrypted or not using OpenSSL APIs?

If nobody else can suggest anything better, and without an exhaustive
check for higher-level alternatives, I can suggest the low-level type-
agnostic PEM_read_bio(3) that reads a PEM header and data, leaving it
up to you to interpret the data as you want, based on the PEM header.

For example:

  
https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_dane.c#L1189-L1219

In the case of PKCS8, you'd be looking for:

  openssl/pem.h:# define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY"

as opposed to one of:

  openssl/pem.h:# define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
  openssl/pem.h:# define PEM_STRING_RSA  "RSA PRIVATE KEY"
  openssl/pem.h:# define PEM_STRING_DSA  "DSA PRIVATE KEY"
  openssl/pem.h:# define PEM_STRING_PKCS8INF "PRIVATE KEY"
  openssl/pem.h:# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"

-- 
Viktor.



Re: TLSv1.2 Distinguished Names Length 0 / how to set it

2022-01-19 Thread Viktor Dukhovni
On Wed, Jan 19, 2022 at 05:21:27PM +0100, Olivier Germain via openssl-users 
wrote:

> We have a requirement to implement the  Distinguished Name in the response
> received by the client. Hopefully I am ok.

More accurately, you're being asked to send a suitable non-empty list of
"Distinguished Names" in server "certificate request" extensions, when
soliciting client certificates.  This can be necessary to, e.g., solicit
client certificates from Java applications, which select the certificate
to use based on the names suggested by the server.

> How can I set in my SSL code the value for the distinguished Name?

Something along the lines of the below, which extracts the subject
DNs from a PEM file with trusted issuer (root CA) certificates:

if (CAfile) {
STACK_OF(X509_NAME) *calist = SSL_load_client_CA_file(CAfile);

if (calist != NULL)
SSL_CTX_set_client_CA_list(ctx, calist);
}

The operator of the server should be able to configure a file of trusted
client cert issuers separately from the default list of trusted issuers.
This would ideally hold just one or a few CAs actually used to issue
client certificates trusted by the server in question.

Note the documented ownership transfer:

   SSL_CTX_set_client_CA_list() sets the list of CAs sent to the client
   when requesting a client certificate for ctx. Ownership of list is
   transferred to ctx and it should not be freed by the caller.

There are other ways to construct a stack of CA X.509 names, but loading
them from a PEM file of CA certs is typically the simplest option.

-- 
Viktor.


Re: SSL_CTX_set_tlsext_ticket_key_evp_cb

2021-12-05 Thread Viktor Dukhovni
On Sun, Dec 05, 2021 at 10:35:01PM +, Jeremy Harris wrote:

> The docs at
> 
>
> https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_tlsext_ticket_key_evp_cb.html
> 
> say "returns 0 to indicate the callback function was set"
> 
> 
> The code (6d770c5ba36d43f4):
> 
>   int SSL_CTX_set_tlsext_ticket_key_evp_cb
>  (SSL_CTX *ctx, int (*fp)(SSL *, unsigned char *, unsigned char *,
>   EVP_CIPHER_CTX *, EVP_MAC_CTX *, int))
>   {
>  ctx->ext.ticket_key_evp_cb = fp;
>  return 1;
>   }
> 
> 
> (I suspect from my application code comments that
>   SSL_CTX_set_tlsext_ticket_key_cb()  may suffer the same)

Looks like you're right.  The documentation is in error, but given the
functions in question just set a pointer, I'm presently ignoring their
return values.  Still, the docs should be correct.

-- 
Viktor.


Re: Need Replacement for Deprecated function.

2021-12-05 Thread Viktor Dukhovni
On Sun, Dec 05, 2021 at 09:59:34PM +, Jeremy Harris wrote:

> >> The reference example in
> >> https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_tlsext_ticket_key_cb.html
> >>
> >> uses OSSL_MAC_PARAM_KEY and OSSL_MAC_PARAM_DIGEST.
> >>
> >> So does the code in master as of 6d770c5ba3.  But I don't see definitions
> >> for them
>
> So... how does that code compile?

It works fine for me:

https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls.h#L78

https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls.h#L87-L94

#ifndef OPENSSL_VERSION_PREREQ
#define OPENSSL_VERSION_PREREQ(m,n) 0
#endif


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_server.c#L155

#if OPENSSL_VERSION_PREREQ(3,0)
#include  /* EVP_MAC parameters */
#endif


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_server.c#L302-L339

> Where is that macro defined?



-- 
Viktor.


Re: (OpenSSL bug please fix) Re: Need Replacement for Deprecated function.

2021-12-05 Thread Viktor Dukhovni
On Sat, Dec 04, 2021 at 12:53:34AM -0500, Viktor Dukhovni wrote:

> Actually, no, not your fault at all.  The implementation in libssl is
> borked.  Please open a ticket.

I took care of opening the ticket: 
https://github.com/openssl/openssl/issues/17196

-- 
Viktor.


(OpenSSL bug please fix) Re: Need Replacement for Deprecated function.

2021-12-03 Thread Viktor Dukhovni
On Fri, Dec 03, 2021 at 07:05:43PM +, Jeremy Harris wrote:

> > EVP_PKEY_get_bits() should be equivalent to DH_bits() (for a DH
> > file). I would definitely double-check that you are not mis-loading
> > something.
> 
> OK; this was indeed my fault.

Actually, no, not your fault at all.  The implementation in libssl is
borked.  Please open a ticket.

> One minor docs item:
>https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set0_tmp_dh_pkey.html
> 
> says
>"Ownership of the dhpkey value is passed to the SSL_CTX or SSL
>object as a result of this call, and so the caller should not free
>it if the function call is succesful."

Yes, ***if the call is successful**.  Unsuccessfull calls should not
ever take ownership or have any side effects other than reporting
failure.

The implementation is:

int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey)
{
if (!ssl_security(s, SSL_SECOP_TMP_DH,
  EVP_PKEY_get_security_bits(dhpkey), 0, dhpkey)) {
ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
--Wrong!--> EVP_PKEY_free(dhpkey);
return 0;
}
EVP_PKEY_free(s->cert->dh_tmp);
s->cert->dh_tmp = dhpkey;
return 1;
}

> It's not quite clear what the onwership for a failing call is.
> Experiment shows that an EVP_free() after a fail causes a crash,
> at least for a "dh key too small" error.

This is a booby trap and needs to be fixed.  You're not the only
the one to bit by this.  This even affects existing code in OpenSSL:

ssl/ssl_conf.c:cmd_DHParameters()

...
if (cctx->ctx != NULL) {
if ((rv = SSL_CTX_set0_tmp_dh_pkey(cctx->ctx, dhpkey)) > 0)
dhpkey = NULL;
}
if (cctx->ssl != NULL) {
if ((rv = SSL_set0_tmp_dh_pkey(cctx->ssl, dhpkey)) > 0)
dhpkey = NULL;
}
 end:
EVP_PKEY_free(dhpkey);
BIO_free(in);
return rv > 0;
}

The key is freed when the call fails.  This is a bug in:

commit 163f6dc1f70f30de46a68137c36e70cae4d95cd8
Author: Matt Caswell 
Date:   Thu Oct 15 16:45:54 2020 +0100

Implement a replacement for SSL_set_tmp_dh()

-- 
Viktor.


Re: Need Replacement for Deprecated function.

2021-12-01 Thread Viktor Dukhovni
On Wed, Dec 01, 2021 at 03:54:15PM +, Jeremy Harris wrote:

> On 29/11/2021 15:10, Matt Caswell wrote:
> > SSL_CTX_set0_tmp_dh_pkey() 
> 
> "Deprecated since OpenSSL 3.0"
> 
> Is there a non-deprecated interface?

I've reworked the DH support in Postfix for OpenSSL 3.x compatibility,
without use of any deprecated interfaces.  I now prefer/recommend the
use "auto" DH parameter selection:


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_dh.c#L140-L230

-- 
Viktor.


Re: OpenSSL 1.1 on OSX

2021-11-19 Thread Viktor Dukhovni
On Sat, Nov 20, 2021 at 01:38:39PM +1100, Grahame Grieve wrote:

> I agree it's sure not a core openSSL issue. But surely lots of people
> want to use openSSL in cross platform apps and openSSL is interested
> in adoption issues?

Most of the users here are building applications that are not notarised,
and so work with the upstream builds.

> Anyway, it looks like I now have to figure out how to maintain a
> custom build of openSSL :-(

It shouldn't be too difficult to execute the build, once you've figured
out the actual requirements.  Apparently you need to make sure that
signed code has very explicit dependencies, which makes some sense, so
the libraries bundled with the application need to be built in a way
that can be verified along with the application.

My best guess is that Apple are not specifically picking on OpenSSL 
here, and similar issues would arise with any other libraries you'd
want to package with your application.  Good luck.

Feel free to share your findings.  Perhaps someone will then help
you find a way to improve on them, or to add a template to the
build to support this going forward...

-- 
Viktor.


Re: OpenSSL 1.1 on OSX

2021-11-19 Thread Viktor Dukhovni
On Sat, Nov 20, 2021 at 06:14:30AM +1100, Grahame Grieve wrote:

> And the rule for that is that all code your application uses must be
> signed either by you or by apple. I can include both openSSL dylibs in
> my .app package, and sign all that, but the way libssl loads libcrypto
> seems to not meet those rules - which specifically exclude symlinking
> and which specifically prohibit loading libcrypto without specifying a
> specific version.

Which means you need to build libssl in such a way that it depends
explicitly on the corresponding versioned build of libcrypto.  That is
you'll need to tweak the Darwin Configuration template to specify some
additional linker options or other relevant settings.

This is not an Apple Developer community, you're perhaps better off
asking on an Apple forum, this is not an OpenSSL issue.

You have

* Application X ->
* Needs Library Y ->
* Needs Library Z

you need to know how to build Library Y so that it is compatible with
Apple's packaging requirements.

Perhaps someone has done that for MacOS, but they might not be reading
this list...

-- 
Viktor.


Re: OpenSSL 1.1 on OSX

2021-11-19 Thread Viktor Dukhovni
On Fri, Nov 19, 2021 at 05:36:24PM +1100, Grahame Grieve wrote:

> It's very definitely something active that OSX is doing. Here's an OSX
> error generated:
> 
> System Integrity Protection: enabled
> 
> Crashed Thread:0  Dispatch queue: com.apple.main-thread
> 
> Exception Type:EXC_CRASH (SIGABRT)
> Exception Codes:   0x, 0x
> Exception Note:EXC_CORPSE_NOTIFY
> 
> Application Specific Information:
> abort() called
> Invalid dylib load. Clients should not load the unversioned libcrypto
> dylib as it does not have a stable ABI.

Well, I think that's evidence of confusion about which "libcrypto" to
load.  It sure seems that you're trying to load the default system
libcrypto, not the one in the application bundle.

You should probably arrange to "salt" the names of the libssl and
libcrypto libraries used by your application, so that there can't
be any confusion with the platform's libssl and libcrypto.

May also need to do something to avoid symbol name collisions, but I
haven't looked into how that works on Darwin, so can't offer specific
advice.

-- 
Viktor.


Re: OpenSSL 1.1 on OSX

2021-11-18 Thread Viktor Dukhovni
On Fri, Nov 19, 2021 at 04:31:26PM +1100, Grahame Grieve wrote:

> I'm trying to get my application that uses openSSL 1.1 running on OSX. I've
> installed them using homebrew, but I can't get past Apple's gates around
> blocking use of openSSL.

I don't think they're actively doing blocking here, though I could
perhaps be wrong...

> I've copied both dylibs into my app /Contents/MacOS folder, and signed
> both of them, and I load them from the that location, but OSX still
> blocks loading.

More accurately I think, the libraries fail to load.

> It actually blocks loading libssl.1.1.dylib, with a message about libcrypto
> - presumably libssl has a non-version dependence on libcrypto that OSX is
> blocking?

The problem is likely that "libssl" not built to locate "libcrypto"
relative to its own location, but rather expects to find it at a fixed
location.  This would be some MacOS-specific instance of setting the
runpath to $ORIGIN on ELF systems.

With OpenSSL installed at a fixed location, OpenSSL is working just
fine for me (and of course in HomeBrew, ...).

So the issue most probably the inability of "libssl.dylib" to find
"libcrypt.dylib", not because of some policy enforcement by Apple's
evil overlords, but simply because the runtime linker does not
expect to look in the location where you have libcrypt installed.

The only thing that gives me some pause is Whether or not notarisation
also complicates relocation, but presumably applications can ship
shared libraries with the application code without running into
major obstacles.

Perhaps the presence of LibreSSL on MacOS is another complication,
but that libssl and libcrypt should have different version suffixes,
and should not get in the way, provided that MacOS has something
akin to symbol versioning, to allow separate API versions of the
same library to exist in a process side by side without getting
in each other's way.

If the symbol namespace in MacOS is "flat", then you may indeed
run into trouble because of symbol conflicts between the real
OpenSSL and the LibreSSL fork.

Good luck.

-- 
Viktor.


Re: “EC PUBLIC KEY”

2021-11-17 Thread Viktor Dukhovni
On Wed, Nov 17, 2021 at 11:11:58AM -0500, Felipe Gasper wrote:

> Does OpenSSL intend to handle EC public keys that in PEM begin “BEGIN EC 
> PUBLIC KEY”?

I doubt it, but there is:

$ openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:prime256v1 | 
openssl ec 
read EC key
writing EC key
-BEGIN EC PRIVATE KEY-
MHcCAQEEIDvaIBqlCepZmpLChB7wW1aMbecIsw79AftoaZttrdaEoAoGCCqGSM49
AwEHoUQDQgAE0XMziiLRVpKP/jNklqzZqejJKgcK+TQ9wynz3etCRqOq8hzW24VG
PY+ORzD9LJqTMQF7NJytxR4vcCVcrpuXGg==
-END EC PRIVATE KEY-

There is no correspoding EC-specific PEM public key form in OpenSSL.
You should be using the algorithm agnostic formats.

-- 
Viktor.


Re: “EC PUBLIC KEY”

2021-11-17 Thread Viktor Dukhovni
On Wed, Nov 17, 2021 at 10:37:01PM -0500, Felipe Gasper wrote:

> It came from my own (very incomplete) crypto implementation.
> (https://github.com/FGasper/p5-Crypt-Perl) It looks like I just had
> the wrong idea about EC public keys back-when.
> 
> Funny thing is that the “EC PUBLIC KEY” that I was outputting is the
> same structure as a normal SPKI ECC public key; I just had the wrong
> header (and, when parsing, thought there were 2 formats to check for).

OpenSSL source in include/openssl/pem.h contains:

# define PEM_STRING_X509_OLD "X509 CERTIFICATE"
# define PEM_STRING_X509 "CERTIFICATE"
# define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
# define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
# define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
# define PEM_STRING_X509_CRL "X509 CRL"
# define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
# define PEM_STRING_PUBLIC   "PUBLIC KEY"
# define PEM_STRING_RSA  "RSA PRIVATE KEY"
# define PEM_STRING_RSA_PUBLIC   "RSA PUBLIC KEY"
# define PEM_STRING_DSA  "DSA PRIVATE KEY"
# define PEM_STRING_DSA_PUBLIC   "DSA PUBLIC KEY"
# define PEM_STRING_PKCS7"PKCS7"
# define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
# define PEM_STRING_PKCS8"ENCRYPTED PRIVATE KEY"
# define PEM_STRING_PKCS8INF "PRIVATE KEY"
# define PEM_STRING_DHPARAMS "DH PARAMETERS"
# define PEM_STRING_DHXPARAMS"X9.42 DH PARAMETERS"
# define PEM_STRING_SSL_SESSION  "SSL SESSION PARAMETERS"
# define PEM_STRING_DSAPARAMS"DSA PARAMETERS"
# define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
# define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
# define PEM_STRING_PARAMETERS   "PARAMETERS"
# define PEM_STRING_CMS  "CMS"

The PEM formats supported should be at most these.

-- 
Viktor.


Re: X509_get_pubkey() in OpenSSL 3.0?

2021-11-03 Thread Viktor Dukhovni
On Wed, Nov 03, 2021 at 08:32:43PM +, Jason Schultz wrote:

> To summarize, at application start time I read in all of the
> certificates in /etc/ssl/certs/ to a trusted store created with
> X509_STORE_new().
> 
> When getting ready to "start" a server (again, leaving a lot of
> specifics out to avoid getting bogged down in details), I'm doing the
> processing in the previous messages on this thread. Here are the API
> calls again, with the changes previously discussed:
> 
> ctx = SSL_CTX_new_ex(non_fips_libctx, NULL, TLS_method());
> SSL_CTX_use_PrivateKey_file(ctx,,SSL_FILETYPE_PEM);
> SSL_CTX_use_certificate_file(ctx,,SSL_FILETYPE_PEM);
> SSL_CTX_check_private_key(ctx);
> mycert = SSL_CTX_get0_certificate(ctx);
> pkey = X509_get_pubkey(mycert);
> 
>  After that's done, I make several OpenSSL calls to get things set up the way 
> I want:
> 
> param = X509_VERIFY_PARAM_new();
> X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_PARTIAL_CHAIN);
> X509_STORE_set1_param(ssl_trusted_certs, param);
> X509_VERIFY_PARAM_free(param);
> 
> I call these to treat intermediate certs as trust-anchors, so I can
> trust an intermediate certificate; ssl_trusted_certs is the
> aforementioned X509_STORE.

I am puzzled as to you working so hard (writing a bunch of low-level
trust-store and chain construction code) to construct at runtime, what
could be created statically at chain file construction time.  Especially
if you stick with best practice and keep certificate lifetimes
reasonably short (~90 days or less, not years).  The certificate chain
file constructed at the time the certificate is issued should work
unchanged for the lifetime of the certificate, and the server
applications can avoid having to execute any chain construction or
verification code.

Yes, you're asking somewhat "interesting" questions, in that, e.g., I am
not up to speed on all the changes in 3.0.0, and perhaps there are
indeed some issues around legacy SHA1 signatures, but I do suspect that
a more productive use of your time is likely to reconsider the decision
to work at such a low layer.  It may be wiser to find a way to "unask"
the question, i.e. make it moot, by avoiding rather than solving the
problem.

> I'm not clear on if the calls I've added to
> SSL_CTX_get0_certificate(ctx) and X509_get_pubkey(), the latter of
> which was being used before, are what's causing the problem. The
> OpenSSL error queue shows the following on the
> SSL_CTX_build_cert_chain() failure:
> 
> 00B741558E7F:error:0308010C:digital envelope routines:(unknown 
> function):unsupported:crypto/evp/evp_fetch.c:346:Global default library 
> context, Algorithm (SHA1 : 96), Properties ()
> 00B741558E7F:error:0372:digital envelope routines:(unknown 
> function):decode error:crypto/x509/x_pubkey.c:444:
> 00B741558E7F:error:0372:digital envelope routines:(unknown 
> function):decode error:crypto/x509/x_pubkey.c:444:
> 00B741558E7F:error:0580006C:x509 certificate routines:(unknown 
> function):unable to get certs public key:crypto/x509/x509_vfy.c:1986:
> 00B741558E7F:error:0A86:SSL routines:(unknown function):certificate 
> verify failed:ssl/ssl_cert.c:905:Verify error:unspecified certificate 
> verification error

I haven't seen these before, your guess is as good as mine.

-- 
Viktor.


Re: X509_get_pubkey() in OpenSSL 3.0?

2021-11-03 Thread Viktor Dukhovni
On Wed, Nov 03, 2021 at 12:38:51PM +, Jason Schultz wrote:

> In any case, things appear to be working now, but I'm hitting an issue
> later on when calling SSL_CTX_build_cert_chain(). I working on
> debugging that, I may have to start yet another thread later.

Your mistake is probably in loading a certificate file, rather than
a certificate chain file.  With the latter, you'd also pick up any
associated intermediate issuer certificates (e.g. from certbot's
"fullchain.pem").

With the intermediate certificates thus obtained, you're far more likely
to be able to verify the completely server's chain relative to some
trust store with exclusively or mostly just a bunch of root CAs.

I'd in fact recommend not rebuilding the provided chain, but just
observing whether it is complete, the user may have good reasons
for going with some alternative sequence of issuer CAs (e.g. to
support old Android devices, as with e.g. current Let's Encrypt
redundant cross cert).  Therefore, per:

SSL_CTX_build_cert_chain() builds the certificate chain for ctx.
Normally this uses the chain store or the verify store if the chain
store is not set. If the function is successful the built chain will
replace any existing chain. The flags parameter can be set to
SSL_BUILD_CHAIN_FLAG_UNTRUSTED to use existing chain certificates as
untrusted CAs, SSL_BUILD_CHAIN_FLAG_NO_ROOT to omit the root CA from
the built chain, SSL_BUILD_CHAIN_FLAG_CHECK to use all existing
chain certificates only to build the chain (effectively sanity
checking and rearranging them if necessary), the flag
SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR ignores any errors during
verification: if flag SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR is also set
verification errors are cleared from the error queue. Details of the
chain building process are described in "Certification Path
Building" in openssl-verification-options(1).

I'd set the flags to:

SSL_BUILD_CHAIN_FLAG_UNTRUSTED | SSL_BUILD_CHAIN_FLAG_CHECK

if you're sure the service is not DANE TLSA enabled, and there's
definitely good reason to omit the root CA from the chain, or
you provide a configuration to let the user make the choice,
you can also add:

SSL_BUILD_CHAIN_FLAG_NO_ROOT

which is often, but not always appropriate, and should ideally
not be unconditionally hardcoded.

Be sure to clear the error queue before starting, and after reporting
any errors observed.

-- 
Viktor.


Re: X509_get_pubkey() in OpenSSL 3.0?

2021-11-02 Thread Viktor Dukhovni
On Tue, Nov 02, 2021 at 08:28:01PM +, Jason Schultz wrote:
> Victor-
> 
> I can't seem to find any documentation on SSL_CTX_get0_privatekey(),
> but by the name of it, it sounds like it's getting the private key;
> I'm trying to get the public key.

It does appear to be "under-documented" (i.e. not at all), perhaps
that could be addressed.  Note that you can get a public key from
the private key.

> That said, I should probably explain more of why I'm doing what I'm
> doing, because there may be an easier way all together. Basically, we
> allow configuring RSA or EC certificates/keys, and I want to get the
> public key so I can check the type of key with a call to:
> 
>  EVP_PKEY_base_id(pubkey);

Which you can equally get from the private key, but there's also:

SSL_CTX_get0_certificate(sadly also "under-documented")

which means that you certainly don't need to read the PEM file again.

> So maybe there's a better way? After I call:
> 
>  SSL_CTX_use_certificate_file(ctx,,SSL_FILETYPE_PEM);
> 
> Is there an API I can call passing the ctx that will tell me what type
> of certificate is in use for that ctx? Or something else along those
> lines?

Also once you have an (SSL *) handle you can call SSL_get_certificate(3)
which is documented, and proceed from there.

> It's very possible I'm overcomplicating things with the fopen(),
> PEM_read_X509(), X509_get_pubkey() sequence, so any suggestions on how
> to better accomplish this verification are welcome.

Yes.  Query the data you already have in memory.

Note that a context can be configured with *both* an RSA certificate
chain *and* an EC certificate chain.  The above functions return the one
most recently loaded, but a handshake with a peer may select one of
the other chains.

Most applications only load keys for just one algorithm, but in general
more may be present.

It is surprising that you care which algorithm is in cert/keys.  So
long as it loads, why does it matter?

If you want to log data for each handshake, at that point you can use
SSL_get_certificate(3) for the cert actually selected by this handshake
on the local end:


https://github.com/vdukhovni/postfix/blob/master/postfix/src/tls/tls_misc.c#L950-L953

-- 
Viktor.


Re: X509_get_pubkey() in OpenSSL 3.0?

2021-11-02 Thread Viktor Dukhovni
On Tue, Nov 02, 2021 at 07:42:15PM +, Jason Schultz wrote:

> I thought I should start a new thread since this question was buried in my 
> "FIPS" thread and I dont' think it has anything to do with FIPS and OpenSSL 
> providers. I'm hitting another problem that I think is related to the 
> migration to OpenSSL 3.0, as this code works with OpenSSL 1.1.1 (and 1.0.2 
> before it). When looking at the documentation pages for 1.1.1 vs 3.0, I'm not 
> seeing any differences between the OpenSSL APIs I'm calling in the 2 
> different release levels.
> 
> Here is the sequence, I'm basically setting up my certificate and private 
> key, both in PEM format, for the server, then I need to extract some 
> information from them:
> 
> ctx = SSL_CTX_new_ex(non_fips_libctx, NULL, TLS_method());
> SSL_CTX_use_PrivateKey_file(ctx,,SSL_FILETYPE_PEM);
> SSL_CTX_use_certificate_file(ctx,,SSL_FILETYPE_PEM);
> SSL_CTX_check_private_key(ctx);
> fp = fopen(, "r");
> mycert = PEM_read_X509(fp, NULL, 0, NULL);
> pkey = X509_get_pubkey(mycert);

Without addressing the question of why you're unable to get the public
key handle from the certificate, why not just:

 pkey = SSL_CTX_get0_privatekey(ctx){

and skip reading the cert again?

-- 
Viktor.


Re: Client side session handling

2021-10-13 Thread Viktor Dukhovni
On Wed, Oct 13, 2021 at 11:57:14PM +, Jason Schultz wrote:

> I'm somewhat familiar with the reference count stuff from reading the
> doc on these (and other) functions. But it sounds like the behavior
> I'm seeing is expected, and OpenSSL is doing the actual free of the
> SSL_SESSION when the SSL_CTX is freed.

That's plausibly the case, barring bugs in your application, yes
either freeing some handle too many or too few times.

-- 
Viktor.


Re: Client side session handling

2021-10-13 Thread Viktor Dukhovni
On Wed, Oct 13, 2021 at 02:32:10PM +, Jason Schultz wrote:

> The confusing part is that given everything above, when I free the
> SSL_CTX associated with these connections/sessions, I see the remove
> callback function get called again for client-side sessions that I
> already called SSL_SESSION_free() on. Is this normal behavior? Is
> there something else I’m missing?

OpenSSL SSL_SESSSIONS are reference-counted.  This is typical of a
number of similar sufficiently complex structures for which it makes
more sense to bump a reference counter than to make a copy.

The SSL_SESSION_free(3), X509_free(), and various other calls just
decrement the reference counter, with the object only actually freed
once the counter reaches 0.

Various functions (though not all, as documented for each function) that
return such objects to the application increment the refernce counter
(say initially from 1 to 2), and the application is then responsible for
decrementing it.  THe object is finally freed when any internal
reference is released (if that happens last).

The internal store of client-side sessions is not used by OpenSSL
for anything other than asking the application to remove sessions
when the cache exceeds some limit, the application still needs its
own cache lookup mechanism and its own separat cache (of the same
shared by reference count underlying objects), all the OpenSSL
cache is doing for you is "helping" you keep the cache size bounded.

In Postfix we serialise session objects into a cache in which they
are not shared with OpenSSL and manage expunging stale sessions
independently of OpenSSL.  We therefore tell OpenSSL to not bother
maintaining an internal cache.

SSL_CTX_set_session_cache_mode(client_ctx,
   SSL_SESS_CACHE_CLIENT |
   SSL_SESS_CACHE_NO_INTERNAL_STORE |
   SSL_SESS_CACHE_NO_AUTO_CLEAR);

All the work of managing session storage and lookup is done by
the callback:

SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb);

There's no remove callback, we handle cache management outside OpenSSL..

-- 
Viktor.


[Mostly off-topic] Build RSA private key from (p,q,e) triple

2021-10-08 Thread Viktor Dukhovni
Every once in a while IIRC there are posts asking about how to create an
RSA private key from the two prime factors (p and q) and exponent.

Though there are surely simple examples in Python or Perl, I happened to
write on in Haskell.  Here it is for posterity (Main.hs and .cabal spec).
Input is from stdin, with each of p, q and e in either decimal or
0x-prefixed hex on separate lines.  10 lines of boilerplate and 3 lines
of code:

---
Main.hs:

module Main (main) where
import qualified Data.ByteString as B
import Crypto.Number.Basic (numBytes)
import Crypto.PubKey.RSA (generateWith)
import Data.ASN1.BinaryEncoding (DER(DER))
import Data.ASN1.Encoding (encodeASN1')
import Data.ASN1.Types (toASN1)
import Data.X509 (PrivKey(PrivKeyRSA))

main :: IO ()
main = do
(p, q, e) <- (,,) <$> readLn <*> readLn <*> readLn
mapM_ (B.putStr . toDER) $ generateWith (p,q) (numBytes (p*q)) e
  where toDER = encodeASN1' DER . flip toASN1 [] . PrivKeyRSA . snd
---
pqe.cabal:

cabal-version:  2.4
name:   pqe
version:0.1.0.0

executable pqe
main-is:  Main.hs
build-depends:base >= 4.14 && < 5
, asn1-encoding ^>= 0.9
, asn1-types ^>= 0.3
, bytestring >= 0.10 && < 0.12
, cryptonite ^>= 0.29
, x509 ^>= 1.7
---

The output is legacy RSA DER, but can be converted to PKCS8 PEM by
piping it to "openssl pkey -inform DER" (optionally adding a passphrase, ...):

If the program fails to read the (p, q, e) values it will exit with an
error.  If these fail to yield a valid key it will produce no output.

Silly little example with (p, q, e) = (29, 23, 3):

$ printf '%s\n%s\n%s\n' 29 23 3 | cabal run -v0 | openssl pkey -inform DER 
-text
-BEGIN PRIVATE KEY-
MDMCAQAwDQYJKoZIhvcNAQEBBQAEHzAdAgEAAgICmwIBAwICAZsCAR0CARcCARMC
AQ8CARg=
-END PRIVATE KEY-
RSA Private-Key: (10 bit, 2 primes)
modulus: 667 (0x29b)
publicExponent: 3 (0x3)
privateExponent: 411 (0x19b)
prime1: 29 (0x1d)
prime2: 23 (0x17)
exponent1: 19 (0x13)
exponent2: 15 (0xf)
coefficient: 24 (0x18)

More realistic example with a throw-away 2048-bit RSA key:

$ cabal run -v0 < 
0xfb9e9c8a90615c9edd4870b2eb434a76abcf8ffe22d0764fdf9c921523b561b25edd2ebc547836ab2e40ba7229e2f023dde7f2209c0d8ba548d442a7e9ee415f97714a1f6cdd53aa6e67b2d020287c4b2fe730355e04fb25f93b078bf41a7af8e6700c4cf2e2407720e19f90464d8e9cb4d70d960c23309b3228b5510e550833
> 
0xe779cd8cc5a7d3ae41cfe4869598832aeec3e26b0919743486f9e5d0cf1e00826a6ffe865d347e35b0c55cfcef32515b6850d552be53b5af335c3e0a8062a5d4e063b33071365f3faac29e44990f83f2994bb93cf45a0c09a4fef13e441128ebe9c36ef2dc32dddffc99ed7d1ad7bc0232c1692ff3ee466c6bcb612074d54187
> 0x10001
> EOF
-BEGIN PRIVATE KEY-
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDjg9dBZiSs+s4w
JZgYVNknm6TW4vh8lONdEOe6lquTYDciA53K00dededDmjwvQYMHbsoA6TyC/5O4
r8T21GaXwdQHHOsMou9JcyU+5Sun350I2lh7sDeJ0Ipz/nn3RwitXBHeWMLz1MLD
Arutm0Wc1ZFC0ri2sxXTXsoYYc4mqMCBp0C8sPkQCAkheCsOBkWHaYK6vlsOXK/V
O1LMaxqawYZamfPQ7Nznh3rVjVY2v/zlEtHqtNbzjMu6cJrLKgzYzhfxWMO/aNA/
QhjZoUjSNFTP5VwhpyP7EFQlrMQFLb4vumboj5G66jiHWk/SeDn5LxhLyFbnijSe
ADkUW0XlAgMBAAECggEBALnNBLCrCw6dMF/Pg9tzB3i6Oi8nYsjTCq8JTEVsIKiV
rdDAZU+rpaA152yk+7uX47rhNmTyFPHiaLAuE0uEgFg0+cPpUOeb9JDmUSeBHlrV
WjhNoG86pNCOl1NNIivYPfTduNX9ZRCd04RQqhaINJx1KVEKJ8FElXFt+ttYnHOi
WDVGtpXYNjM+6s/R6UpkSTL0SpVjY7RjQMXZ8P3uUrAru/4UQba0ZcZIbHXSQO5J
MCWa05pIOGuTs0C/2nUuO+lN5fqz6Cv8G+YlQjp54MUcjK3XisP/vx9GC4uvt3XT
ik8y/+plvvBk1nwO8ehJ01bUzgokWNkePI58lfczqu0CgYEA+56cipBhXJ7dSHCy
60NKdqvPj/4i0HZP35ySFSO1YbJe3S68VHg2qy5AunIp4vAj3efyIJwNi6VI1EKn
6e5BX5dxSh9s3VOqbmey0CAofEsv5zA1XgT7Jfk7B4v0Gnr45nAMTPLiQHcg4Z+Q
Rk2OnLTXDZYMIzCbMii1UQ5VCDMCgYEA53nNjMWn065Bz+SGlZiDKu7D4msJGXQ0
hvnl0M8eAIJqb/6GXTR+NbDFXPzvMlFbaFDVUr5Tta8zXD4KgGKl1OBjszBxNl8/
qsKeRJkPg/KZS7k89FoMCaT+8T5EESjr6cNu8twy3d/8me19Gte8AjLBaS/z7kZs
a8thIHTVQYcCgYEAw1apdLENxNfYNmq3nAkLgAF2C/VhlbCj5ZcpmZu1LnlJSDEG
KBWDa3Vm7te+SN3hGl79C+/aXDUeyxpMPUGoIsvxOXgYDeLsBvYeTZEJnSTJtZMp
eyomx54rA3rVMNGS9WK7SemtWBqjvkUfvlRriKCj63o3RgJwGYqc6KZVwR0CgYEA
uNfNSrKz+BfZOhg1WNR3Oht8lRwAIjFnmLmJyZr7TFDYiiJoTZmTh3Bnyn+4yyeo
pL6X+wE9e4Iys2BfpnIgFsQxGXB/l3msL8JF/GV1vFpIC+4aPM6DelgltaORW1qg
OQX1XT516DPrVUgOdRb9bYv2YvcGBap6/gFkyDRD75UCgYAkruxwtnikj5hKlaSJ
/OIXvjj3VmbPpJtSFbvadTCTzBxWCWjaBQHf0nKsbNRa/9V60y44L0EVnC40Udj6
r6LxLw66+GHJQPfhW5bnFIpUksIDC8fF9gUyc+C0AI3OJR+jrmlXNAllqoNIEsYd
mkdZ2BxLEY0/fmBftSO3d/dC+A==
-END PRIVATE KEY-

-- 
Viktor.


Re: OpenSSL 3.0.0 enabling SSLv3 support

2021-10-07 Thread Viktor Dukhovni
On Thu, Oct 07, 2021 at 09:38:30AM -0500, Mark Hack wrote:

> Added to all the weaknesses in SSLv3, the only supported cipher suites
> are either vulnerable  or deprecated and not advisable.

If we set aside browsers where CBC padding oracles are a problem, the
below are in practice still reasonably strong in most other
applications.

ECDHE-RSA-AES256-SHASSLv3 Kx=ECDH Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256)  Mac=SHA1
DHE-RSA-AES256-SHA  SSLv3 Kx=DH   Au=RSA  Enc=AES(256)  Mac=SHA1
AES256-SHA  SSLv3 Kx=RSA  Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-RSA-AES128-SHASSLv3 Kx=ECDH Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128)  Mac=SHA1
DHE-RSA-AES128-SHA  SSLv3 Kx=DH   Au=RSA  Enc=AES(128)  Mac=SHA1
AES128-SHA  SSLv3 Kx=RSA  Au=RSA  Enc=AES(128)  Mac=SHA1

And yet, SSLv3 should still not be used, because it does not support
extensions, so no SNI, no protection against insecure renegotiation, ...

-- 
Viktor.


Re: OpenSSL 3.0.0 enabling SSLv3 support

2021-10-05 Thread Viktor Dukhovni
On Tue, Oct 05, 2021 at 03:49:48PM -0700, Kory Hamzeh wrote:

> It looks like SSLv3 is not built by default in OpenSSL 3.0.0. At least
> SSLv3_method() is not define, and looking at the conditional
> compilation of that function, it makes sense.
> 
> What command line option do I pass the Configure script to enable it?
> I tried enable-sslv3 and  enable-SSLv3. It complained about both. I
> need to compile some old code (Python 2.7) which we will abandon soon.

Don't enable SSLv3 in OpenSSL 3.0, that's not doing anyone a favour.
Better to instead build the code in question against OpenSSL 1.1.1, if
SSLv3 actually needs to be *used*.  It is not a problem to install both
OpenSSL 1.1.1 and OpenSSL 3.0 side-by-side (shared libraries) on systems
with support for symbol versioning.

If the only purpose of SSLv3 is to get code to compile, that will not
in fact ever run, or that can reasonably just return an error when
it runs, you can enable the method stubs, without enabling support
for the protocol:

./Configure enable-ssl3-method ...

The default is to disable both "ssl3" and "ssl3-protocol" and I would
strongly encourage you to not enable both.  Nobody should be actually
using SSLv3 anymore, but exporting function stubs that will error out
makes some sense if required to support toolkits that wrap the OpenSSL
API and still want to expose SSLv3 methods.

-- 
Viktor.


Re: SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

2021-10-03 Thread Viktor Dukhovni
On Sun, Oct 03, 2021 at 09:33:29PM +0200, Alex Robuchon wrote:

> > Not quite, a candidate chain is constructed from whatever certificates the
> > peer (server in your case) provided, and then passed to the callback with
> > "preverify_ok" set to false (for the top certificate), because the chain is
> > not trusted.
> 
> This confuses me a little bit because I thought the callback function set
> with *SSL_set_verify* would have the "trusted first" valid chain.

But there is no trust store configured, so trust first is a no-op.
The constructed chain consists entirely of certificates from the
peer, and last certificate in the chain (the ultimate issuing CA)
is still not trusted, so preverify_ok = 0.


> Are you sure you are not speaking as if eventmachine was using the
> *SSL_CTX_set_cert_verify_callback* ?

I rewrote the OpenSSL chain construction code for OpenSSL 1.1.0.  Yes, I
am sure.

> - *build_chain* that will apply the trusted first algorithm and replace the
> certificate chain passed by the server with the valid one ( if found ).

The code in eventmachine does not configure any trusted certificates for
the SSL_CTX handles used to create the SSL connections.  So
trusted-first is a no-op.

> - *internal_verify *which now has the new chain and will call *verify_callback
> *( the callback function passed to SSL_set_verify ) for every certificate
> in this new chain in reverse order.

You don't have to explain the code to me. :-)

> > But given all the evidence before me, I'd want to delete that code and
> > never see it again.
> 
> I hear you :).

That code is beyond repair, it needs to be thrown out, and replaced with
ground up by the book TLS connection establishment.

#1. No compiled in private keys

#2. Configure the SSL_CTX with the desired list of trust anchors

#3. Reuse the SSL_CTX for multiple connections that share the same
trust and other general settings

#4. Prior to SSL_connect(), tell the SSL library what hostname you want
to verify via SSL_set1_host(3).  Let OpenSSL do all the heavy
lifting of certificate and name checks.

#5. DO NOT attempt to override certificate chain verifiction in the
verify callback.  Use the verify callback only for logging or
similar diagnostic purposes.

#6. Return "preverify_ok" unmodified, unless your application is doing
opportunistic unauthenticated TLS, or wants to complete the
handshake even on verification failure, and then gracefully tear
down the application-layer session with the peer (after checking the
verification status at connection completion).

If preverify_ok is false (0), OpenSSL chain verification failed,
your application is unlikely to do better.  Return 0, and the
TLS handshake will be aborted, you can log the error reason,
chain depth, ... in the verify callback.

-- 
Viktor.


Re: SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

2021-10-03 Thread Viktor Dukhovni
> On 3 Oct 2021, at 12:33 pm, Alex Robuchon  
> wrote:
> 
> So I suppose openssl skip the part that is supposed to build the chain when 
> no store is configured.

Not quite, a candidate chain is constructed from whatever certificates
the peer (server in your case) provided, and then passed to the callback
with "preverify_ok" set to false (for the top certificate), because the
chain is not trusted.

But the evenmachine callback ignores "preverify_ok" and goes through the
motions of doing some sort of verification of each certificate.

Ultimately, it will attempt to "verify" the leaf certificate, and if it
can somehow do a fair job of that (by building its own chain, checking
all the signatures, doing the name checks (for a name that does not
appear to be passed to the verification function), then in theory
the checks at depths above 0 are just silly opportunities to fail and
the EE cert check would be enough.

But given all the evidence before me, I'd want to delete that code and
never see it again.

-- 
Viktor.



Re: SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

2021-10-03 Thread Viktor Dukhovni
On Sun, Oct 03, 2021 at 01:54:44PM +0200, Alex Robuchon wrote:

> Thanks for the detailed answer.
> 
> From strace I can see that I'm using /lib/x86_64-linux-gnu/libssl.so.1.1
> 
> When I use the eventmachine lib that uses the wrong cert chain I can see
> with strace :

Run as far away from eventmachine as you can.  The very first thing you
see in the code is a compiled in default "private key" (for all the
world to share).


https://github.com/eventmachine/eventmachine/blob/5cac87805f26b5cdc29eca713871c3374131d786/ext/ssl.cpp#L30-L123

Though applications can override these, and supply actual private keys,
it does not get better from there...  The comments in the code show the
author punting on understanding the OpenSSL API and just guessing what
to do.

Indeed the code creates SSL_CTX objects without specifying either the
default or explicit trust stores.

The real disaster is in:


https://github.com/eventmachine/eventmachine/blob/5cac87805f26b5cdc29eca713871c3374131d786/ext/ssl.cpp#L675-L698

with a completely broken SSL verification callback, that completely
ignores all errors from the chain construction and signature
verification code, and just attempts to "verify" each certificate in
*isolation*.


https://github.com/eventmachine/eventmachine/blob/5cac87805f26b5cdc29eca713871c3374131d786/ext/ssl.cpp#L693-L697

This means:

* No verification of chain signatures
* No verification of path constraints
* No verification of name constraints
* No hostname checks.
* ...

This code was written by someone too clueless to know what they're
doing and too lazy to bother to learn.  DO NOT USE IT.

Do whatever it takes to never rely on this code again.  Even abandon
Ruby if that's what it takes...

-- 
Viktor.


Re: SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

2021-10-02 Thread Viktor Dukhovni
On Sat, Oct 02, 2021 at 06:21:00PM +0100, Angus Robertson - Magenta Systems Ltd 
wrote:

> > Yes.  To make things even more complex, a few sites also have an 
> > older version of R3 that is directly signed by the DST root:
> > 
> >  - leaf <- R3 <- DST Root CA X3 (self-signed)
> > 
> > but that's far from common at this point.
> 
> That old R3 [CA] was issued last winter and got installed in Windows
> Server 2018 intermediate stores then, and was still being sent out on
> 29th and 30th, despite expiring on 29th.  

Not just Windows, at least one Unix system running Postfix is still
vending a chain with the R3 signed by DST that expired on 2021-09-29:

issuer=O = Digital Signature Trust Co., CN = DST Root CA X3
subject=C = US, O = Let's Encrypt, CN = R3
notBefore=Oct  7 19:21:40 2020 GMT
notAfter=Sep 29 19:21:40 2021 GMT
SHA256 
Fingerprint=73:0C:1B:DC:D8:5F:57:CE:5D:C0:BB:A7:33:E5:F1:BA:5A:92:5B:2A:77:1D:64:0A:26:F7:A4:54:22:4D:AD:3B
-BEGIN CERTIFICATE-
MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIwMTAwNzE5MjE0MFoXDTIxMDkyOTE5MjE0MFow
MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT
AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs
jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp
Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB
U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7
gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel
/xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R
oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p
ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE
p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE
AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu
Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0
LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf
r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B
AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH
ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8
S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL
qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p
O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw
UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg==
-END CERTIFICATE-

The EE (depth 0 server) certificate is not expired, and yet somehow the
server is building a chain with a fresh leaf cert, and a rather stale
issuer CA.

It verifies via the DANE implementation in OpenSSL, because its "2 1 1"
record with a fresh RRSIG specifies the R3 CA as trusted, and its
expiration date is not in scope since it was signed by an entity outside
the effective trust chain.

Validation would fail for the same chain with WebPKI, unless there's a
new improved R3 in the trust store (not just the roots).

My DANE survey scan engine checks trust-anchor cert expiration date,
even when an intermediate CA, mostly because the implementation is
done that way, but I can retroactively justify it because it makes
sense to be more strict in tools that look for potential issues.

Implementations other than OpenSSL might similarly reject such a
suboptimal chain.

-- 
Viktor.


Re: SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

2021-10-02 Thread Viktor Dukhovni
On Sat, Oct 02, 2021 at 05:24:26PM +0200, Alex Robuchon wrote:

> The project has a callback function registered with SSL_CTX_set_verify
> and failed to verify DST Root CA X3 since it expired.

That happens when either:

* The configured trust store (perhaps not the default system
  trust store) does not contain the ISRG root CA certificate

* The version of OpenSSL used (perhaps indirectly via some
  library that is linked with an older OpenSSL) is 1.0.x
  rather than 1.1.0 or later.

> From what I understood about the let's encrypt certificate chain, R3 is
> cross signed and two chained could be built:
> 
>- leaf <- R3 <- ISRG Root X1 <- DST Root CA X3 (self-signed)
>- leaf <- R3 <- ISRG Root X1 (self-signed)

Yes.  To make things even more complex, a few sites also have an older
version of R3 that is directly signed by the DST root:

 - leaf <- R3 <- DST Root CA X3 (self-signed)

but that's far from common at this point.

> The servers by default return the first chain but from what I
> understand depending on the openssl version/flags it should  use the
> second path if ISRG Root X1 is in the store

Yes, see above.

> My config :
> openssl version : OpenSSL 1.1.1f  31 Mar 2020

Are you sure there are no other versions of OpenSSL also installed on
the system, and/or no other trust stores that the application in
question might be using instead of the default system store?

An "strace" of the process should show which shared objects it is
loading, and which cert store files it is opening...  Best to not
post the complete strace output here, it may contain sensitive
data.  Try to interpret it on your end and post your findings.

> ISRG Root X1 self signed is in my cert store.

This presumes a *singular* "trust store", but the application could
easily be looking elsewhere.

> So from what I understand, trusted first is default in this version of
> openssl and the second path should be taken.

Yes, per the pre-requisite conditions.

> For the record s_client can valide the second path on my machine :
> $ echo | openssl s_client -connect retouche-pro.ch:443 -name retouche-pro.ch 
> -servername retouche-pro.ch
> CONNECTED(0003)
> depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
> verify return:1
> depth=1 C = US, O = Let's Encrypt, CN = R3
> verify return:1
> depth=0 CN = retouche-pro.ch
> verify return:1

As expected for 1.1.1f and a trust store that contains the ISRG X1 root.

> So I suppose the problem relies on the use of openssl in the ruby
> libs.

Are the ruby libraries linked with OpenSSL 1.1.1?  Are they overriding
the default system trust store?

> However what I'm a bit surprised with is the fact that
> SSL_CTX_set_verify is called with the "wrong" certificate chain.

I think you mean the callback specified via that function is called
with unexpected chain elements, not the function itself...

> The documentation says it's going to be called for each certificate in
> the chain but do not specify if it's the chain specified by the server
> or the one built by openssl with trusted first algorithm.

Except when various earlier errors take place during chain construction,
those callbacks take place as part of signature verification on the
already constructed chain, so the callback normally sees the "trusted"
chain, not the server provided certificate "heap" (which may not be
linearly ordered).

> Is it normal to have the callback defined in SSL_CTX_set_verify to be
> called with the wrong chain ? Or do you think something is not configured
> correctly on these gems ?

See above, the callbacks report the constructed chain, except when some
error happens during chain construction.

-- 
Viktor.


Re: openssl 1.0 vs 1.1 s_client verify CA cert expiration

2021-09-30 Thread Viktor Dukhovni
> On 30 Sep 2021, at 3:34 pm, nate  wrote:
> 
>>  $ openssl s_client -showcerts \
>>-connect bad_server_name:443 \
>>-servername bad_server_name 2>/dev/null |
>>openssl crl2pkcs7 -nocrl -certfile /dev/stdin |
>>openssl pkcs7 -print_certs -noout -text |
>>egrep 'not(Before|After)'
>> or write the errors to a separate file.
> 
> 
> That almost worked.. but because the first openssl command
> never completes the other commands just wait..
> 
> I poked around and found that sending Q to the command gets it
> to exit so I came up with this:
> 
> echo "Q" | [...]

True, I forgot that I usually write:

  $ sleep 2 | openssl s_client ...

which generally gives s_client enough time to complete the handshake,
and then it exits when it sees EOF on stdin.  The "Q" is perhaps cleaner.

-- 
Viktor.



Re: openssl 1.0 vs 1.1 s_client verify CA cert expiration

2021-09-30 Thread Viktor Dukhovni
On Thu, Sep 30, 2021 at 11:26:14AM -0700, nate wrote:

> > This is *not* the correct way to see all the expiration dates in the
> > chain.  It will show only the leaf certificate dates.  The right
> > incantation is:
> > 
> >   $ openssl s_client -connect bad_server_name:443 -servername 
> > bad_server_name |
> > openssl crl2pkcs7 -nocrl -certfile /dev/stdin |
> > openssl pkcs7 -print_certs -noout -text |
> > egrep 'not(Before|After)'
> 
> At least in this case the command you supplied appears to provide less 
> information:
> 
> (OpenSSL 1.0.2g)
> depth=3 O = Digital Signature Trust Co., CN = DST Root CA X3
> verify error:num=10:certificate has expired
> notAfter=Sep 30 14:01:15 2021 GMT

Ah, you also need to add "-showcerts" to s_client and best to separate
stdout and stderr in order to avoid confusion due to error text leaking
through, sender stderr to /dev/null:

  $ openssl s_client -showcerts \
-connect bad_server_name:443 \
-servername bad_server_name 2>/dev/null |
openssl crl2pkcs7 -nocrl -certfile /dev/stdin |
openssl pkcs7 -print_certs -noout -text |
egrep 'not(Before|After)'

or write the errors to a separate file.

> (OpenSSL 1.0.2g with -trusted_first option)
> depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
> verify return:1
> depth=1 C = US, O = Let's Encrypt, CN = R3
> verify return:1
> depth=0 CN = bad_server_name
> verify return:1

Good.

> (OpenSSL 1.1.1f)
> depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
> verify return:1
> depth=1 C = US, O = Let's Encrypt, CN = R3
> verify return:1
> depth=0 CN = bad_server_name
> verify return:1

Ditto.

> Is there a command sequence that could get openssl to show all dates in
> the tree whether it is being served by the server or checked in the
> local trusted store?

The "crl2pkcs7 -nocrl -certfile /dev/stdin" command piped to
"pkcs7 -print_certs -text" is how to see the full chain.


> I assume your command is intended to do that, but
> it doesn't for me.

I neglected to suggest "-showcerts".

-- 
Viktor.


Re: openssl 1.0 vs 1.1 s_client verify CA cert expiration

2021-09-30 Thread Viktor Dukhovni
On Thu, Sep 30, 2021 at 09:43:54AM -0700, nate wrote:

> If I run this on OpenSSL 1.0.2g (Ubuntu 16.04)
> 
> openssl s_client -connect bad_server_name:443 -servername bad_server_name
> 
> I get at the end a clear: Verify return code: 10 (certificate has expired)

This is because OpenSSL 1.0.2 looks at the peer's certificate chain
before looking in the trust store.

> If I run on the same OpenSSL:
> 
> openssl s_client -connect bad_server_name:443 -servername bad_server_name | 
> openssl x509 -noout -dates

This is *not* the correct way to see all the expiration dates in the
chain.  It will show only the leaf certificate dates.  The right
incantation is:

  $ openssl s_client -connect bad_server_name:443 -servername bad_server_name |
openssl crl2pkcs7 -nocrl -certfile /dev/stdin |
openssl pkcs7 -print_certs -noout -text |
egrep 'not(Before|After)'

> If I try the same on OpenSSL 1.1.1f (Ubuntu 20.04), I get only the 
> server cert
> not the CA cert dates:
> notBefore=Aug 31 17:59:09 2021 GMT
> notAfter=Nov 29 17:59:08 2021 GMT

Expected behaviour, you've only asked for the EE cert details.

> Also on the first command there is no error saying the cert is expired 
> on OpenSSL 1.1.1f

OpenSSL 1.1.1 looks for issuer certificates first in the trust store and
only then in the peer chain.

> additional differences it seems 1.1.1f defaults to a verify depth of 2 
> and 1.0.2g goes at least
> to 3 (perhaps more).

Expected, because it finds the ISRG root in the trust store, and so
ignores the cross-cert in the peer's chain.

Another potential issue (not in this case) is that the Let's Encrypt R3
intermediate issuing CA certificate (same subject DN and public key) is
available in two different forms:

* One issued by ISRG, still valid
* Another issued by DST, expired yesterday.

Correctly configured systems that use the Let's Encrypt "full_chain.pem"
file are using the ISRG version, and should not have any issues,
provided the client system is using OpenSSL 1.1.1 and has the ISRG root
CA

Servers that update only the Let's encrypt "cert.pem" file and provide
the rest of the chain independently, or somehow otherwise manage to be
stuck with the DST-signed "R3" now have certificate chains that will
fail to validate.

-- 
Viktor.


Re: openssl(1) 3.0 crash

2021-09-30 Thread Viktor Dukhovni
On Thu, Sep 30, 2021 at 02:48:39PM +0200, Steffen Nurpmeso wrote:

> Thanks for fixing this so fast.
> 
>  ...
>  |You should open an issue on Github.  The immediate cause is:
>  ...
> 
> I finally (re)created a github account to cause less burden the next
> trivial time.  But i do not understand a jingle word of what you both
> talk about in the issues you referenced.

No worries,  It appears that in posts upthread I misunderstood the
intent of the new code in 3.0.0.  The "openssl {  |  }"
commands are not after all deprecated in 3.0.0, it was just that the
pointer to their deprecation status was not initialised to NULL.

So the fix is a one-liner to zero out the structure `f`, ensuring
a NULL deprecation status.

-- 
Viktor


Re: openssl(1) 3.0 crash

2021-09-29 Thread Viktor Dukhovni
On Wed, Sep 29, 2021 at 05:14:45PM -0400, Viktor Dukhovni wrote:

> A better fix, that emits the intended deprecation warning would be:
> 
> --- a/apps/openssl.c
> +++ b/apps/openssl.c
> [...]

Opened as pull request https://github.com/openssl/openssl/pull/16714
addressing issue: https://github.com/openssl/openssl/issues/16713

-- 
Viktor.


Re: openssl(1) 3.0 crash

2021-09-29 Thread Viktor Dukhovni
On Wed, Sep 29, 2021 at 04:59:51PM -0400, Viktor Dukhovni wrote:

>400  if (fp == NULL) {
>401  if (EVP_get_digestbyname(argv[0])) {
>402  f.type = FT_md;
>403  f.func = dgst_main;
>404  fp = 
>405  } else if (EVP_get_cipherbyname(argv[0])) {
>406  f.type = FT_cipher;
>407  f.func = enc_main;
>408  fp = 
>409  }
>410  }
> 
> The code is missing "f.deprecated_alternative = NULL" between lines
> 409 and 410, or else after each of 403 and 407.

A better fix, that emits the intended deprecation warning would be:

--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -392,6 +392,7 @@ int help_main(int argc, char **argv)
 static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
 {
 FUNCTION f, *fp;
+static char alt_buf[256];
 
 if (argc <= 0 || argv[0] == NULL)
 return 0;
@@ -401,12 +402,16 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, 
char *argv[])
 if (EVP_get_digestbyname(argv[0])) {
 f.type = FT_md;
 f.func = dgst_main;
+(void) BIO_snprintf(alt_buf, sizeof(alt_buf), "dgst -%s", argv[0]);
 fp = 
 } else if (EVP_get_cipherbyname(argv[0])) {
 f.type = FT_cipher;
 f.func = enc_main;
+(void) BIO_snprintf(alt_buf, sizeof(alt_buf), "enc -%s", argv[0]);
 fp = 
 }
+f.deprecated_alternative = alt_buf;
+f.deprecated_version = "3.0.0";
 }
 if (fp != NULL) {
 if (fp->deprecated_alternative != NULL)

-- 
Viktor.


Re: openssl(1) 3.0 crash

2021-09-29 Thread Viktor Dukhovni
On Wed, Sep 29, 2021 at 10:30:29PM +0200, Steffen Nurpmeso wrote:

> I first thought it was musl related but the AlpineLinux bug report
> turned out to be wrong, i can easily reproduce it anywhere, it is
> just that the according script only runs there:
> 
>   #?0|kent:$ export 
> LD_LIBRARY_PATH=~/usr-kent-crux-linux-x86_64/opt/.ossl3/lib64/
>   #?0|kent:$ ~/usr-kent-crux-linux-x86_64/opt/.ossl3/bin/openssl bla
>   Invalid command 'bla'; type "help" for a list.
>   #?1|kent:$ ~/usr-kent-crux-linux-x86_64/opt/.ossl3/bin/openssl chacha20
>   Segmentation fault
>   #?139|kent:$

You should open an issue on Github.  The immediate cause is:

   46   static void warn_deprecated(const FUNCTION *fp)
   47   {
   48   if (fp->deprecated_version != NULL)
-> 49   BIO_printf(bio_err, "The command %s was deprecated in version 
%s.",
   50  fp->name, fp->deprecated_version);
   ...

but in the case of the "chacha20" command, fp->deprecated_version was
not initialised:

$10 = {
  type = FT_cipher
  name = 0x7ffeefbff47a "chacha20"
  func = 0x000100021d30 (openssl`enc_main at enc.c:105)
  help = 0x7ffeefbff1b0
  deprecated_alternative = 0x7ffeefbff0b0 ""
  deprecated_version = 0xef60232fcf210011 ""
}

and so printing the version of OpenSSL in which it was deprecated
crashes.  The caller is at fault:

   392  static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
   393  {
   394  FUNCTION f, *fp;
   395
   396  if (argc <= 0 || argv[0] == NULL)
   397  return 0;
   398  f.name = argv[0];
   399  fp = lh_FUNCTION_retrieve(prog, );
   400  if (fp == NULL) {
   401  if (EVP_get_digestbyname(argv[0])) {
   402  f.type = FT_md;
   403  f.func = dgst_main;
   404  fp = 
   405  } else if (EVP_get_cipherbyname(argv[0])) {
   406  f.type = FT_cipher;
   407  f.func = enc_main;
   408  fp = 
   409  }
   410  }
   411  if (fp != NULL) {
   412  if (fp->deprecated_alternative != NULL)
   413  warn_deprecated(fp);
   414  return fp->func(argc, argv);
   415  }

The code is missing "f.deprecated_alternative = NULL" between lines
409 and 410, or else after each of 403 and 407.

-- 
Viktor.


Re: OpenSSL SSL_CTX_set_default_verify_paths Slow

2021-09-27 Thread Viktor Dukhovni
> On 27 Sep 2021, at 11:24 am, Jay Foster  wrote:
> 
> I don't think so.  The file system is a UBIFS on nand flash, and it works 
> with 1.0.2 and 1.1.1.  Even 1.1.1 is a *little* bit slower than 1.0.2, but 
> nowhere near as much slower as 3.0.0.
> 
> It looks like the OpenSSL library is reading the cert.pem file in 4KB blocks 
> at a time and doing some processing on the data read. It appears that this 
> processing is what is taking longer.

OpenSSL 3.0.0 has a new OSSL_DECODER API, it may still need some
performance tuning?  For example, in Postfix + OpenSSL 3.0.0 I'm
decoding the compiled-in DER DH group via:

+static void load_builtin(void)
+{
+EVP_PKEY *tmp = 0;
+OSSL_DECODER_CTX *d;
+const unsigned char *endp = builtin_der;
+size_t  dlen = sizeof(builtin_der);
+
+d = OSSL_DECODER_CTX_new_for_pkey(, "DER", NULL, "DH",
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ NULL, NULL);
+/* Check decode succeeds and consumes all data (final dlen == 0) */
+if (d && OSSL_DECODER_from_data(d, , ) && tmp && !dlen) {
+   dhp = tmp;
+} else {
+   EVP_PKEY_free(tmp);
+   msg_warn("error loading compiled-in DH parameters");
+   tls_print_errors();
+}
+OSSL_DECODER_CTX_free(d);
+}

IIRC the loading of certificates now uses this API.  There was perhaps
also some work on new X509_STORE infrastructure.  Performance issues in
the new code are not implausible, and I hope can be addressed in upcoming
releases.

-- 
Viktor.



Re: Will TLSv1.3 always send session ticket?

2021-09-16 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 09:49:31AM -0700, Benjamin Kaduk via openssl-users 
wrote:

> I'd be interested in hearing your thoughts about what an API/config would look
> like to enable the delayed-send behavior.

A simple boolean SSL_CONF_CMD called something like:

-ticket_delay, or
-ticket_data_prepend

would cause the ticket generation to be deferred until the first
application data write from server to client.

The API would be either a direct call to set the boolean, or
an indirect action via the SSL_CONF layer.

This would require a new bit to set the policy in the SSL_CTX that would
be inherited by any derived SSL handles.

The first data transmission would inspect the desired ticket count
computed during the handshake, and send that many tickets, resetting the
count to zero.

The current immediate transmission of tickets would merely squirrel away
the number of tickets to send with the first batch of data.

-- 
Viktor.


Re: Getting SSL_SESSION remaining lifetime

2021-09-16 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 06:50:40PM +0200, Hubert Kario wrote:
> On Thursday, 16 September 2021 17:59:48 CEST, Viktor Dukhovni wrote:
> > The Internet does not solely consist of browser traffic from portable
> > devices at wifi hotspots to taboo web sites.
> 
> taboo web sites are not the only reason to expect privacy...

Indeed, but there are also applications in which client "privacy" is
both unavailable and undesirable.  One size does not fit all.

-- 
Viktor.


Re: Will TLSv1.3 always send session ticket?

2021-09-16 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 09:30:18AM -0700, Benjamin Kaduk via openssl-users 
wrote:
> On Thu, Sep 16, 2021 at 12:20:05PM -0400, Viktor Dukhovni wrote:
> > 
> > I don't recall whether OpenSSL makes any effort to or supports deferring
> > the transmission of session tickets until just before the first
> > application data transmission from server to client (or else perhaps
> > just before responding to a received close-notify with a reciprocal
> > close-notify)
> 
> It's not the default behavior, but is supported: you can configure the
> SSL/SSL_CTX to send zero tickets by default and then manually call
> SSL_new_session_ticket(), which defers the transmission until there is another
> write or explicit SSL_do_handshake() call.

So nothing built-in...  What I had in mind was a built-in behaviour of
the library to delay session ticket transmission until there's a first
opportunity to send some application data, which the client application
can be reasonably expected to read at that point.

If this is left entirely to applications, many of the less sophisticated
ones might not know to consider the issue.

In my SMTP use-cases, after STARTTLS, the client is expected to send
a short "EHLO" command, and then turn around and read a server response,
so deadlock would require a very small TCP window on the server side,
and/or an unreasonably large (many kilobytes) client EHLO name.

So Postfix does not take any application-layer steps to postpone session
ticket transmission.  I also would not to send session tickets without
an indication that the client did not present a sufficiently fresh ticket,
so handling session ticket generation in the application logic would
become even more complex...

-- 
Viktor.


Re: Will TLSv1.3 always send session ticket?

2021-09-16 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 10:05:44AM +0100, Matt Caswell wrote:

> No. Unless you configure the server otherwise OpenSSL will always send 
> session ticket(s) in TLSv1.3.

It may be worth mentioning a discussion from some time back on the TLSWG
list started by David Benjamin that notes that in TLS 1.3 it is not
always opportune for the server to send post-handshake session
resumption tickets unless it is also sending some application data.

If the application protocol in question has the client sending first and
delivering a large request to the server before attempting to read a
response, an "unsolicited" transmission of session tickets from server
to client may cause an application protocol deadlock if the client's TCP
window is not large enough to accommodate the session tickets withour
any client-side reads.

This situation can with some justification be argued to be a defect in
the TLS 1.3 protocol.

I don't recall whether OpenSSL makes any effort to or supports deferring
the transmission of session tickets until just before the first
application data transmission from server to client (or else perhaps
just before responding to a received close-notify with a reciprocal
close-notify)

-- 
Viktor.


Re: Getting SSL_SESSION remaining lifetime

2021-09-16 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 04:11:49PM +0200, Hubert Kario wrote:

> On Thursday, 16 September 2021 04:41:44 CEST, Jaya Muthiah wrote:
> >
> > I am trying to get the remaining lifetime of the ticket so that 
> > server can decide to renew ticket or not
> 
> TLS 1.3 tickets are single use. If the ticket was used by a client,
> and you expect it to make a connection in the future, server needs to
> send a new one.

This is wrong both in terms of specification and the extant OpenSSL
implementation.

The Postfix SMTP server arranges to accept multi-use tickets without
reissuing replacement tickets when the original ticket is still good for
reuse.  Ticket reuse is well suited to the MTA-to-MTA use-case where
"privacy" is not only a concern but in fact undesirable.  MTAs often
reject traffic from senders with no PTR records, generic PTR records,
poor IP reputation, 

The Internet does not solely consist of browser traffic from portable
devices at wifi hotspots to taboo web sites.

-- 
Viktor.


Re: Getting SSL_SESSION remaining lifetime

2021-09-15 Thread Viktor Dukhovni
On Thu, Sep 16, 2021 at 08:11:44AM +0530, Jaya Muthiah wrote:

> I am trying to get the remaining lifetime of the ticket so that server can
> decide to renew ticket or not

In Postfix, I rotate ticket keys every hour, and sessions are valid for
two hours.  For the first hour when they were issued by the current
ticket the ticket is accepted without forcing a new ticket to be
generated.  Durign the second hour when accepting tickets signed by
the previous key, a fresh ticket is generated.

I don't rely on OpenSSL to tell me the ticket age, it is implied by
the key id.

Since ticket keys should be rotated anyway, something like that might
also work for you.

What I haven't yet built is a mechanism to rotate keys consistely across
multiple machines in a load-balancer pool.  That would be generally
useful.

-- 
Viktor.


Re: OpenSSL session reuse does not work with TLS_client_method()

2021-09-15 Thread Viktor Dukhovni
On Wed, Sep 15, 2021 at 05:26:51PM +0530, Jaya Muthiah wrote:

> I am trying to reuse SSL_SESSION as below, it works fine when I use
> TLSv1_2_client_method() to create context. However, it does not work
> when I use TLS_client_method().
> [...]
> if (SSL_connect(ssl) != 1) { return -1; }
> int reused = SSL_session_reused(ssl);
> ssl_session = SSL_get1_session(ssl); // for future connections

That's because with TLS_client_method() you end up negotiating TLS 1.3,
and with TLS 1.3 session tickets are sent by servers *after* the
completion of the handshake.

A TLS 1.3 session saved manually, immediately at the completion of the
handshake will have no session tickets, and will not be able to perform
resumption.  The robust way to save the session state for resumption is
to implement the session callbacks.

For example, in Postfix, you'll find:

SSL_CTX_set_session_cache_mode(client_ctx,
   SSL_SESS_CACHE_CLIENT |
   SSL_SESS_CACHE_NO_INTERNAL_STORE |
   SSL_SESS_CACHE_NO_AUTO_CLEAR);
SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb);

static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
{
...
/*
 * The cache name (if caching is enabled in tlsmgr(8)) and the cache ID
 * string for this session are stored in the TLScontext. It cannot be
 * null at this point.
 */
if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0)
msg_panic("%s: null TLScontext in new session callback", myname);
...
}

-- 
Viktor.

[ We all miss the little details sometimes, but I'd have expected Matt
  to not miss this one... ]


  1   2   3   4   5   6   7   8   9   10   >