also zero pad DHE public key in ClientKeyExchange message for interop
authorFelix Monninger <felix.monninger@gmail.com>
Tue, 30 Jun 2020 20:57:36 +0000 (22:57 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Tue, 1 Sep 2020 12:27:05 +0000 (14:27 +0200)
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/12331)

ssl/statem/statem_clnt.c

index 4c994dd3896a74fcbe52a96d5d07993b269b9171..0780e5fc9a3ed09e1e97415b0b6d38a22d8c26ef 100644 (file)
@@ -3069,9 +3069,9 @@ static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_DH
     DH *dh_clnt = NULL;
-    const BIGNUM *pub_key;
     EVP_PKEY *ckey = NULL, *skey = NULL;
     unsigned char *keybytes = NULL;
+    int prime_len;
 
     skey = s->s3.peer_tmp;
     if (skey == NULL) {
@@ -3101,15 +3101,19 @@ static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
     }
 
     /* send off the data */
-    DH_get0_key(dh_clnt, &pub_key, NULL);
-    if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
-                                        &keybytes)) {
+    prime_len = BN_num_bytes(DH_get0_p(dh_clnt));
+    /*
+     * For interoperability with some versions of the Microsoft TLS
+     * stack, we need to zero pad the DHE pub key to the same length
+     * as the prime, so use the length of the prime here.
+     */
+    if (!WPACKET_sub_allocate_bytes_u16(pkt, prime_len, &keybytes)
+            || BN_bn2binpad(DH_get0_pub_key(dh_clnt), keybytes, prime_len) < 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
                  ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
-    BN_bn2bin(pub_key, keybytes);
     EVP_PKEY_free(ckey);
 
     return 1;