Description:
For the certificate that doesn't have line length of 65 characters (64+\n) MySQL loads it correctly but any SSL connection is refused with an ambiguous error: `SSL connection error: protocol version mismatch`.
$ for l in $(<ServerCertificate.crt); do echo $l | wc -c; done;
11
17
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
61
57
9
17
From Non-SSL session:
mysql> show variables like 'have%ssl';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl | YES |
| have_ssl | YES |
+---------------+-------+
From SSL Session:
$ mysql -h 127.0.0.1 -umsandbox -pmsandbox --ssl-mode=REQUIRED -P 5720
ERROR 2026 (HY000): SSL connection error: protocol version mismatch
Everything works fine when (the same) certificate have line length of 65 (64+\n) characters
# openssl x509 -in ServerCertificate.crt -out rfc.crt
$ for l in $(<rfc.crt); do echo $l |wc -c; done;
11
17
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
65
5
9
17
$ mysql -h 127.0.0.1 -umsandbox -pmsandbox --ssl-mode=REQUIRED -P 5720
Server version: 5.7.20 MySQL Community Server (GPL)
mysql> \s
[...]
Current user: msandbox@localhost
SSL: Cipher in use is DHE-RSA-AES256-SHA
The certificates are basically the same, except for the line length.
$ for i in ServerCertificate.crt rfc.crt; do cat $i | tr -d '\n' | md5sum; done;
a94cc96c06512dcd7ae74e90b4938e86 -
a94cc96c06512dcd7ae74e90b4938e86 -
Note, that there's a hardcoded PEM line length in file extra/yassl/taocrypt/crd/coding.cpp:
67: const int pemLineSz = 64;
which is later used in
128: void Base64Encoder::Encode()
129: {
130: word32 bytes = plain_.size();
140: word32 outSz = (bytes + 3 - 1) / 3 * 4;
150:
160: outSz += (outSz + pemLineSz - 1) / pemLineSz; // new lines
161: encoded_.New(outSz);
Any version compiled with OpenSSL isn't affected.
Note, RFC 7468 says that:
Generators MUST wrap the base64-encoded lines so that each line
consists of exactly 64 characters except for the final line, which
will encode the remainder of the data (within the 64-character line
boundary), and they MUST NOT emit extraneous whitespace. Parsers MAY
handle other line sizes. These requirements are consistent with PEM
[RFC1421].
however, this isn't strictly followed by many SSL implementations.
How to repeat:
1. Generate SSL certificate that doesn't have a line length of 65 (64+\n) characters.
2. Run MySQL with this certificate loaded.
3. Change the line length of the certificate (openssl x509 -in ServerCertificate.crt -out rfc.crt).
4. Run MySQL with the new certificate.
Suggested fix:
1. It should be allowed to load certificate that line length differs from 64 or, at least, an Error should be returned.
2. This should be included in the documentation because issues like that are really hard to debug.