blautenb 2003/04/07 05:11:54
Added: c/src/enc/XSCrypt XSCryptCryptoBase64.cpp
XSCryptCryptoBase64.hpp
Log:
Internal implementation of Base64 encode/decode
Revision Changes Path
1.1 xml-security/c/src/enc/XSCrypt/XSCryptCryptoBase64.cpp
Index: XSCryptCryptoBase64.cpp
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "<WebSig>" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Institute for
* Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
* The development of this software was partly funded by the European
* Commission in the <WebSig> project in the ISIS Programme.
* For more information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* XSEC
*
* XSCryptCryptoBase64 := Internal implementation of a base64
* encoder/decoder
*
* Author(s): Berin Lautenbach
*
* $Id: XSCryptCryptoBase64.cpp,v 1.1 2003/04/07 12:11:54 blautenb Exp $
*
*/
#include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
//
--------------------------------------------------------------------------------
// Lookup tables and macros
//
--------------------------------------------------------------------------------
char Base64LookupTable[] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/',
};
#define IS_UPPER(c) (c >= 'A' && c <= 'Z')
#define IS_LOWER(c) (c >= 'a' && c <= 'z')
#define IS_NUMBR(c) (c >= '0' && c <= '9')
#define IS_OTHER(c) (c == '+' || c == '/')
#define IS_B64CH(c) (IS_LOWER(c) || IS_UPPER(c) || IS_NUMBR(c) || IS_OTHER(c))
#define IS_B64OE(c) (IS_B64CH(c) || c == '=')
//
--------------------------------------------------------------------------------
// Decoding
//
--------------------------------------------------------------------------------
unsigned char decodeCh(unsigned char c) {
if (IS_UPPER(c))
return c - 'A';
if (IS_LOWER(c))
return (c - 'a') + 26;
if (IS_NUMBR(c))
return (c - '0') + 52;
if (c == '+')
return 62;
if (c == '/')
return 63;
if (c == '=')
return 64;
return 65; // error;
}
void XSCryptCryptoBase64::canonicaliseInput(unsigned char *inData,
unsigned int inLength) {
// Canonicalise the input buffer into m_inputBuffer
unsigned char buf[400]; // Do 400 bytes at a time
unsigned int i, j;
j = 0;
for (i = 0; i < inLength; ++i) {
if (IS_B64OE(inData[i])) {
// Have a base64 or '=' char
buf[j++] = inData[i];
if (j == 400) {
m_inputBuffer.sbMemcpyIn(m_remainingInput, buf,
400);
m_remainingInput += 400;
j = 0;
}
}
}
if (j > 0) {
m_inputBuffer.sbMemcpyIn(m_remainingInput, buf, j);
m_remainingInput += j;
}
}
void XSCryptCryptoBase64::decodeInit(void) {
m_remainingInput = m_remainingOutput = 0;
m_allDone = false;
m_state = B64_DECODE;
}
unsigned int XSCryptCryptoBase64::decode(unsigned char * inData,
unsigned int
inLength,
unsigned char *
outData,
unsigned int
outLength) {
// Ensure we are in an appropriate state
if (m_state != B64_DECODE) {
throw XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Attempt to decode when not in decode
state");
}
// Copy the data into our input buffer
canonicaliseInput(inData, inLength);
unsigned int i = 0;
unsigned char t;
while (m_allDone != true && m_remainingInput - i >= 4) {
// BYTE 1
t = decodeCh(m_inputBuffer[i++]);
if (t > 63) {
throw
XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Invalid character at start of base 64
block");
}
m_outputBuffer[m_remainingOutput] = (t << 2);
// BYTE 2
t = decodeCh(m_inputBuffer[i++]);
if (t > 63) {
throw
XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Invalid character at start of base 64
block");
}
// Take top two bits and place at end of current byte
m_outputBuffer[m_remainingOutput] =
m_outputBuffer[m_remainingOutput] |
(t >> 4);
m_remainingOutput++; // Have a new complete byte
// Take remaining 4 bits and add to outputBuffer
m_outputBuffer[m_remainingOutput] = ( t << 4);
// BYTE 3
t = decodeCh(m_inputBuffer[i++]);
if (t > 64) {
throw
XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Invalid character at start of base 64
block");
}
if (t == 64) {
// '=' character found
m_allDone = true;
break;
}
// Take 4 bits and append to current buffer
m_outputBuffer[m_remainingOutput] =
m_outputBuffer[m_remainingOutput] | (t >> 2);
m_remainingOutput++;
// Take last 2 bits and append to buffer
m_outputBuffer[m_remainingOutput] = (t << 6);
// BYTE 4
t = decodeCh(m_inputBuffer[i++]);
if (t > 64) {
throw
XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Invalid character at start of base 64
block");
}
if (t == 64) {
m_allDone = true;
break;
}
// Place all six bits and end of current byte
m_outputBuffer[m_remainingOutput] =
m_outputBuffer[m_remainingOutput] | t;
m_remainingOutput++;
}
// Now whatever we've decoded can be placed in the output buffer
unsigned int cpyOut = (m_remainingOutput < outLength ?
m_remainingOutput : outLength);
m_outputBuffer.sbMemcpyOut(outData, cpyOut);
// Move the buffers down
if (cpyOut != m_remainingOutput) {
m_remainingOutput = m_remainingOutput - cpyOut;
m_outputBuffer.sbMemshift(0, cpyOut, m_remainingOutput);
}
else
m_remainingOutput = 0;
if (i != m_remainingInput) {
m_remainingInput -= i;
m_inputBuffer.sbMemshift(0, i, m_remainingInput);
}
else
m_remainingInput = 0;
// Return however much we have decoded
return cpyOut;
}
unsigned int XSCryptCryptoBase64::decodeFinish(unsigned char * outData,
unsigned
int outLength) {
if (m_state != B64_DECODE) {
throw XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Attempt to complete a decode when not
in decode state");
}
m_allDone = true;
unsigned int cpyOut = (m_remainingOutput < outLength ?
m_remainingOutput : outLength);
m_outputBuffer.sbMemcpyOut(outData, cpyOut);
// Move the buffers down
if (cpyOut != m_remainingOutput) {
m_remainingOutput = m_remainingOutput - cpyOut;
m_outputBuffer.sbMemshift(0, cpyOut, m_remainingOutput);
}
else {
m_remainingOutput = 0;
}
return cpyOut;
}
//
--------------------------------------------------------------------------------
// Encoding
//
--------------------------------------------------------------------------------
void XSCryptCryptoBase64::encodeInit(void) {
m_remainingInput = m_remainingOutput = 0;
m_allDone = false;
m_charCount = 0;
m_state = B64_ENCODE;
}
unsigned int XSCryptCryptoBase64::encode(unsigned char * inData,
unsigned int
inLength,
unsigned char *
outData,
unsigned int
outLength) {
if (m_state != B64_ENCODE) {
throw XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Attempt to encode when not in
encoding state");
}
// Copy input data into end of input buffer
m_inputBuffer.sbMemcpyIn(m_remainingInput, inData, inLength);
m_remainingInput += inLength;
unsigned int i = 0;
unsigned char t;
while (m_allDone == false && m_remainingInput - i >= 3) {
// Have a complete block of three bytes to encode
// First 6 bits;
t = (m_inputBuffer[i] >> 2);
m_outputBuffer[m_remainingOutput++] = Base64LookupTable[t];
// 2 bits from byte one and 4 from byte 2
t = ((m_inputBuffer[i++] << 4) & 0x30) | (m_inputBuffer[i] >>
4);
m_outputBuffer[m_remainingOutput++] = Base64LookupTable[t];
// 4 from byte 2 and 2 from byte 3
t = ((m_inputBuffer[i++] << 2) & 0x3C) | (m_inputBuffer[i] >>
6);
m_outputBuffer[m_remainingOutput++] = Base64LookupTable[t];
// last 6 bits from byte 3
t = m_inputBuffer[i++] & 0x3F;
m_outputBuffer[m_remainingOutput++] = Base64LookupTable[t];
m_charCount += 4;
if (m_charCount >= 76) {
m_outputBuffer[m_remainingOutput++] = '\n';
m_charCount = 0;
}
}
// Now copy data out to output buffer
unsigned int cpyOut = (m_remainingOutput < outLength ?
m_remainingOutput : outLength);
m_outputBuffer.sbMemcpyOut(outData, cpyOut);
// Move the buffers down
if (cpyOut != m_remainingOutput) {
m_remainingOutput = m_remainingOutput - cpyOut;
m_outputBuffer.sbMemshift(0, cpyOut, m_remainingOutput);
}
else
m_remainingOutput = 0;
if (i != m_remainingInput) {
m_remainingInput -= i;
m_inputBuffer.sbMemshift(0, i, m_remainingInput);
}
else
m_remainingInput = 0;
// Return however much we have decoded
return cpyOut;
}
unsigned int XSCryptCryptoBase64::encodeFinish(unsigned char * outData,
unsigned
int outLength) {
if (m_state != B64_ENCODE) {
throw XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Attempt to complete an encode when
not in encoding state");
}
if (m_allDone == false && m_remainingInput > 0) {
// Will always be < 3 characters remaining in inputBuffer
// If necessary - terminate the Base64 string
if (m_remainingInput >= 3) {
throw
XSECCryptoException(XSECCryptoException::Base64Error,
"XSCrypt:Base64 - Too much remaining input in
input buffer");
}
// First 6 bits;
unsigned int t = (m_inputBuffer[0] >> 2);
m_outputBuffer[m_remainingOutput++] = Base64LookupTable[t];
// 2 bits from byte one and 4 from byte 2
t = ((m_inputBuffer[0] << 4) & 0x30);
if (m_remainingInput == 1) {
m_outputBuffer[m_remainingOutput++] =
Base64LookupTable[t];
m_outputBuffer[m_remainingOutput++] = '=';
m_outputBuffer[m_remainingOutput++] = '=';
}
else {
t |= (m_inputBuffer[1] >> 4);
m_outputBuffer[m_remainingOutput++] =
Base64LookupTable[t];
// 4 from byte 2
t = ((m_inputBuffer[1] << 2) & 0x3C);
m_outputBuffer[m_remainingOutput++] =
Base64LookupTable[t];
m_outputBuffer[m_remainingOutput++] = '=';
}
}
m_allDone = true;
// Copy out
unsigned int cpyOut = (m_remainingOutput < outLength ?
m_remainingOutput : outLength);
m_outputBuffer.sbMemcpyOut(outData, cpyOut);
// Move the buffers down
if (cpyOut != m_remainingOutput) {
m_remainingOutput = m_remainingOutput - cpyOut;
m_outputBuffer.sbMemshift(0, cpyOut, m_remainingOutput);
}
else {
m_remainingOutput = 0;
}
return cpyOut;
}
1.1 xml-security/c/src/enc/XSCrypt/XSCryptCryptoBase64.hpp
Index: XSCryptCryptoBase64.hpp
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "<WebSig>" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Institute for
* Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
* The development of this software was partly funded by the European
* Commission in the <WebSig> project in the ISIS Programme.
* For more information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* XSEC
*
* XSCryptCryptoBase64 := Internal implementation of a base64 encoder/decoder
*
* Author(s): Berin Lautenbach
*
* $Id: XSCryptCryptoBase64.hpp,v 1.1 2003/04/07 12:11:54 blautenb Exp $
*
*/
#ifndef XSCRYPTCRYPTOBASE64_INCLUDE
#define XSCRYPTCRYPTOBASE64_INCLUDE
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/enc/XSECCryptoBase64.hpp>
#include <xsec/utils/XSECSafeBuffer.hpp>
class DSIG_EXPORT XSCryptCryptoBase64 : public XSECCryptoBase64 {
public :
// Constructors/Destructors
XSCryptCryptoBase64() : m_state(B64_UNINITIALISED) {};
virtual ~XSCryptCryptoBase64() {};
// Decoding Activities
virtual void decodeInit(void);
// Setup
virtual unsigned int decode(unsigned char * inData,
unsigned int
inLength,
unsigned char *
outData,
unsigned int
outLength); // decode
virtual unsigned int decodeFinish(unsigned char * outData,
unsigned
int outLength);// Finish
// Encoding activities
virtual void encodeInit(void);
// Setup
virtual unsigned int encode(unsigned char * inData,
unsigned int
inLength,
unsigned char *
outData,
unsigned int
outLength); // decode
virtual unsigned int encodeFinish(unsigned char * outData,
unsigned
int outLength); // Finish
private :
enum b64state {
B64_UNINITIALISED,
B64_ENCODE,
B64_DECODE,
};
safeBuffer m_inputBuffer; //
Carry over buffer
safeBuffer m_outputBuffer; //
Carry over output
unsigned int m_remainingInput; // Number of
bytes in carry input buffer
unsigned int m_remainingOutput; // Number of
bytes in carry output buffer
bool m_allDone;
// End found (=)
b64state m_state;
// What are we currently doing?
unsigned int m_charCount; // How many
characters in current line?
// Private functions
void canonicaliseInput(unsigned char *inData, unsigned int inLength);
};
#endif /* XSCRYPTCRYPTOBASE64_INCLUDE */