takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers base64b.cpp Source File

base64b.cpp

00001 /*
00002 * Copyright (c) 2018 ARM Limited. All rights reserved.
00003 * SPDX-License-Identifier: Apache-2.0
00004 * Licensed under the Apache License, Version 2.0 (the License); you may
00005 * not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 * http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 
00017 #include "base64b.h"
00018 
00019 using namespace std;
00020 
00021 static char IntToBase64Char(uint8_t intVal)
00022 {
00023     const char *base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00024     return base64Digits[intVal & 0x3F];
00025 }
00026 
00027 #define BASE_64_PAD 0xFF
00028 static base64_result_e Base64CharToInt(char base64, uint8_t *intVal)
00029 {
00030     if (NULL == intVal) {
00031         return BASE64_INVALID_PARAMETER;
00032     }
00033 
00034     if ((base64 >= 'A') && (base64 <= 'Z')) {
00035         *intVal = base64 - 'A' ;
00036     } else if ((base64 >= 'a') && (base64 <= 'z')) {
00037         *intVal = base64 - 'a' + 26;
00038     } else if ((base64 >= '0') && (base64 <= '9')) {
00039         *intVal = base64 - '0' + 52;
00040     } else if (base64 == '+') {
00041         *intVal = 62;
00042     } else if (base64 == '/') {
00043         *intVal = 63;
00044     } else if (base64 == '=') {
00045         *intVal = BASE_64_PAD;
00046     } else {
00047         return BASE64_ERROR;
00048     }
00049 
00050     return BASE64_SUCCESS;
00051 }
00052 
00053 base64_result_e trng_DecodeNBase64(const char *string,
00054                                    uint32_t stringMaxSize,
00055                                    void *buffer,
00056                                    uint32_t bufferSize,
00057                                    uint32_t *lengthWritten,
00058                                    uint32_t *charsProcessed)
00059 {
00060     base64_result_e result = BASE64_SUCCESS;
00061     uint32_t bitOffset = 0;
00062     uint8_t *writePtr = (uint8_t *)buffer;
00063     uint8_t *bufferEnd = (uint8_t *)buffer + bufferSize;
00064     uint8_t tempVal = 0;
00065     uint32_t currPos = 0;
00066     uint32_t localBytesWritten = 0;
00067     uint32_t localCharsProcessed = 0;
00068     bool isEndOfString = false;
00069 
00070     if ((NULL == string) || (NULL == buffer) || (bufferSize == 0)) {
00071         return BASE64_INVALID_PARAMETER;
00072     }
00073 
00074     *writePtr = 0;
00075     while (( currPos < stringMaxSize ) &&
00076             ( string[currPos] != 0 ) &&
00077             ( writePtr  <  bufferEnd ) &&
00078             ( !isEndOfString )) {
00079         uint8_t val;
00080 
00081         if (string[currPos] == 0) {
00082             break;
00083         }
00084 
00085         result = Base64CharToInt(string[currPos++], &val);
00086         if (result != BASE64_SUCCESS) {
00087             break;
00088         }
00089 
00090         if (val != BASE_64_PAD) {
00091             if (bitOffset <= 2) {
00092                 tempVal |= val << (2 - bitOffset);
00093                 if (bitOffset == 2) {
00094                     *writePtr++ = tempVal;
00095                     tempVal = 0;
00096                 }
00097             } else {
00098                 *writePtr++ = (uint8_t)(tempVal | (val >> (bitOffset - 2)));
00099                 tempVal = (uint8_t)(val << (10 - bitOffset));
00100             }
00101         } else { // found BASE_64_PAD
00102             // At most two pad characters may occur at the end of the encoded stream
00103             if (bitOffset == 2) {
00104                 isEndOfString = true;    // The last padding byte has been processed.
00105             } else if (bitOffset != 4) {
00106                 return BASE64_ERROR;    // Incorrect padding
00107             }
00108         }
00109 
00110         bitOffset = (bitOffset + 6) & 0x7;
00111         if (bitOffset == 0) {
00112             localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
00113             localCharsProcessed = currPos;
00114         }
00115     }
00116     if (charsProcessed == NULL) {
00117         localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
00118     } else {
00119         *charsProcessed = localCharsProcessed;
00120     }
00121     if (lengthWritten != NULL) {
00122         *lengthWritten = localBytesWritten;
00123     } else if (bufferSize != localBytesWritten) {
00124         return BASE64_BUFFER_TOO_SMALL;
00125     }
00126 
00127     // Check if additional bytes should have been processed but buffer isn't sufficient.
00128     if (( result == BASE64_SUCCESS ) &&
00129             ( !isEndOfString ) &&
00130             ( currPos < stringMaxSize ) &&
00131             ( string[currPos] != 0 ) &&
00132             ( string[currPos] != '=' ) ) {
00133         return BASE64_BUFFER_TOO_SMALL;
00134     }
00135 
00136     if (result != BASE64_SUCCESS) {
00137         return result;
00138     }
00139 
00140     return BASE64_SUCCESS;
00141 }
00142 
00143 base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize)
00144 {
00145     uint32_t bitOffset = 0;
00146 
00147     const uint8_t *readPtr = (const uint8_t *)buffer;
00148     const uint8_t *bufferEnd = (const uint8_t *)buffer + bufferSize;
00149 
00150     char *writePtr = string;
00151     char *stringEnd = string + stringSize - 1;
00152 
00153     if ((NULL == string) || (NULL == buffer) || (stringSize == 0)) {
00154         return BASE64_INVALID_PARAMETER;
00155     }
00156 
00157     stringSize--;
00158     while (readPtr < bufferEnd && writePtr < stringEnd) {
00159         uint8_t tempVal = 0;
00160         switch (bitOffset) {
00161             case 0:
00162                 *writePtr++ = IntToBase64Char(*readPtr >> 2);                 // take upper 6 bits
00163                 break;
00164             case 6:
00165                 tempVal = *readPtr++ << 4;
00166                 if (readPtr < bufferEnd) {
00167                     tempVal |= *readPtr >> 4;
00168                 }
00169                 *writePtr++ = IntToBase64Char(tempVal);
00170                 break;
00171             case 4:
00172                 tempVal = *readPtr++ << 2;
00173                 if (readPtr < bufferEnd) {
00174                     tempVal |= *readPtr >> 6;
00175                 }
00176                 *writePtr++ = IntToBase64Char(tempVal);
00177                 break;
00178             case 2:
00179                 *writePtr++ = IntToBase64Char(*readPtr++);
00180                 break;
00181             default:
00182                 return BASE64_ERROR; // we should never reach this code.
00183         }
00184         bitOffset = (bitOffset + 6) & 0x7;
00185     }
00186     while (bitOffset > 0 && writePtr < stringEnd) {
00187         *writePtr++ = '=';
00188         bitOffset = (bitOffset + 6) & 0x7;
00189     }
00190     *writePtr = 0;
00191 
00192     if ((readPtr < bufferEnd) || (bitOffset != 0)) {
00193         return (BASE64_BUFFER_TOO_SMALL);
00194     }
00195 
00196     return (BASE64_SUCCESS);
00197 }