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 <[email protected]>
> ---
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel