CASA/CASA-auth-token/client/mechanisms/pwd/util.c

283 lines
8.8 KiB
C

/***********************************************************************
*
* 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 <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include "internal.h"
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Debug Level
int DebugLevel = 0;
// 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_PWTOKEN,
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_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================