mirror of https://github.com/ARMmbed/mbed-os.git
198 lines
6.1 KiB
C++
198 lines
6.1 KiB
C++
/*
|
|
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
|
* not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "base64b.h"
|
|
|
|
using namespace std;
|
|
|
|
static char IntToBase64Char(uint8_t intVal)
|
|
{
|
|
const char *base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
return base64Digits[intVal & 0x3F];
|
|
}
|
|
|
|
#define BASE_64_PAD 0xFF
|
|
static base64_result_e Base64CharToInt(char base64, uint8_t *intVal)
|
|
{
|
|
if (NULL == intVal) {
|
|
return BASE64_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((base64 >= 'A') && (base64 <= 'Z')) {
|
|
*intVal = base64 - 'A' ;
|
|
} else if ((base64 >= 'a') && (base64 <= 'z')) {
|
|
*intVal = base64 - 'a' + 26;
|
|
} else if ((base64 >= '0') && (base64 <= '9')) {
|
|
*intVal = base64 - '0' + 52;
|
|
} else if (base64 == '+') {
|
|
*intVal = 62;
|
|
} else if (base64 == '/') {
|
|
*intVal = 63;
|
|
} else if (base64 == '=') {
|
|
*intVal = BASE_64_PAD;
|
|
} else {
|
|
return BASE64_ERROR;
|
|
}
|
|
|
|
return BASE64_SUCCESS;
|
|
}
|
|
|
|
base64_result_e trng_DecodeNBase64(const char *string,
|
|
uint32_t stringMaxSize,
|
|
void *buffer,
|
|
uint32_t bufferSize,
|
|
uint32_t *lengthWritten,
|
|
uint32_t *charsProcessed)
|
|
{
|
|
base64_result_e result = BASE64_SUCCESS;
|
|
uint32_t bitOffset = 0;
|
|
uint8_t *writePtr = (uint8_t *)buffer;
|
|
uint8_t *bufferEnd = (uint8_t *)buffer + bufferSize;
|
|
uint8_t tempVal = 0;
|
|
uint32_t currPos = 0;
|
|
uint32_t localBytesWritten = 0;
|
|
uint32_t localCharsProcessed = 0;
|
|
bool isEndOfString = false;
|
|
|
|
if ((NULL == string) || (NULL == buffer) || (bufferSize == 0)) {
|
|
return BASE64_INVALID_PARAMETER;
|
|
}
|
|
|
|
*writePtr = 0;
|
|
while ((currPos < stringMaxSize) &&
|
|
(string[currPos] != 0) &&
|
|
(writePtr < bufferEnd) &&
|
|
(!isEndOfString)) {
|
|
uint8_t val;
|
|
|
|
if (string[currPos] == 0) {
|
|
break;
|
|
}
|
|
|
|
result = Base64CharToInt(string[currPos++], &val);
|
|
if (result != BASE64_SUCCESS) {
|
|
break;
|
|
}
|
|
|
|
if (val != BASE_64_PAD) {
|
|
if (bitOffset <= 2) {
|
|
tempVal |= val << (2 - bitOffset);
|
|
if (bitOffset == 2) {
|
|
*writePtr++ = tempVal;
|
|
tempVal = 0;
|
|
}
|
|
} else {
|
|
*writePtr++ = (uint8_t)(tempVal | (val >> (bitOffset - 2)));
|
|
tempVal = (uint8_t)(val << (10 - bitOffset));
|
|
}
|
|
} else { // found BASE_64_PAD
|
|
// At most two pad characters may occur at the end of the encoded stream
|
|
if (bitOffset == 2) {
|
|
isEndOfString = true; // The last padding byte has been processed.
|
|
} else if (bitOffset != 4) {
|
|
return BASE64_ERROR; // Incorrect padding
|
|
}
|
|
}
|
|
|
|
bitOffset = (bitOffset + 6) & 0x7;
|
|
if (bitOffset == 0) {
|
|
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
|
|
localCharsProcessed = currPos;
|
|
}
|
|
}
|
|
if (charsProcessed == NULL) {
|
|
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
|
|
} else {
|
|
*charsProcessed = localCharsProcessed;
|
|
}
|
|
if (lengthWritten != NULL) {
|
|
*lengthWritten = localBytesWritten;
|
|
} else if (bufferSize != localBytesWritten) {
|
|
return BASE64_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
// Check if additional bytes should have been processed but buffer isn't sufficient.
|
|
if ((result == BASE64_SUCCESS) &&
|
|
(!isEndOfString) &&
|
|
(currPos < stringMaxSize) &&
|
|
(string[currPos] != 0) &&
|
|
(string[currPos] != '=')) {
|
|
return BASE64_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (result != BASE64_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
return BASE64_SUCCESS;
|
|
}
|
|
|
|
base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize)
|
|
{
|
|
uint32_t bitOffset = 0;
|
|
|
|
const uint8_t *readPtr = (const uint8_t *)buffer;
|
|
const uint8_t *bufferEnd = (const uint8_t *)buffer + bufferSize;
|
|
|
|
char *writePtr = string;
|
|
char *stringEnd = string + stringSize - 1;
|
|
|
|
if ((NULL == string) || (NULL == buffer) || (stringSize == 0)) {
|
|
return BASE64_INVALID_PARAMETER;
|
|
}
|
|
|
|
stringSize--;
|
|
while (readPtr < bufferEnd && writePtr < stringEnd) {
|
|
uint8_t tempVal = 0;
|
|
switch (bitOffset) {
|
|
case 0:
|
|
*writePtr++ = IntToBase64Char(*readPtr >> 2); // take upper 6 bits
|
|
break;
|
|
case 6:
|
|
tempVal = *readPtr++ << 4;
|
|
if (readPtr < bufferEnd) {
|
|
tempVal |= *readPtr >> 4;
|
|
}
|
|
*writePtr++ = IntToBase64Char(tempVal);
|
|
break;
|
|
case 4:
|
|
tempVal = *readPtr++ << 2;
|
|
if (readPtr < bufferEnd) {
|
|
tempVal |= *readPtr >> 6;
|
|
}
|
|
*writePtr++ = IntToBase64Char(tempVal);
|
|
break;
|
|
case 2:
|
|
*writePtr++ = IntToBase64Char(*readPtr++);
|
|
break;
|
|
default:
|
|
return BASE64_ERROR; // we should never reach this code.
|
|
}
|
|
bitOffset = (bitOffset + 6) & 0x7;
|
|
}
|
|
while (bitOffset > 0 && writePtr < stringEnd) {
|
|
*writePtr++ = '=';
|
|
bitOffset = (bitOffset + 6) & 0x7;
|
|
}
|
|
*writePtr = 0;
|
|
|
|
if ((readPtr < bufferEnd) || (bitOffset != 0)) {
|
|
return (BASE64_BUFFER_TOO_SMALL);
|
|
}
|
|
|
|
return (BASE64_SUCCESS);
|
|
}
|