Hi,

On 05/03/2021 00:06, Arne Schwabe wrote:
> This commit cleans up the logic in the function a bit. It also makes it
> more clear the the details printed in the second part of the message are
> details about the peer certificate and not the TLS connection as such.
> Also print the signature algorithm as this might help to identify
> peer certificate that still use SHA1.
> 
> The new format with for TLS 1.3 and an EC certificate.
> 
> Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer 
> certificate: 384 bit EC, curve secp384r1, signature: ecdsa-with-SHA256
> 
> Using the more generic OpenSSL functions also allows use to correctly
> print details about ED certificates:
> 
> Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer 
> certificate: 253 bit ED25519, signature: ED25519
> 
> Patch v2: Cleanup multiple calls to EVP_PKEY_id, minor code restructuring
> 
> Signed-off-by: Arne Schwabe <a...@rfc2549.org>
> ---
>  src/openvpn/ssl_openssl.c | 121 +++++++++++++++++++++++++-------------
>  1 file changed, 81 insertions(+), 40 deletions(-)
> 
> diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
> index d161f48b..a9b18447 100644
> --- a/src/openvpn/ssl_openssl.c
> +++ b/src/openvpn/ssl_openssl.c
> @@ -2001,6 +2001,83 @@ key_state_read_plaintext(struct key_state_ssl *ks_ssl, 
> struct buffer *buf,
>      return ret;
>  }
>  
> +/**
> + * Print human readable information about the certifcate into buf
> + * @param cert      the certificate being used
> + * @param buf       output buffer
> + * @param buflen    output buffer length
> + */
> +static void
> +print_cert_details(X509 *cert, char *buf, size_t buflen)
> +{
> +    const char *curve = "";
> +    const char *type = "(error getting type)";
> +    EVP_PKEY *pkey = X509_get_pubkey(cert);
> +
> +    if (pkey == NULL)
> +    {
> +        buf[0] = 0;
> +        return;
> +    }
> +
> +    int typeid = EVP_PKEY_id(pkey);
> +
> +#ifndef OPENSSL_NO_EC
> +    if (typeid == EVP_PKEY_EC && EVP_PKEY_get0_EC_KEY(pkey) != NULL)
> +    {
> +        EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
> +        const EC_GROUP *group = EC_KEY_get0_group(ec);
> +
> +        int nid = EC_GROUP_get_curve_name(group);
> +        if (nid == 0 || (curve = OBJ_nid2sn(nid)) == NULL)
> +        {
> +            curve = "(error getting curve name)";
> +        }
> +    }
> +#endif
> +    if (typeid != 0)
> +    {
> +        /* OpenSSL reports rsaEncryption, dsaEncryption and
> +        * id-ecPublicKey, override the names with more readable ones */
> +        if (typeid == EVP_PKEY_RSA)
> +        {
> +            type = "RSA";
> +        }
> +        else if (typeid == EVP_PKEY_DSA)
> +        {
> +            type = "DSA";
> +        }
> +        else if (typeid == EVP_PKEY_EC)
> +        {
> +            /* EC gets the curve appended after the type */
> +            type = "EC, curve ";
> +        }
> +        else
> +        {
> +            /* Normal case, the name given by OpenSSL is used */
> +            type = OBJ_nid2sn(typeid);
> +
> +            if (type == NULL)
> +            {
> +                type = "unknown type";
> +            }
> +        }
> +   }
> +
> +    char sig[128];
> +    int signature_nid = X509_get_signature_nid(cert);
> +    if (signature_nid != 0)
> +    {
> +        openvpn_snprintf(sig, sizeof(sig), ", signature: %s",
> +                         OBJ_nid2sn(signature_nid));
> +    }
> +
> +    openvpn_snprintf(buf, buflen, ", peer certificate: %d bit %s%s%s",
> +                     EVP_PKEY_bits(pkey), type, curve, sig);

Am I wrong or here we might end up using 'sig' without having
initialized it?


Regards,


> +
> +    EVP_PKEY_free(pkey);
> +}
> +
>  /* **************************************
>   *
>   * Information functions
> @@ -2012,7 +2089,6 @@ void
>  print_details(struct key_state_ssl *ks_ssl, const char *prefix)
>  {
>      const SSL_CIPHER *ciph;
> -    X509 *cert;
>      char s1[256];
>      char s2[256];
>  
> @@ -2023,48 +2099,13 @@ print_details(struct key_state_ssl *ks_ssl, const 
> char *prefix)
>                       SSL_get_version(ks_ssl->ssl),
>                       SSL_CIPHER_get_version(ciph),
>                       SSL_CIPHER_get_name(ciph));
> -    cert = SSL_get_peer_certificate(ks_ssl->ssl);
> -    if (cert != NULL)
> -    {
> -        EVP_PKEY *pkey = X509_get_pubkey(cert);
> -        if (pkey != NULL)
> -        {
> -            if ((EVP_PKEY_id(pkey) == EVP_PKEY_RSA) && 
> (EVP_PKEY_get0_RSA(pkey) != NULL))
> -            {
> -                RSA *rsa = EVP_PKEY_get0_RSA(pkey);
> -                openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA",
> -                                 RSA_bits(rsa));
> -            }
> -            else if ((EVP_PKEY_id(pkey) == EVP_PKEY_DSA) && 
> (EVP_PKEY_get0_DSA(pkey) != NULL))
> -            {
> -                DSA *dsa = EVP_PKEY_get0_DSA(pkey);
> -                openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
> -                                 DSA_bits(dsa));
> -            }
> -#ifndef OPENSSL_NO_EC
> -            else if ((EVP_PKEY_id(pkey) == EVP_PKEY_EC) && 
> (EVP_PKEY_get0_EC_KEY(pkey) != NULL))
> -            {
> -                EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
> -                const EC_GROUP *group = EC_KEY_get0_group(ec);
> -                const char *curve;
> +    X509 *cert = SSL_get_peer_certificate(ks_ssl->ssl);
>  
> -                int nid = EC_GROUP_get_curve_name(group);
> -                if (nid == 0 || (curve = OBJ_nid2sn(nid)) == NULL)
> -                {
> -                    curve = "Error getting curve name";
> -                }
> -
> -                openvpn_snprintf(s2, sizeof(s2), ", %d bit EC, curve: %s",
> -                                 EC_GROUP_order_bits(group), curve);
> -
> -            }
> -#endif
> -            EVP_PKEY_free(pkey);
> -        }
> +    if (cert)
> +    {
> +        print_cert_details(cert, s2, sizeof(s2));
>          X509_free(cert);
>      }
> -    /* The SSL API does not allow us to look at temporary RSA/DH keys,
> -     * otherwise we should print their lengths too */
>      msg(D_HANDSHAKE, "%s%s", s1, s2);
>  }
>  
> 

-- 
Antonio Quartulli


_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to