tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ClearKeyBase64.cpp (2455B)


      1 /*
      2 * Copyright 2015, Mozilla Foundation and contributors
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include "ClearKeyBase64.h"
     18 
     19 using std::string;
     20 using std::vector;
     21 
     22 /**
     23 * Take a base64-encoded string, convert (in-place) each character to its
     24 * corresponding value in the [0x00, 0x3f] range, and truncate any padding.
     25 */
     26 static bool Decode6Bit(string& aStr) {
     27  for (size_t i = 0; i < aStr.length(); i++) {
     28    if (aStr[i] >= 'A' && aStr[i] <= 'Z') {
     29      aStr[i] -= 'A';
     30    } else if (aStr[i] >= 'a' && aStr[i] <= 'z') {
     31      aStr[i] -= 'a' - 26;
     32    } else if (aStr[i] >= '0' && aStr[i] <= '9') {
     33      aStr[i] -= '0' - 52;
     34    } else if (aStr[i] == '-' || aStr[i] == '+') {
     35      aStr[i] = 62;
     36    } else if (aStr[i] == '_' || aStr[i] == '/') {
     37      aStr[i] = 63;
     38    } else {
     39      // Truncate '=' padding at the end of the aString.
     40      if (aStr[i] != '=') {
     41        aStr.erase(i, string::npos);
     42        return false;
     43      }
     44      aStr[i] = '\0';
     45      aStr.resize(i);
     46      break;
     47    }
     48  }
     49 
     50  return true;
     51 }
     52 
     53 bool DecodeBase64(const string& aEncoded, vector<uint8_t>& aOutDecoded) {
     54  if (aEncoded.empty()) {
     55    aOutDecoded.clear();
     56    return true;
     57  }
     58  if (aEncoded.size() == 1) {
     59    // Invalid Base64 encoding.
     60    return false;
     61  }
     62  string encoded = aEncoded;
     63  if (!Decode6Bit(encoded)) {
     64    return false;
     65  }
     66 
     67  // The number of bytes we haven't yet filled in the current byte, mod 8.
     68  int shift = 0;
     69 
     70  aOutDecoded.resize((encoded.size() * 3) / 4);
     71  vector<uint8_t>::iterator out = aOutDecoded.begin();
     72  for (size_t i = 0; i < encoded.length(); i++) {
     73    if (!shift) {
     74      *out = encoded[i] << 2;
     75    } else {
     76      *out |= encoded[i] >> (6 - shift);
     77      out++;
     78      if (out == aOutDecoded.end()) {
     79        // Hit last 6bit octed in encoded, which is padding and can be ignored.
     80        break;
     81      }
     82      *out = encoded[i] << (shift + 2);
     83    }
     84    shift = (shift + 2) % 8;
     85  }
     86 
     87  return true;
     88 }