From 7c43eb5dcf5cb098b9e2c2c58b000353af51efa2 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Sun, 6 Oct 2019 22:25:10 +0300 Subject: [PATCH] Strip BOM on loading PEM files Reviewed-by: Richard Levitte Reviewed-by: Viktor Dukhovni --- crypto/pem/pem_lib.c | 19 ++++++++++++--- test/recipes/04-test_pem.t | 1 + test/recipes/04-test_pem_data/cert-bom.pem | 28 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 test/recipes/04-test_pem_data/cert-bom.pem diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c index eb07c884e7..020a030334 100644 --- a/crypto/pem/pem_lib.c +++ b/crypto/pem/pem_lib.c @@ -680,9 +680,20 @@ int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, #endif /* Some helpers for PEM_read_bio_ex(). */ -static int sanitize_line(char *linebuf, int len, unsigned int flags) +static int sanitize_line(char *linebuf, int len, unsigned int flags, int first_call) { int i; + if (first_call) { + /* Other BOMs imply unsupported multibyte encoding, + * so don't strip them and let the error raise */ + const unsigned char utf8_bom[3] = {0xEF, 0xBB, 0xBF}; + + if (len > 3 && memcmp(linebuf, utf8_bom, 3) == 0) { + memmove(linebuf, linebuf + 3, len - 3); + linebuf[len - 3] = 0; + len -= 3; + } + } if (flags & PEM_FLAG_EAY_COMPATIBLE) { /* Strip trailing whitespace */ @@ -727,6 +738,7 @@ static int get_name(BIO *bp, char **name, unsigned int flags) char *linebuf; int ret = 0; int len; + int first_call = 1; /* * Need to hold trailing NUL (accounted for by BIO_gets() and the newline @@ -747,7 +759,8 @@ static int get_name(BIO *bp, char **name, unsigned int flags) } /* Strip trailing garbage and standardize ending. */ - len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64); + len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64, first_call); + first_call = 0; /* Allow leading empty or non-matching lines. */ } while (strncmp(linebuf, beginstr, BEGINLEN) != 0 @@ -819,7 +832,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, } if (!strncmp(linebuf, endstr, ENDLEN) || got_header == IN_HEADER) flags_mask &= ~PEM_FLAG_ONLY_B64; - len = sanitize_line(linebuf, len, flags & flags_mask); + len = sanitize_line(linebuf, len, flags & flags_mask, 0); /* Check for end of header. */ if (linebuf[0] == '\n') { diff --git a/test/recipes/04-test_pem.t b/test/recipes/04-test_pem.t index b8f4d722a0..0e6e419519 100644 --- a/test/recipes/04-test_pem.t +++ b/test/recipes/04-test_pem.t @@ -32,6 +32,7 @@ my %cert_expected = ( "cert-256line.pem" => 1, "cert-257line.pem" => 1, "cert-blankline.pem" => 0, + "cert-bom.pem" => 1, "cert-comment.pem" => 0, "cert-earlypad.pem" => 0, "cert-extrapad.pem" => 0, diff --git a/test/recipes/04-test_pem_data/cert-bom.pem b/test/recipes/04-test_pem_data/cert-bom.pem new file mode 100644 index 0000000000..91fbaf4024 --- /dev/null +++ b/test/recipes/04-test_pem_data/cert-bom.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzDCCA7QCCQCgxkRox+YljjANBgkqhkiG9w0BAQsFADCCASYxYzBhBgNVBAgM +WlRoZSBHcmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVs +ZCBOYW1lcyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0G +A1UEBwwWVG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2 +b2xlbnQgU29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlw +aHJhc2lzMT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlk +ZW50aWFyeSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwHhcN +MTcwMjIzMjAyNTM2WhcNMTcwMzI1MjAyNTM2WjCCASYxYzBhBgNVBAgMWlRoZSBH +cmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVsZCBOYW1l +cyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0GA1UEBwwW +VG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2b2xlbnQg +U29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlwaHJhc2lz +MT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlkZW50aWFy +eSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7MOIrqH+ZIJiZdroKMrelKMSvvRKg2MEg +j/sx9TaHHqrKys4AiL4Rq/ybQEigFC6G8mpZWbBrU+vN2SLr1ZsPftCHIY12LF56 +0WLYTYNqDgF5BdCZCrjJ2hhN+XwML2tgYdWioV/Eey8SJSqUskf03MpcwnLbVfSp +hwmowqNfiEFFqPBCf7E8IVarGWctbMpvlMbAM5owhMev/Ccmqqt81NFkb1WVejvN +5v/JKv243/Xedf4I7ZJv7zKeswoP9piFzWHXCd9SIVzWqF77u/crHufIhoEa7NkZ +hSC2aosQF619iKnfk0nqWaLDJ182CCXkHERoQC7q9X2IGLDLoA0XAgMBAAEwDQYJ +KoZIhvcNAQELBQADggEBAKbtLx+YlCGRCBmYn3dfYF+BIvK/b/e0DKNhDKhb4s9J +ywlJ4qnAB48tgPx0q+ZB+EdMYRqCwyvXJxEdZ7PsCdUeU6xI2ybkhSdUUfQbYem3 +aYRG+yukGzazySQJs8lGqxBlRMFl/FGCg+oSQ/I32eGf8micDskj2zkAJtCkUPHX +30YrWMfOwW1r2xYr2mBNXbNWXJhW/sIg5u8aa9fcALeuQcMXkbsbVoPmC5aLdiVZ +rvUFoJ8DPg0aYYwj64RwU0B5HW/7jKhQ25FgKVAzLGrgYx1DivkM7UQGdWYnU8IA +A8S89gRjGk2hnkeagWas3dxqTTpgJDhprgWzyKa9hII= +-----END CERTIFICATE----- -- 2.25.1