Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/gmp-clearkey/0.1/ClearKeyBase64.cpp
Line
Count
Source (jump to first uncovered line)
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
#include <algorithm>
20
21
using namespace std;
22
23
/**
24
* Take a base64-encoded string, convert (in-place) each character to its
25
* corresponding value in the [0x00, 0x3f] range, and truncate any padding.
26
*/
27
static bool
28
Decode6Bit(string& aStr)
29
0
{
30
0
  for (size_t i = 0; i < aStr.length(); i++) {
31
0
    if (aStr[i] >= 'A' && aStr[i] <= 'Z') {
32
0
      aStr[i] -= 'A';
33
0
    }
34
0
    else if (aStr[i] >= 'a' && aStr[i] <= 'z') {
35
0
      aStr[i] -= 'a' - 26;
36
0
    }
37
0
    else if (aStr[i] >= '0' && aStr[i] <= '9') {
38
0
      aStr[i] -= '0' - 52;
39
0
    }
40
0
    else if (aStr[i] == '-' || aStr[i] == '+') {
41
0
      aStr[i] = 62;
42
0
    }
43
0
    else if (aStr[i] == '_' || aStr[i] == '/') {
44
0
      aStr[i] = 63;
45
0
    }
46
0
    else {
47
0
      // Truncate '=' padding at the end of the aString.
48
0
      if (aStr[i] != '=') {
49
0
        aStr.erase(i, string::npos);
50
0
        return false;
51
0
      }
52
0
      aStr[i] = '\0';
53
0
      aStr.resize(i);
54
0
      break;
55
0
    }
56
0
  }
57
0
58
0
  return true;
59
0
}
60
61
bool
62
DecodeBase64(const string& aEncoded, vector<uint8_t>& aOutDecoded)
63
0
{
64
0
  if (aEncoded.empty()) {
65
0
    aOutDecoded.clear();
66
0
    return true;
67
0
  }
68
0
  if (aEncoded.size() == 1) {
69
0
    // Invalid Base64 encoding.
70
0
    return false;
71
0
  }
72
0
  string encoded = aEncoded;
73
0
  if (!Decode6Bit(encoded)) {
74
0
    return false;
75
0
  }
76
0
77
0
  // The number of bytes we haven't yet filled in the current byte, mod 8.
78
0
  int shift = 0;
79
0
80
0
  aOutDecoded.resize((encoded.size() * 3) / 4);
81
0
  vector<uint8_t>::iterator out = aOutDecoded.begin();
82
0
  for (size_t i = 0; i < encoded.length(); i++) {
83
0
    if (!shift) {
84
0
      *out = encoded[i] << 2;
85
0
    }
86
0
    else {
87
0
      *out |= encoded[i] >> (6 - shift);
88
0
      out++;
89
0
      if (out == aOutDecoded.end()) {
90
0
        // Hit last 6bit octed in encoded, which is padding and can be ignored.
91
0
        break;
92
0
      }
93
0
      *out = encoded[i] << (shift + 2);
94
0
    }
95
0
    shift = (shift + 2) % 8;
96
0
  }
97
0
98
0
  return true;
99
0
}