You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by bl...@apache.org on 2005/07/05 13:51:18 UTC
cvs commit: xml-security/c/src/dsig DSIGAlgorithmHandlerDefault.hpp DSIGAlgorithmHandlerDefault.cpp
blautenb 2005/07/05 04:51:18
Added: c/src/dsig DSIGAlgorithmHandlerDefault.hpp
DSIGAlgorithmHandlerDefault.cpp
Log:
Initial implementation of AlgorithmHandlers for DSIG algorithms
Revision Changes Path
1.1 xml-security/c/src/dsig/DSIGAlgorithmHandlerDefault.hpp
Index: DSIGAlgorithmHandlerDefault.hpp
===================================================================
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* XSEC
*
* DSIGAlgorithmHandlerDefault := Interface class to define handling of
* default signature algorithms
*
* $Id: DSIGAlgorithmHandlerDefault.hpp,v 1.1 2005/07/05 11:51:17 blautenb Exp $
*
*/
#ifndef DSIGALGHANDLERDEFAULT_INCLUDE
#define DSIGALGHANDLERDEFAULT_INCLUDE
// XSEC Includes
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECAlgorithmHandler.hpp>
class TXFMChain;
class XENCEncryptionMethod;
class XSECCryptoKey;
// Xerces
class DSIGAlgorithmHandlerDefault : public XSECAlgorithmHandler {
public:
virtual ~DSIGAlgorithmHandlerDefault() {};
virtual XSECAlgorithmHandler * clone(void) const;
// Signature ops
virtual bool appendSignatureHashTxfm(
TXFMChain * inputBytes,
const XMLCh * URI,
XSECCryptoKey * key
);
virtual unsigned int signToSafeBuffer(
TXFMChain * inputBytes,
const XMLCh * URI,
XSECCryptoKey * key,
unsigned int outputLength,
safeBuffer & result
);
virtual bool verifyBase64Signature(
TXFMChain * inputBytes,
const XMLCh * URI,
const char * sig,
unsigned int outputLength,
XSECCryptoKey * key
);
virtual bool appendHashTxfm(
TXFMChain * inputBytes,
const XMLCh * URI
);
// Unsupported Encryption Operations
virtual unsigned int decryptToSafeBuffer(
TXFMChain * cipherText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,
safeBuffer & result
);
virtual bool appendDecryptCipherTXFM(
TXFMChain * cipherText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc
);
virtual bool encryptToSafeBuffer(
TXFMChain * plainText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,
safeBuffer & result
);
virtual XSECCryptoKey * createKeyForURI(
const XMLCh * uri,
unsigned char * keyBuffer,
unsigned int keyLen
);
private:
};
/*\@}*/
#endif /* DSIGALGHANDLERDEFAULT_INCLUDE */
1.1 xml-security/c/src/dsig/DSIGAlgorithmHandlerDefault.cpp
Index: DSIGAlgorithmHandlerDefault.cpp
===================================================================
/*
* Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* XSEC
*
* XSECAlgorithmHandlerDefault := Interface class to define handling of
* default encryption algorithms
*
* $Id: DSIGAlgorithmHandlerDefault.cpp,v 1.1 2005/07/05 11:51:17 blautenb Exp $
*
*/
// XSEC Includes
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMSHA1.hpp>
#include <xsec/transformers/TXFMMD5.hpp>
#include <xsec/enc/XSECCryptoKey.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include "DSIGAlgorithmHandlerDefault.hpp"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/Janitor.hpp>
XERCES_CPP_NAMESPACE_USE
// --------------------------------------------------------------------------------
// Some useful utility functions
// --------------------------------------------------------------------------------
bool compareBase64StringToRaw(const char * b64Str,
unsigned char * raw,
unsigned int rawLen,
unsigned int maxCompare = 0) {
// Decode a base64 buffer and then compare the result to a raw buffer
// Compare at most maxCompare bits (if maxComare > 0)
// Note - whilst the other parameters are bytes, maxCompare is bits
unsigned char outputStr[1024];
unsigned int outputLen = 0;
XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64();
if (!b64) {
throw XSECException(XSECException::CryptoProviderError,
"Error requesting Base64 object from Crypto Provider");
}
Janitor<XSECCryptoBase64> j_b64(b64);
b64->decodeInit();
outputLen = b64->decode((unsigned char *) b64Str, (unsigned int) strlen((char *) b64Str), outputStr, 1024);
outputLen += b64->decodeFinish(&outputStr[outputLen], 1024 - outputLen);
// Compare
div_t d;
unsigned int maxCompareBytes, maxCompareBits;
maxCompareBits = 0;
unsigned int size;
if (maxCompare > 0) {
d = div(maxCompare, 8);
maxCompareBytes = d.quot;
if (d.rem != 0)
maxCompareBytes++;
if (rawLen < maxCompareBytes && outputLen < maxCompareBytes) {
if (rawLen != outputLen)
return false;
size = rawLen;
}
else if (rawLen < maxCompareBytes || outputLen < maxCompareBytes) {
return false;
}
else
size = maxCompareBytes;
}
else {
if (rawLen != outputLen)
return false;
size = rawLen;
}
// Compare bytes
unsigned int i, j;
for (i = 0; i < size; ++ i) {
if (raw[i] != outputStr[i])
return false;
}
// Compare bits
char mask = 0x01;
if (maxCompare != 0) {
for (j = 0 ; j < (unsigned int) d.rem; ++i) {
if ((raw[i] & mask) != (outputStr[i] & mask))
return false;
mask = mask << 1;
}
}
return true;
}
void convertRawToBase64String(safeBuffer &b64SB,
unsigned char * raw,
unsigned int rawLen,
unsigned int maxBits = 0) {
// Translate the rawbuffer (at most maxBits or rawLen - whichever is smaller)
// to a base64 string
unsigned char b64Str[1024];
unsigned int outputLen = 0;
XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64();
if (!b64) {
throw XSECException(XSECException::CryptoProviderError,
"Error requesting Base64 object from Crypto Provider");
}
Janitor<XSECCryptoBase64> j_b64(b64);
// Determine length to translate
unsigned int size;
if (maxBits > 0) {
div_t d = div(maxBits, 8);
size = d.quot;
if (d.rem != 0)
++size;
if (size > rawLen)
size = rawLen;
}
else
size = rawLen;
b64->encodeInit();
outputLen = b64->encode((unsigned char *) raw, rawLen, b64Str, 1024);
outputLen += b64->encodeFinish(&b64Str[outputLen], 1024 - outputLen);
b64Str[outputLen] = '\0';
// Copy out
b64SB.sbStrcpyIn((char *) b64Str);
}
// --------------------------------------------------------------------------------
// Clone
// --------------------------------------------------------------------------------
XSECAlgorithmHandler * DSIGAlgorithmHandlerDefault::clone(void) const {
DSIGAlgorithmHandlerDefault * ret;
XSECnew(ret, DSIGAlgorithmHandlerDefault);
return ret;
}
// --------------------------------------------------------------------------------
// Add a hash txfm
// --------------------------------------------------------------------------------
TXFMBase * addHashTxfm(signatureMethod sm, hashMethod hm, XSECCryptoKey * key,
DOMDocument * doc) {
// Given a hash method and signature method, create an appropriate TXFM
TXFMBase * txfm;
switch (hm) {
case HASH_SHA1 :
if (sm == SIGNATURE_HMAC){
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault::addHashTxfm - non HMAC key passed in to HMAC signature");
}
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA1, key));
}
else {
XSECnew(txfm, TXFMSHA1(doc));
}
break;
case HASH_SHA224 :
if (sm == SIGNATURE_HMAC){
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault::addHashTxfm - non HMAC key passed in to HMAC signature");
}
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA224, key));
}
else {
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA224));
}
break;
case HASH_SHA256 :
if (sm == SIGNATURE_HMAC){
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault::addHashTxfm - non HMAC key passed in to HMAC signature");
}
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA256, key));
}
else {
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA256));
}
break;
case HASH_SHA384 :
if (sm == SIGNATURE_HMAC){
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault::addHashTxfm - non HMAC key passed in to HMAC signature");
}
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA384, key));
}
else {
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA384));
}
break;
case HASH_SHA512 :
if (sm == SIGNATURE_HMAC){
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault::addHashTxfm - non HMAC key passed in to HMAC signature");
}
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA512, key));
}
else {
XSECnew(txfm, TXFMSHA1(doc, HASH_SHA512));
}
break;
default :
throw XSECException(XSECException::AlgorithmMapperError,
"Hash method unknown in DSIGAlgorithmHandlerDefault::addHashTxfm");
}
return txfm;
}
// --------------------------------------------------------------------------------
// Map a Signature hash
// --------------------------------------------------------------------------------
bool DSIGAlgorithmHandlerDefault::appendSignatureHashTxfm(TXFMChain * inputBytes,
const XMLCh * URI,
XSECCryptoKey * key) {
signatureMethod sm;
hashMethod hm;
// Map to internal constants
if (!XSECmapURIToSignatureMethods(URI, sm, hm)) {
safeBuffer sb;
sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : ");
sb.sbXMLChCat(URI);
throw XSECException(XSECException::AlgorithmMapperError,
sb.rawXMLChBuffer());
}
// Now append the appropriate hash transform onto the end of the chain
// If this is an HMAC of some kind - this function will add the appropriate key
TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument());
inputBytes->appendTxfm(htxfm);
return true;
}
// --------------------------------------------------------------------------------
// Sign
// --------------------------------------------------------------------------------
unsigned int DSIGAlgorithmHandlerDefault::signToSafeBuffer(
TXFMChain * inputBytes,
const XMLCh * URI,
XSECCryptoKey * key,
unsigned int outputLength,
safeBuffer & result) {
signatureMethod sm;
hashMethod hm;
// Map to internal constants
if (!XSECmapURIToSignatureMethods(URI, sm, hm)) {
safeBuffer sb;
sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : ");
sb.sbXMLChCat(URI);
throw XSECException(XSECException::AlgorithmMapperError,
sb.rawXMLChBuffer());
}
// Now append the appropriate hash transform onto the end of the chain
// If this is an HMAC of some kind - this function will add the appropriate key
TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument());
inputBytes->appendTxfm(htxfm);
unsigned char hash[4096];
int hashLen = inputBytes->getLastTxfm()->readBytes((XMLByte *) hash, 4096);
// Now check the calculated hash
char b64Buf[1024];
unsigned int b64Len;
safeBuffer b64SB;
switch (key->getKeyType()) {
case (XSECCryptoKey::KEY_DSA_PRIVATE) :
case (XSECCryptoKey::KEY_DSA_PAIR) :
if (sm != SIGNATURE_DSA) {
throw XSECException(XSECException::AlgorithmMapperError,
"Key type does not match <SignedInfo> signature type");
}
b64Len = ((XSECCryptoKeyDSA *) key)->signBase64Signature(
hash,
hashLen,
(char *) b64Buf,
1024);
if (b64Len <= 0) {
throw XSECException(XSECException::AlgorithmMapperError,
"Unknown error occured during a DSA Signing operation");
}
if (b64Buf[b64Len-1] == '\n')
b64Buf[b64Len-1] = '\0';
else
b64Buf[b64Len] = '\0';
break;
case (XSECCryptoKey::KEY_RSA_PRIVATE) :
case (XSECCryptoKey::KEY_RSA_PAIR) :
if (sm != SIGNATURE_RSA) {
throw XSECException(XSECException::AlgorithmMapperError,
"Key type does not match <SignedInfo> signature type");
}
b64Len = ((XSECCryptoKeyRSA *) key)->signSHA1PKCS1Base64Signature(
hash,
hashLen,
(char *) b64Buf,
1024);
if (b64Len <= 0) {
throw XSECException(XSECException::AlgorithmMapperError,
"Unknown error occured during a RSA Signing operation");
}
// Clean up some "funnies" and make sure the string is NULL terminated
if (b64Buf[b64Len-1] == '\n')
b64Buf[b64Len-1] = '\0';
else
b64Buf[b64Len] = '\0';
break;
case (XSECCryptoKey::KEY_HMAC) :
if (sm != SIGNATURE_HMAC) {
throw XSECException(XSECException::AlgorithmMapperError,
"Key type does not match <SignedInfo> signature type");
}
// Signature already created, so just translate to base 64 and enter string
convertRawToBase64String(b64SB,
hash,
hashLen,
outputLength);
strncpy(b64Buf, (char *) b64SB.rawBuffer(), 1024);
break;
default :
throw XSECException(XSECException::AlgorithmMapperError,
"Key found, but don't know how to sign the document using it");
}
result = b64Buf;
return strlen(b64Buf);
}
// --------------------------------------------------------------------------------
// Verify
// --------------------------------------------------------------------------------
bool DSIGAlgorithmHandlerDefault::verifyBase64Signature(
TXFMChain * inputBytes,
const XMLCh * URI,
const char * sig,
unsigned int outputLength,
XSECCryptoKey * key) {
signatureMethod sm;
hashMethod hm;
// Map to internal constants
if (!XSECmapURIToSignatureMethods(URI, sm, hm)) {
safeBuffer sb;
sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : ");
sb.sbXMLChCat(URI);
throw XSECException(XSECException::AlgorithmMapperError,
sb.rawXMLChBuffer());
}
// Now append the appropriate hash transform onto the end of the chain
// If this is an HMAC of some kind - this function will add the appropriate key
TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument());
inputBytes->appendTxfm(htxfm);
unsigned char hash[4096];
int hashLen = inputBytes->getLastTxfm()->readBytes((XMLByte *) hash, 4096);
// Now check the calculated hash
bool sigVfyRet = false;
switch (key->getKeyType()) {
case (XSECCryptoKey::KEY_DSA_PUBLIC) :
case (XSECCryptoKey::KEY_DSA_PAIR) :
if (sm != SIGNATURE_DSA) {
throw XSECException(XSECException::AlgorithmMapperError,
"Key type does not match <SignedInfo> signature type");
}
sigVfyRet = ((XSECCryptoKeyDSA *) key)->verifyBase64Signature(
hash,
hashLen,
(char *) sig,
strlen(sig));
break;
case (XSECCryptoKey::KEY_RSA_PUBLIC) :
case (XSECCryptoKey::KEY_RSA_PAIR) :
if (sm != SIGNATURE_RSA) {
throw XSECException(XSECException::AlgorithmMapperError,
"Key type does not match <SignedInfo> signature type");
}
sigVfyRet = ((XSECCryptoKeyRSA *) key)->verifySHA1PKCS1Base64Signature(
hash,
hashLen,
sig,
strlen(sig));
break;
case (XSECCryptoKey::KEY_HMAC) :
// Already done - just compare calculated value with read value
sigVfyRet = compareBase64StringToRaw(sig,
hash,
hashLen,
outputLength);
break;
default :
throw XSECException(XSECException::AlgorithmMapperError,
"Key found, but don't know how to check the signature using it");
}
return sigVfyRet;
}
// --------------------------------------------------------------------------------
// Hash TXFM appenders
// --------------------------------------------------------------------------------
bool DSIGAlgorithmHandlerDefault::appendHashTxfm(
TXFMChain * inputBytes,
const XMLCh * URI) {
hashMethod hm;
// Is this a URI we recognise?
if (!XSECmapURIToHashMethod(URI, hm)) {
safeBuffer sb;
sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown Hash URI : ");
sb.sbXMLChCat(URI);
throw XSECException(XSECException::AlgorithmMapperError,
sb.rawXMLChBuffer());
}
TXFMBase * txfm;
DOMDocument *d = inputBytes->getLastTxfm()->getDocument();
switch (hm) {
case HASH_SHA1 :
case HASH_SHA224 :
case HASH_SHA256 :
case HASH_SHA384 :
case HASH_SHA512 :
XSECnew(txfm, TXFMSHA1(d, hm));
break;
case HASH_MD5 :
XSECnew(txfm, TXFMMD5(d));
break;
default :
safeBuffer sb;
sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Internal error unknown Hash, but URI known. URI : ");
sb.sbXMLChCat(URI);
throw XSECException(XSECException::AlgorithmMapperError,
sb.rawXMLChBuffer());
}
inputBytes->appendTxfm(txfm);
return true;
}
// --------------------------------------------------------------------------------
// SafeBuffer decryption
// --------------------------------------------------------------------------------
unsigned int DSIGAlgorithmHandlerDefault::decryptToSafeBuffer(
TXFMChain * cipherText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
DOMDocument * doc,
safeBuffer & result
) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault - Encryption operations not supported");
}
bool DSIGAlgorithmHandlerDefault::appendDecryptCipherTXFM(
TXFMChain * cipherText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc
) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault - Encryption operations not supported");
}
// --------------------------------------------------------------------------------
// SafeBuffer encryption
// --------------------------------------------------------------------------------
bool DSIGAlgorithmHandlerDefault::encryptToSafeBuffer(
TXFMChain * plainText,
XENCEncryptionMethod * encryptionMethod,
XSECCryptoKey * key,
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,
safeBuffer & result
) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault - Encryption operations not supported");
}
// --------------------------------------------------------------------------------
// Key Creation
// --------------------------------------------------------------------------------
XSECCryptoKey * DSIGAlgorithmHandlerDefault::createKeyForURI(
const XMLCh * uri,
unsigned char * keyBuffer,
unsigned int keyLen
) {
throw XSECException(XSECException::AlgorithmMapperError,
"DSIGAlgorithmHandlerDefault - Key creation operations not supported");
}