| 168 | return -1; |
| 169 | } |
| 170 | |
| 171 | static SC::Result scHttpWebSocketBase64Decode(SC::StringSpan value, SC::Span<uint8_t> output, size_t& decodedBytes) |
| 172 | { |
| 173 | decodedBytes = 0; |
| 174 | SC_TRY_MSG((value.sizeInBytes() % 4) == 0, "HttpWebSocketHandshake malformed base64 length"); |
| 175 | |
| 176 | for (size_t offset = 0; offset < value.sizeInBytes(); offset += 4) |
| 177 | { |
| 178 | int sextets[4] = {0, 0, 0, 0}; |
| 179 | int padding = 0; |
| 180 | for (size_t idx = 0; idx < 4; ++idx) |
| 181 | { |
| 182 | const char current = value.bytesWithoutTerminator()[offset + idx]; |
| 183 | if (current == '=') |
| 184 | { |
| 185 | SC_TRY_MSG(offset + idx >= value.sizeInBytes() - 2, "HttpWebSocketHandshake malformed base64 padding"); |
| 186 | sextets[idx] = 0; |
| 187 | padding++; |
| 188 | } |
| 189 | else |
| 190 | { |
| 191 | SC_TRY_MSG(padding == 0, "HttpWebSocketHandshake malformed base64 padding"); |
| 192 | sextets[idx] = scHttpWebSocketBase64Value(current); |
| 193 | SC_TRY_MSG(sextets[idx] >= 0, "HttpWebSocketHandshake malformed base64 character"); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | const uint32_t combined = (static_cast<uint32_t>(sextets[0]) << 18) | |
| 198 | (static_cast<uint32_t>(sextets[1]) << 12) | (static_cast<uint32_t>(sextets[2]) << 6) | |
| 199 | static_cast<uint32_t>(sextets[3]); |
| 200 | const size_t bytesThisBlock = 3 - static_cast<size_t>(padding); |
| 201 | SC_TRY_MSG(decodedBytes + bytesThisBlock <= output.sizeInBytes(), |
| 202 | "HttpWebSocketHandshake base64 decode output too small"); |
| 203 | if (bytesThisBlock >= 1) |
| 204 | { |
| 205 | output[decodedBytes++] = static_cast<uint8_t>((combined >> 16) & 0xFF); |
| 206 | } |
| 207 | if (bytesThisBlock >= 2) |
| 208 | { |
| 209 | output[decodedBytes++] = static_cast<uint8_t>((combined >> 8) & 0xFF); |
| 210 | } |
| 211 | if (bytesThisBlock >= 3) |
| 212 | { |
| 213 | output[decodedBytes++] = static_cast<uint8_t>(combined & 0xFF); |
| 214 | } |
| 215 | } |
| 216 | return SC::Result(true); |
| 217 | } |
| 218 | |
| 219 | static bool scHttpWebSocketForcePlatformSha1Unavailable = false; |
no test coverage detected