lkml.org 
[lkml]   [2021]   [Mar]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 3/5] certs: Make blacklist_vet_description() more strict
    Date
    From: Mickaël Salaün <mic@linux.microsoft.com>

    Before exposing this new key type to user space, make sure that only
    meaningful blacklisted hashes are accepted. This is also checked for
    builtin blacklisted hashes, but a following commit make sure that the
    user will notice (at built time) and will fix the configuration if it
    already included errors.

    Check that a blacklist key description starts with a valid prefix and
    then a valid hexadecimal string.

    Cc: David Howells <dhowells@redhat.com>
    Cc: David Woodhouse <dwmw2@infradead.org>
    Cc: Eric Snowberg <eric.snowberg@oracle.com>
    Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>
    Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
    Link: https://lore.kernel.org/r/20210312171232.2681989-4-mic@digikod.net
    ---

    Changes since v5:
    * Add Reviewed-by Jarkko.

    Changes since v2:
    * Fix typo in blacklist_vet_description() comment, spotted by Tyler
    Hicks.
    * Add Jarkko's Acked-by.

    Changes since v1:
    * Return ENOPKG (instead of EINVAL) when a hash is greater than the
    maximum currently known hash (suggested by David Howells).
    ---
    certs/blacklist.c | 46 ++++++++++++++++++++++++++++++++++++----------
    1 file changed, 36 insertions(+), 10 deletions(-)

    diff --git a/certs/blacklist.c b/certs/blacklist.c
    index c9a435b15af4..97a35cf9a62c 100644
    --- a/certs/blacklist.c
    +++ b/certs/blacklist.c
    @@ -19,6 +19,16 @@
    #include "blacklist.h"
    #include "common.h"

    +/*
    + * According to crypto/asymmetric_keys/x509_cert_parser.c:x509_note_pkey_algo(),
    + * the size of the currently longest supported hash algorithm is 512 bits,
    + * which translates into 128 hex characters.
    + */
    +#define MAX_HASH_LEN 128
    +
    +static const char tbs_prefix[] = "tbs";
    +static const char bin_prefix[] = "bin";
    +
    static struct key *blacklist_keyring;

    #ifdef CONFIG_SYSTEM_REVOCATION_LIST
    @@ -32,24 +42,40 @@ extern __initconst const unsigned long revocation_certificate_list_size;
    */
    static int blacklist_vet_description(const char *desc)
    {
    - int n = 0;
    -
    - if (*desc == ':')
    - return -EINVAL;
    - for (; *desc; desc++)
    - if (*desc == ':')
    - goto found_colon;
    + int i, prefix_len, tbs_step = 0, bin_step = 0;
    +
    + /* The following algorithm only works if prefix lengths match. */
    + BUILD_BUG_ON(sizeof(tbs_prefix) != sizeof(bin_prefix));
    + prefix_len = sizeof(tbs_prefix) - 1;
    + for (i = 0; *desc; desc++, i++) {
    + if (*desc == ':') {
    + if (tbs_step == prefix_len)
    + goto found_colon;
    + if (bin_step == prefix_len)
    + goto found_colon;
    + return -EINVAL;
    + }
    + if (i >= prefix_len)
    + return -EINVAL;
    + if (*desc == tbs_prefix[i])
    + tbs_step++;
    + if (*desc == bin_prefix[i])
    + bin_step++;
    + }
    return -EINVAL;

    found_colon:
    desc++;
    - for (; *desc; desc++) {
    + for (i = 0; *desc && i < MAX_HASH_LEN; desc++, i++) {
    if (!isxdigit(*desc) || isupper(*desc))
    return -EINVAL;
    - n++;
    }
    + if (*desc)
    + /* The hash is greater than MAX_HASH_LEN. */
    + return -ENOPKG;

    - if (n == 0 || n & 1)
    + /* Checks for an even number of hexadecimal characters. */
    + if (i == 0 || i & 1)
    return -EINVAL;
    return 0;
    }
    --
    2.30.2
    \
     
     \ /
      Last update: 2021-03-12 18:14    [W:2.574 / U:0.160 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site