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