Kaynağa Gözat

Fix hang when decoding PEM

Reported via [0]

[0] https://github.com/DCIT/perl-CryptX/issues/110#issue-2533207989

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 1 yıl önce
ebeveyn
işleme
c1437deec2

+ 6 - 0
src/misc/pem/pem_read.c

@@ -163,6 +163,7 @@ int pem_read(void *pem, unsigned long *w, struct pem_headers *hdr, struct get_ch
    unsigned long slen, linelen;
    int err, hdr_ok = 0;
    int would_overflow = 0;
+   unsigned char empty_lines = 0;
 
    linelen = sizeof(buf);
    if (s_get_line(buf, &linelen, g) == NULL) {
@@ -184,6 +185,11 @@ int pem_read(void *pem, unsigned long *w, struct pem_headers *hdr, struct get_ch
          hdr_ok = 1;
          break;
       }
+      if (!slen) {
+         if (empty_lines)
+            break;
+         empty_lines++;
+      }
       if (!would_overflow && s_fits_buf(wpem, slen, end)) {
          XMEMCPY(wpem, buf, slen);
       } else {

+ 1 - 0
tests/pem/pkcs/invalid/single_line

@@ -0,0 +1 @@
+-----BEGIN EC PRIVATE KEY-----MHcCAQEEIFF9oAGC6vxNLIU8D+nuvM8ms1QQlPtpGzQTfzEBVB06oAoGCCqGSM49AwEHoUQDQgAE3VU0nT1p5W0zKHDknAgQpsOODuM2/AoZ/6wNqC9AoUCEpQempFg0aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2mlw==-----END EC PRIVATE KEY-----

+ 1 - 0
tests/pem/pkcs/invalid/single_line.pub

@@ -0,0 +1 @@
+-----BEGIN PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3VU0nT1p5W0zKHDknAgQpsOODuM2/AoZ/6wNqC9AoUCEpQempFg0aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2mlw==-----END PUBLIC KEY-----

+ 9 - 0
tests/pem/pkcs/invalid/tall_multi_line

@@ -0,0 +1,9 @@
+-----BEGIN EC PRIVATE KEY-----
+
+MHcCAQEEIFF9oAGC6vxNLIU8D+nuvM8ms1QQlPtpGzQTfzEBVB06oAoGCCqGSM49
+
+AwEHoUQDQgAE3VU0nT1p5W0zKHDknAgQpsOODuM2/AoZ/6wNqC9AoUCEpQempFg0
+
+aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2mlw==
+
+-----END EC PRIVATE KEY-----

+ 7 - 0
tests/pem/pkcs/invalid/tall_multi_line.pub

@@ -0,0 +1,7 @@
+-----BEGIN PUBLIC KEY-----
+
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3VU0nT1p5W0zKHDknAgQpsOODuM2
+
+/AoZ/6wNqC9AoUCEpQempFg0aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2mlw==
+
+-----END PUBLIC KEY-----'

+ 6 - 0
tests/pem/pkcs/invalid/weird_multi_line.pub

@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MHcCAQEEIFF9oAGC6vxNLIU8D+nuvM8ms1QQlPtp
+GzQTfzEBVB06oAoGCCqGSM49AwEHoUQDQgAE3VU0
+nT1p5W0zKHDknAgQpsOODuM2/AoZ/6wNqC9AoUCE
+pQempFg0aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2m
+lw==-----END PUBLIC KEY-----

+ 8 - 0
tests/pem/pkcs/invalid_but_supported/narrow_multi_line

@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIFF9oAGC6vxNLIU8D+nuvM8m
+s1QQlPtpGzQTfzEBVB06oAoGCCqGSM49
+AwEHoUQDQgAE3VU0nT1p5W0zKHDknAgQ
+psOODuM2/AoZ/6wNqC9AoUCEpQempFg0
+aBqxleOP0uW0HG1YwCnOF8N0D8Q2RR2m
+lw==
+-----END EC PRIVATE KEY-----

+ 6 - 0
tests/pem/pkcs/invalid_but_supported/narrow_multi_line.pub

@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAE3VU0nT1p5W0zKHDknAgQpsOODuM2
+/AoZ/6wNqC9AoUCEpQempFg0aBqxleOP
+0uW0HG1YwCnOF8N0D8Q2RR2mlw==
+-----END PUBLIC KEY-----

+ 9 - 0
tests/pem_test.c

@@ -93,6 +93,13 @@ static int s_key_cmp(ltc_pka_key *key)
    return CRYPT_INVALID_ARG;
 }
 
+static int s_pem_decode_invalid_pkcs(const void *in, unsigned long inlen, void *key)
+{
+   password_ctx pw_ctx = { .callback = password_get };
+   SHOULD_FAIL(pem_decode_pkcs(in, inlen, key, &pw_ctx));
+   return CRYPT_OK;
+}
+
 static int s_pem_only_decode_pkcs(const void *in, unsigned long inlen, void *key)
 {
    password_ctx pw_ctx = { .callback = password_get };
@@ -158,6 +165,8 @@ int pem_test(void)
    DO(test_process_dir("tests/pem/pkcs/ecc-pkcs8", &key, s_pem_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test+ecc"));
    DO(test_process_dir("tests/pem/pkcs/ecc-pkcs8", &key, NULL, s_pem_decode_pkcs_f, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test_filehandle+ecc"));
    DO(test_process_dir("tests/pem/pkcs/extra", &key, s_pem_only_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test+extra"));
+   DO(test_process_dir("tests/pem/pkcs/invalid", &key, s_pem_decode_invalid_pkcs, NULL, NULL, "pem_test_invalid"));
+   DO(test_process_dir("tests/pem/pkcs/invalid_but_supported", &key, s_pem_only_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_invalid_but_supported"));
 #ifdef LTC_SSH
    DO(test_process_dir("tests/pem/ssh", &key, s_pem_decode_ssh, NULL, (dir_cleanup_cb)pka_key_free, "pem_ssh_test"));
    DO(test_process_dir("tests/pem/ssh", &key, NULL, s_pem_decode_ssh_f, (dir_cleanup_cb)pka_key_free, "pem_ssh_test_filehandle"));