]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
contrib/base64: sync with Knot DNS
authorTomas Krizek <tomas.krizek@nic.cz>
Fri, 25 Sep 2020 13:35:20 +0000 (15:35 +0200)
committerTomas Krizek <tomas.krizek@nic.cz>
Tue, 13 Oct 2020 10:55:29 +0000 (12:55 +0200)
contrib/base64.c
contrib/base64url.c
contrib/base64url.h

index 3558f1bfe7a4c57eb66f0cc23079337bb5214a77..845b99c52b7a67e6d2b791805983cf3bcefa21a3 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *  SPDX-License-Identifier: GPL-3.0-or-later
  */
 
@@ -142,6 +142,7 @@ int32_t kr_base64_encode_alloc(const uint8_t  *in,
        int32_t ret = kr_base64_encode(in, in_len, *out, out_len);
        if (ret < 0) {
                free(*out);
+               *out = NULL;
        }
 
        return ret;
@@ -203,8 +204,10 @@ int32_t kr_base64_decode(const uint8_t  *in,
                switch (pad_len) {
                case 0:
                        bin[2] = (c3 << 6) + c4;
+                       // FALLTHROUGH
                case 1:
                        bin[1] = (c2 << 4) + (c3 >> 2);
+                       // FALLTHROUGH
                case 2:
                        bin[0] = (c1 << 2) + (c2 >> 4);
                }
@@ -250,6 +253,7 @@ int32_t kr_base64_decode_alloc(const uint8_t  *in,
        int32_t ret = kr_base64_decode(in, in_len, *out, out_len);
        if (ret < 0) {
                free(*out);
+               *out = NULL;
        }
 
        return ret;
index 05697f45e94e1eddfdf0914e292d14d907b0ba57..a01520570735e0b430a2066f25cb72c2fa313da0 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <ctype.h>
 
 /*! \brief Maximal length of binary input to Base64url encoding. */
 #define MAX_BIN_DATA_LEN       ((INT32_MAX / 4) * 3)
@@ -73,7 +74,7 @@ static const uint8_t base64url_dec[256] = {
        [ 34] = KO, ['M'] = 12, ['x'] = 49, [163] = KO, [206] = KO, [249] = KO,
        [ 35] = KO, ['N'] = 13, ['y'] = 50, [164] = KO, [207] = KO, [250] = KO,
        [ 36] = KO, ['O'] = 14, ['z'] = 51, [165] = KO, [208] = KO, [251] = KO,
-       [ 37] = KO, ['P'] = 15, [123] = KO, [166] = KO, [209] = KO, [252] = KO,
+       ['%'] = KO, ['P'] = 15, [123] = KO, [166] = KO, [209] = KO, [252] = KO,
        [ 38] = KO, ['Q'] = 16, [124] = KO, [167] = KO, [210] = KO, [253] = KO,
        [ 39] = KO, ['R'] = 17, [125] = KO, [168] = KO, [211] = KO, [254] = KO,
        [ 40] = KO, ['S'] = 18, [126] = KO, [169] = KO, [212] = KO, [255] = KO,
@@ -160,7 +161,7 @@ int32_t kr_base64url_encode_alloc(const uint8_t  *in,
 }
 
 int32_t kr_base64url_decode(const uint8_t  *in,
-                      const uint32_t in_len,
+                      uint32_t in_len,
                       uint8_t        *out,
                       const uint32_t out_len)
 {
@@ -168,6 +169,18 @@ int32_t kr_base64url_decode(const uint8_t  *in,
        if (in == NULL || out == NULL) {
                return KNOT_EINVAL;
        }
+
+       // cut up to two "%3d" from the end of input
+       int pad3d = 0;
+       const uint8_t *end = in + in_len;
+       char *perc3d = "d3%d3%", *stop3d = perc3d + 6;
+       while (end != in && perc3d != stop3d && tolower(*--end) == *perc3d) {
+               if (*perc3d++ == '%') {
+                       in_len -= 3;
+                       pad3d++;
+               }
+       }
+
        if (in_len > INT32_MAX || out_len < ((in_len + 3) / 4) * 3) {
                return KNOT_ERANGE;
        }
@@ -181,30 +194,32 @@ int32_t kr_base64url_decode(const uint8_t  *in,
        while (in < stop) {
                // Filling and transforming 4 Base64 chars.
                c1 =                   base64url_dec[in[0]]     ;
-               c2 = (in + 1 < stop) ? base64url_dec[in[1]] : PD;
+               c2 =                   base64url_dec[in[1]]     ;
                c3 = (in + 2 < stop) ? base64url_dec[in[2]] : PD;
                c4 = (in + 3 < stop) ? base64url_dec[in[3]] : PD;
 
-               // Check 4. char if is bad or padding.
-               if (c4 >= PD) {
-                       if (c4 == PD && pad_len == 0) {
-                               pad_len = 1;
+               // Check 1. and 2. chars if are not padding
+               if (c1 >= PD || c2 >= PD) {
+                       return KNOT_BASE64_ECHAR;
+               }
+               // Check 3. char if is bad or padding.
+               else if (c3 >= PD) {
+                       if (c3 == PD) {
+                               pad_len = 2;
                        } else {
                                return KNOT_BASE64_ECHAR;
                        }
                }
-
                // Check 3. char if is bad or padding.
-               if (c3 >= PD) {
-                       if (c3 == PD && pad_len == 1) {
-                               pad_len = 2;
+               else if (c4 >= PD) {
+                       if (c4 == PD) {
+                               pad_len = 1;
                        } else {
                                return KNOT_BASE64_ECHAR;
                        }
                }
 
-               // Check 1. and 2. chars if are not padding.
-               if (c2 >= PD || c1 >= PD) {
+               if (pad_len > 0 && in <= stop - 4) {
                        return KNOT_BASE64_ECHAR;
                }
 
@@ -227,15 +242,19 @@ int32_t kr_base64url_decode(const uint8_t  *in,
                        break;
                case 1:
                        bin += 2;
-                       break;
+                       goto end;
                case 2:
                        bin += 1;
-                       break;
+                       goto end;
                }
 
                in += 4;
        }
 
+end:
+       if (pad3d > pad_len) {
+               return KNOT_BASE64_ECHAR;
+       }
        return (bin - out);
 }
 
index 66a3afccc6d75d11896c4144754d8b1febbacbaa..875ecfa2a77b5837f18e69f9c6d486b1e67d9a9e 100644 (file)
@@ -76,7 +76,7 @@ int32_t kr_base64url_encode_alloc(const uint8_t  *in,
  * \retval KNOT_E*     if error.
  */
 int32_t kr_base64url_decode(const uint8_t  *in,
-                      const uint32_t in_len,
+                      uint32_t       in_len,
                       uint8_t        *out,
                       const uint32_t out_len);