cryptomgmtlibs/securityutils/source/secutil/base64.cpp
changeset 0 2c201484c85f
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Base64 encoding and decoding functions.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 /**
       
    23  @file
       
    24 */
       
    25 
       
    26 #include "base64.h"
       
    27 
       
    28 // Constants used by the Base64 algorithm
       
    29 const TUint8 TBase64::iAlphabet[] =
       
    30 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
       
    31 const TInt8 KImcvLookUpStartOffset = 43;
       
    32 const TUint8 KImcvConvEquals = '=';
       
    33 const TInt8 AsciiToBase64[80]=
       
    34 	{
       
    35 	 62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
       
    36 	 57, 58, 59, 60, 61, -1, -1, -1, 64, -1,
       
    37 	 -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,
       
    38 	  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       
    39 	 18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
       
    40 	 -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
       
    41 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
       
    42 	 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
       
    43 	};
       
    44 const TInt8 Base64ToAscii[65]=
       
    45 	{
       
    46 	 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
       
    47 	 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
       
    48 	 85, 86, 87, 88, 89, 90, 97, 98, 99,100,
       
    49 	101,102,103,104,105,106,107,108,109,110,
       
    50 	111,112,113,114,115,116,117,118,119,120,
       
    51 	121,122, 48, 49, 50, 51, 52, 53, 54, 55,
       
    52 	 56, 57, 43, 47, 61
       
    53 	};
       
    54 
       
    55 EXPORT_C TBase64::TBase64() :
       
    56 	iShiftStored(0),
       
    57 	iMaskShiftStored(ESix)
       
    58 	{
       
    59 	}
       
    60 
       
    61 EXPORT_C void TBase64::Initialize()
       
    62 	{
       
    63 	iMaskShiftStored = ESix;
       
    64 	}
       
    65 
       
    66 //Encodes data to Base64.
       
    67 EXPORT_C HBufC8* TBase64::EncodeLC(const TDesC8& aSrcString)
       
    68 	{
       
    69 	// Allocate and clear destination string
       
    70 	TInt destLen = ((aSrcString.Length() - 1) / 3 + 1) * 4;
       
    71 	HBufC8* destString = HBufC8::NewMaxLC(destLen);
       
    72 	TPtr8 destPtr = destString->Des();
       
    73 
       
    74 	// Initialise variables
       
    75 	const TUint8* srcStringPtr = aSrcString.Ptr();
       
    76 	const TUint8* srcStringEnd = aSrcString.Length() + srcStringPtr;
       
    77 	TUint8* destStringPtr = (TUint8*)destString->Ptr();
       
    78 	TUint8* destStringPtrBase = destStringPtr;
       
    79 
       
    80 	TInt character = 0;
       
    81 	TUint8 encodedChar = 0;
       
    82 	TInt charStorage = 0;
       
    83  	TInt maskShift = EZero;
       
    84 
       
    85 	while (srcStringPtr <= srcStringEnd)
       
    86 		{
       
    87 		// maskShift is used as a char read counter
       
    88 		if(maskShift == ESix)
       
    89 			{
       
    90 			// If the 3rd char read is also the last char then the while loop
       
    91 			// is broken on the next check.
       
    92 			if(srcStringPtr == srcStringEnd)
       
    93 				srcStringPtr++;
       
    94 			maskShift = EZero;
       
    95 			character = 0;
       
    96 			}
       
    97 		else
       
    98 			{
       
    99 			if (srcStringPtr == srcStringEnd)
       
   100 				character=0;
       
   101 			else
       
   102 				character = *srcStringPtr;
       
   103 
       
   104 			srcStringPtr++;
       
   105 			// Shifts charStorage ready for the next char
       
   106 			charStorage = charStorage << 8;
       
   107 			maskShift += ETwo;
       
   108 			}
       
   109 		charStorage = charStorage | character;
       
   110 		// Shifts the mask to the correct bit location
       
   111 		// Masks (AND's) the valid bits from charStorage
       
   112 		// Shifts the valid bits into the low order 8bits
       
   113 		// Converts to BASE64 char, Casts the result to an unsigned
       
   114 		// char (which it should be ?....I hope)
       
   115 		encodedChar = (TUint8)Base64ToAscii[((charStorage >> maskShift) & ESixBitMask)];
       
   116 		*destStringPtr++ = encodedChar;
       
   117 		}
       
   118 
       
   119 	// Check for not enough chars and pad if required
       
   120 	if (maskShift == EFour)
       
   121 		{
       
   122 		*destStringPtr++ = KImcvConvEquals;
       
   123 		*destStringPtr++ = KImcvConvEquals;
       
   124 		}
       
   125 	else
       
   126 		if (maskShift == ESix)
       
   127 			*destStringPtr++ = KImcvConvEquals;
       
   128 
       
   129 	destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase));
       
   130 	return destString;
       
   131 	}
       
   132 
       
   133 //Decodes Base64-encoded data.
       
   134 EXPORT_C HBufC8* TBase64::DecodeLC(const TDesC8& aSrcString, TBool& aNeedMoreData)
       
   135 	{
       
   136 	// The source string must be a multiple of 4 bytes long
       
   137 	if (aSrcString.Length() & 0x3)
       
   138 		{
       
   139 		User::Leave(KErrCorrupt);
       
   140 		}
       
   141 
       
   142 	TInt decodedInt = 0;
       
   143 	TInt8 offsetChar = 0;
       
   144 	TUint8 decodedChar = 0;
       
   145 
       
   146     // Find out how long the decoded string will be.
       
   147     TInt outLen = aSrcString.Length() / 4 * 3;
       
   148     if (aSrcString[aSrcString.Length() - 1] == '=')
       
   149         outLen--;
       
   150     if (aSrcString[aSrcString.Length() - 2] == '=')
       
   151         outLen--;
       
   152 
       
   153 	// Construct output buffer.
       
   154 	HBufC8* destString = HBufC8::NewMaxLC(outLen);
       
   155 	TPtr8 destPtr = destString->Des();
       
   156 	destPtr.Zero();
       
   157 
       
   158 	// Initialise variables
       
   159 	const TUint8* srcStringPtr = aSrcString.Ptr();
       
   160 	const TUint8* srcStringEnd = aSrcString.Length() + srcStringPtr;
       
   161 	TUint8* destStringPtr = (TUint8*)destString->Ptr();
       
   162 	TUint8* destStringPtrBase = destStringPtr;
       
   163 	TInt maskShift = iMaskShiftStored;
       
   164 	TInt shiftStorage = iShiftStored;
       
   165 
       
   166 	// Main character process loop
       
   167 	while (srcStringPtr<srcStringEnd)
       
   168 		{
       
   169 		offsetChar = (TInt8)(*srcStringPtr - KImcvLookUpStartOffset);
       
   170 		srcStringPtr++;
       
   171 
       
   172 		// Check for valid B64 character
       
   173 		if ((offsetChar >= 0) && (offsetChar < 80))
       
   174 			{
       
   175 			// Read in next character and B64 decode
       
   176 			decodedInt = AsciiToBase64[offsetChar];
       
   177 
       
   178 			// Exits when a PAD char is reached
       
   179 			if(decodedInt == EPadChar)
       
   180 				{
       
   181 				destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase));
       
   182 				aNeedMoreData = EFalse;
       
   183 				return destString;
       
   184 				}
       
   185 
       
   186 			// Ensures the first 2 chars of 4 are received before processing
       
   187 			if(maskShift == ESix)
       
   188 				maskShift = EFour;
       
   189 			else
       
   190 				{
       
   191 				shiftStorage = shiftStorage << ESix;
       
   192 				shiftStorage = shiftStorage | decodedInt;
       
   193 				decodedChar = (TUint8)((shiftStorage >> maskShift) & EEightBitMask);
       
   194 
       
   195 				if((maskShift -= ETwo) < EZero)
       
   196 					maskShift = ESix;
       
   197 
       
   198 				*destStringPtr++ = decodedChar;
       
   199 				}
       
   200 			shiftStorage = decodedInt;
       
   201 			}
       
   202 		}
       
   203 	iShiftStored = shiftStorage;
       
   204 	iMaskShiftStored = maskShift;
       
   205 
       
   206 	destPtr.SetLength((TInt)(destStringPtr - destStringPtrBase));
       
   207 	aNeedMoreData = maskShift < ESix;
       
   208 	return destString;
       
   209 	}
       
   210