1 /* 2 * 3 * Copyright 2016 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include <grpc/support/alloc.h> 22 #include <grpc/support/log.h> 23 #include "src/core/ext/transport/chttp2/transport/bin_decoder.h" 24 #include "src/core/lib/gpr/string.h" 25 #include "src/core/lib/slice/slice_internal.h" 26 #include "src/core/lib/slice/slice_string_helpers.h" 27 28 static uint8_t decode_table[] = { 29 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 30 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 31 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 32 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 62, 0x40, 0x40, 0x40, 63, 33 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0x40, 0x40, 34 0x40, 0x40, 0x40, 0x40, 0x40, 0, 1, 2, 3, 4, 5, 6, 35 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 36 19, 20, 21, 22, 23, 24, 25, 0x40, 0x40, 0x40, 0x40, 0x40, 37 0x40, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 39 49, 50, 51, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 40 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 41 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 42 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 43 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 44 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 45 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 46 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 47 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 48 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 49 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 50 0x40, 0x40, 0x40, 0x40}; 51 52 static const uint8_t tail_xtra[4] = {0, 0, 1, 2}; 53 54 static bool input_is_valid(uint8_t* input_ptr, size_t length) { 55 size_t i; 56 57 for (i = 0; i < length; ++i) { 58 if (GPR_UNLIKELY((decode_table[input_ptr[i]] & 0xC0) != 0)) { 59 gpr_log(GPR_ERROR, 60 "Base64 decoding failed, invalid character '%c' in base64 " 61 "input.\n", 62 static_cast<char>(*input_ptr)); 63 return false; 64 } 65 } 66 return true; 67 } 68 69 #define COMPOSE_OUTPUT_BYTE_0(input_ptr) \ 70 (uint8_t)((decode_table[input_ptr[0]] << 2) | \ 71 (decode_table[input_ptr[1]] >> 4)) 72 73 #define COMPOSE_OUTPUT_BYTE_1(input_ptr) \ 74 (uint8_t)((decode_table[input_ptr[1]] << 4) | \ 75 (decode_table[input_ptr[2]] >> 2)) 76 77 #define COMPOSE_OUTPUT_BYTE_2(input_ptr) \ 78 (uint8_t)((decode_table[input_ptr[2]] << 6) | decode_table[input_ptr[3]]) 79 80 // By RFC 4648, if the length of the encoded string without padding is 4n+r, 81 // the length of decoded string is: 1) 3n if r = 0, 2) 3n + 1 if r = 2, 3, or 82 // 3) invalid if r = 1. 83 size_t grpc_chttp2_base64_infer_length_after_decode(const grpc_slice& slice) { 84 size_t len = GRPC_SLICE_LENGTH(slice); 85 const uint8_t* bytes = GRPC_SLICE_START_PTR(slice); 86 while (len > 0 && bytes[len - 1] == '=') { 87 len--; 88 } 89 if (GPR_UNLIKELY(GRPC_SLICE_LENGTH(slice) - len > 2)) { 90 gpr_log(GPR_ERROR, 91 "Base64 decoding failed. Input has more than 2 paddings."); 92 return 0; 93 } 94 size_t tuples = len / 4; 95 size_t tail_case = len % 4; 96 if (GPR_UNLIKELY(tail_case == 1)) { 97 gpr_log(GPR_ERROR, 98 "Base64 decoding failed. Input has a length of %zu (without" 99 " padding), which is invalid.\n", 100 len); 101 return 0; 102 } 103 return tuples * 3 + tail_xtra[tail_case]; 104 } 105 106 bool grpc_base64_decode_partial(struct grpc_base64_decode_context* ctx) { 107 size_t input_tail; 108 109 if (ctx->input_cur > ctx->input_end || ctx->output_cur > ctx->output_end) { 110 return false; 111 } 112 113 // Process a block of 4 input characters and 3 output bytes 114 while (ctx->input_end >= ctx->input_cur + 4 && 115 ctx->output_end >= ctx->output_cur + 3) { 116 if (!input_is_valid(ctx->input_cur, 4)) return false; 117 ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); 118 ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); 119 ctx->output_cur[2] = COMPOSE_OUTPUT_BYTE_2(ctx->input_cur); 120 ctx->output_cur += 3; 121 ctx->input_cur += 4; 122 } 123 124 // Process the tail of input data 125 input_tail = static_cast<size_t>(ctx->input_end - ctx->input_cur); 126 if (input_tail == 4) { 127 // Process the input data with pad chars 128 if (ctx->input_cur[3] == '=') { 129 if (ctx->input_cur[2] == '=' && ctx->output_end >= ctx->output_cur + 1) { 130 if (!input_is_valid(ctx->input_cur, 2)) return false; 131 *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); 132 ctx->input_cur += 4; 133 } else if (ctx->output_end >= ctx->output_cur + 2) { 134 if (!input_is_valid(ctx->input_cur, 3)) return false; 135 *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); 136 *(ctx->output_cur++) = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); 137 ; 138 ctx->input_cur += 4; 139 } 140 } 141 142 } else if (ctx->contains_tail && input_tail > 1) { 143 // Process the input data without pad chars, but constains_tail is set 144 if (ctx->output_end >= ctx->output_cur + tail_xtra[input_tail]) { 145 if (!input_is_valid(ctx->input_cur, input_tail)) return false; 146 switch (input_tail) { 147 case 3: 148 ctx->output_cur[1] = COMPOSE_OUTPUT_BYTE_1(ctx->input_cur); 149 /* fallthrough */ 150 case 2: 151 ctx->output_cur[0] = COMPOSE_OUTPUT_BYTE_0(ctx->input_cur); 152 } 153 ctx->output_cur += tail_xtra[input_tail]; 154 ctx->input_cur += input_tail; 155 } 156 } 157 158 return true; 159 } 160 161 grpc_slice grpc_chttp2_base64_decode(grpc_slice input) { 162 size_t input_length = GRPC_SLICE_LENGTH(input); 163 size_t output_length = input_length / 4 * 3; 164 struct grpc_base64_decode_context ctx; 165 grpc_slice output; 166 167 if (GPR_UNLIKELY(input_length % 4 != 0)) { 168 gpr_log(GPR_ERROR, 169 "Base64 decoding failed, input of " 170 "grpc_chttp2_base64_decode has a length of %d, which is not a " 171 "multiple of 4.\n", 172 static_cast<int>(input_length)); 173 return grpc_empty_slice(); 174 } 175 176 if (input_length > 0) { 177 uint8_t* input_end = GRPC_SLICE_END_PTR(input); 178 if (*(--input_end) == '=') { 179 output_length--; 180 if (*(--input_end) == '=') { 181 output_length--; 182 } 183 } 184 } 185 output = GRPC_SLICE_MALLOC(output_length); 186 187 ctx.input_cur = GRPC_SLICE_START_PTR(input); 188 ctx.input_end = GRPC_SLICE_END_PTR(input); 189 ctx.output_cur = GRPC_SLICE_START_PTR(output); 190 ctx.output_end = GRPC_SLICE_END_PTR(output); 191 ctx.contains_tail = false; 192 193 if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) { 194 char* s = grpc_slice_to_c_string(input); 195 gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); 196 gpr_free(s); 197 grpc_slice_unref_internal(output); 198 return grpc_empty_slice(); 199 } 200 GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); 201 GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input)); 202 return output; 203 } 204 205 grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input, 206 size_t output_length) { 207 size_t input_length = GRPC_SLICE_LENGTH(input); 208 grpc_slice output = GRPC_SLICE_MALLOC(output_length); 209 struct grpc_base64_decode_context ctx; 210 211 // The length of a base64 string cannot be 4 * n + 1 212 if (GPR_UNLIKELY(input_length % 4 == 1)) { 213 gpr_log(GPR_ERROR, 214 "Base64 decoding failed, input of " 215 "grpc_chttp2_base64_decode_with_length has a length of %d, which " 216 "has a tail of 1 byte.\n", 217 static_cast<int>(input_length)); 218 grpc_slice_unref_internal(output); 219 return grpc_empty_slice(); 220 } 221 222 if (GPR_UNLIKELY(output_length > 223 input_length / 4 * 3 + tail_xtra[input_length % 4])) { 224 gpr_log( 225 GPR_ERROR, 226 "Base64 decoding failed, output_length %d is longer " 227 "than the max possible output length %d.\n", 228 static_cast<int>(output_length), 229 static_cast<int>(input_length / 4 * 3 + tail_xtra[input_length % 4])); 230 grpc_slice_unref_internal(output); 231 return grpc_empty_slice(); 232 } 233 234 ctx.input_cur = GRPC_SLICE_START_PTR(input); 235 ctx.input_end = GRPC_SLICE_END_PTR(input); 236 ctx.output_cur = GRPC_SLICE_START_PTR(output); 237 ctx.output_end = GRPC_SLICE_END_PTR(output); 238 ctx.contains_tail = true; 239 240 if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) { 241 char* s = grpc_slice_to_c_string(input); 242 gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); 243 gpr_free(s); 244 grpc_slice_unref_internal(output); 245 return grpc_empty_slice(); 246 } 247 GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); 248 GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input)); 249 return output; 250 } 251