/*********************************************************************** * * Copyright (C) 2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * * Author: Juan Carlos Luciani * ***********************************************************************/ //===[ Include files ]===================================================== #include "internal.h" //===[ Type definitions ]================================================== //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== // Tables for Base64 encoding and decoding static const int8_t g_Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const uint8_t g_Expand64[256] = { /* ASCII table */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }; //++======================================================================= CasaStatus EncodeData( IN const void *pData, IN const int32_t dataLen, INOUT char **ppEncodedData, INOUT int32_t *pEncodedDataLen) // // Arguments: // // Returns: // // Description: // // L2 //=======================================================================-- { CasaStatus retStatus; int encodedSize; char *pTmp; DbgTrace(3, "-EncodeData- Start\n", 0); // Determine the encoded size and allocate a buffer to hold the encoded data encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; pTmp = (char*) malloc(encodedSize); *ppEncodedData = pTmp; if (*ppEncodedData) { uint8_t *pOut, *pIn; int i; // Setup pointers to move through the buffers pIn = (uint8_t*) pData; pOut = (uint8_t*) *ppEncodedData; // Perform the encoding for (i = 0; i < dataLen - 2; i += 3) { *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; } if (i < dataLen) { *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; if (i == (dataLen - 1)) { *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; *pOut++ = '='; } else { *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; } *pOut++ = '='; } *pOut++ = '\0'; // Return the encoded data length *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); // Success retStatus = CASA_STATUS_SUCCESS; } else { DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= CasaStatus DecodeData( IN const char *pEncodedData, IN const int32_t encodedDataLen, // Does not include NULL terminator INOUT void **ppData, INOUT int32_t *pDataLen) // // Arguments: // // Returns: // // Description: // // L2 //=======================================================================-- { CasaStatus retStatus; int i, j; int decodedSize; DbgTrace(3, "-DecodeData- Start\n", 0); // Determine the decoded size for (i = 0, j = 0; i < encodedDataLen; i++) if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) j++; decodedSize = (j * 3 + 3) / 4; // Allocate buffer to hold the decoded data *ppData = malloc(decodedSize); if (*ppData) { bool endReached = false; uint8_t c0, c1, c2, c3; uint8_t *p, *q; // Initialize parameters that will be used during the decode operation c0 = c1 = c2 = c3 = 0; p = (uint8_t*) pEncodedData; q = (uint8_t*) *ppData; // Decode the data // // Loop through the data, piecing back information. Any newlines, and/or // carriage returns need to be skipped. while (j > 4) { while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) p++; if (64 == g_Expand64[*p]) { endReached = true; break; } c0 = *(p++); while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) p++; if (64 == g_Expand64[*p]) { *(q++) = (uint8_t)(g_Expand64[c0] << 2); j--; endReached = true; break; } c1 = *(p++); while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) p++; if (64 == g_Expand64[*p]) { *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); *(q++) = (uint8_t)(g_Expand64[c1] << 4); j -= 2; endReached = true; break; } c2 = *(p++); while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) p++; if (64 == g_Expand64[*p]) { *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); *(q++) = (uint8_t)(g_Expand64[c2] << 6); j -= 3; endReached = true; break; } c3 = *(p++); *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); j -= 4; } if (!endReached) { if (j > 1) *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); if (j > 2) *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); if (j > 3) *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); } // Return the length of the decoded data *pDataLen = (int32_t)(q - (uint8_t*)*ppData); // Success retStatus = CASA_STATUS_SUCCESS; } else { DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= int dtoul( IN char *cp, IN int len) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { int n = 0; int i; DbgTrace(2, "-dtoul- Start\n", 0); for (i = 0; i < len; i++, cp++) { // Verify that we are dealing with a valid digit if (*cp >= '0' && *cp <= '9') { n = 10 * n + (*cp - '0'); } else { DbgTrace(0, "-dtoul- Found invalid digit\n", 0); break; } } DbgTrace(2, "-dtoul- End, result = %d\n", n); return n; } //++======================================================================= //++======================================================================= //++=======================================================================