xmlsecurityengine/xmlseccrypto/src/xmlsecc_digests.cpp
changeset 0 e35f40988205
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlseccrypto/src/xmlsecc_digests.cpp	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,337 @@
+/** 
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+#include "xmlsecc_globals.h"
+
+#include <string.h>
+#include <e32err.h>
+#include "xmlsecc_config.h"
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_keys.h"
+#include "xmlsec_transforms.h"
+#include "xmlsec_errors.h"
+#include "xmlsec_error_flag.h"
+
+#include "xmlsecc_app.h"
+#include "xmlsecc_crypto.h"
+#include "xmlsecc_cryptowrapper.h"		// replace gnutils/gnutls.h
+
+//#define XMLSEC_SYMBIAN_MAX_DIGEST_SIZE		32
+
+/**************************************************************************
+ *
+ * Internal SymbianCrypto Digest CTX
+ *
+ *****************************************************************************/
+typedef struct _xmlSecSymbianCryptoDigestCtx 
+                               xmlSecSymbianCryptoDigestCtx, *xmlSecSymbianCryptoDigestCtxPtr;
+struct _xmlSecSymbianCryptoDigestCtx {
+    int			digest;
+    ScMDHd		digestCtx;
+    xmlSecByte	 	dgst[XMLSEC_SYMBIAN_MAX_DIGEST_SIZE];
+    xmlSecSize		dgstSize;	/* dgst size in bytes */
+};	    
+
+xmlSecTransformGetDataTypeMethod const xmlSecCrpytoGetDataTypeMethod  = xmlSecTransformDefaultGetDataType;
+xmlSecTransformPushBinMethod const xmlSecCryptoPushBinMethod = xmlSecTransformDefaultPushBin;
+xmlSecTransformPopBinMethod const xmlSecCryptoPopBinMethod = xmlSecTransformDefaultPopBin;
+
+/******************************************************************************
+ *
+ * Digest transforms
+ *
+ * xmlSecSymbianCryptoDigestCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecSymbianCryptoDigestSize	\
+    (sizeof(xmlSecTransform) + sizeof(xmlSecSymbianCryptoDigestCtx))	
+#define xmlSecSymbianCryptoDigestGetCtx(transform) \
+    ((xmlSecSymbianCryptoDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int 	xmlSecSymbianCryptoDigestInitialize		(xmlSecTransformPtr transform);
+static void 	xmlSecSymbianCryptoDigestFinalize		(xmlSecTransformPtr transform);
+static int	xmlSecSymbianCryptoDigestVerify		(xmlSecTransformPtr transform, 
+							 const xmlSecByte* data, 
+							 xmlSecSize dataSize,
+							 xmlSecTransformCtxPtr transformCtx);
+static int 	xmlSecSymbianCryptoDigestExecute		(xmlSecTransformPtr transform, 
+							 int last, 
+							 xmlSecTransformCtxPtr transformCtx);
+static int	xmlSecSymbianCryptoDigestCheckId		(xmlSecTransformPtr transform);
+
+static int
+xmlSecSymbianCryptoDigestCheckId(xmlSecTransformPtr transform) {
+
+#ifndef XMLSEC_NO_SHA1
+    if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) {
+	return(1);
+    }
+#endif /* XMLSEC_NO_SHA1 */    
+
+    return(0);
+}
+
+static int 
+xmlSecSymbianCryptoDigestInitialize(xmlSecTransformPtr transform) {
+    xmlSecSymbianCryptoDigestCtxPtr ctx;
+#ifndef XMLSEC_GNUTLS_OLD
+    TInt ret;
+#endif /* XMLSEC_GNUTLS_OLD */
+
+    xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1);
+
+    ctx = xmlSecSymbianCryptoDigestGetCtx(transform);
+    xmlSecAssert2(ctx, -1);
+
+    /* initialize context */
+    memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx));
+
+#ifndef XMLSEC_NO_SHA1
+    if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) {
+	ctx->digest = SC_MD_SHA1;
+    } else
+#endif /* XMLSEC_NO_SHA1 */    	
+
+    if(1) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+#ifndef XMLSEC_GNUTLS_OLD
+    ret = sc_md_open(&ctx->digestCtx, ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */
+    if(ret != KErrNone) {
+#else /* XMLSEC_GNUTLS_OLD */
+    ctx->digestCtx = sc_md_open(ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */
+    if(!ctx->digestCtx) {
+#endif /* XMLSEC_GNUTLS_OLD */
+    if ( ret != KErrNone )
+        {
+        xmlSecSetErrorFlag( ret );
+        }
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    "sc_md_open",
+		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    return(0);
+}
+
+static void 
+xmlSecSymbianCryptoDigestFinalize(xmlSecTransformPtr transform) {
+    xmlSecSymbianCryptoDigestCtxPtr ctx;
+
+    xmlSecAssert(xmlSecSymbianCryptoDigestCheckId(transform));
+    xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize));
+
+    ctx = xmlSecSymbianCryptoDigestGetCtx(transform);
+    xmlSecAssert(ctx);
+    
+    if(ctx->digestCtx) {
+	sc_md_close(ctx->digestCtx);
+    }
+    memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx));
+}
+
+static int
+xmlSecSymbianCryptoDigestVerify(xmlSecTransformPtr transform, 
+			const xmlSecByte* data, xmlSecSize dataSize,
+			xmlSecTransformCtxPtr transformCtx) {
+    xmlSecSymbianCryptoDigestCtxPtr ctx;
+    
+    xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1);
+    xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1);
+    xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+    xmlSecAssert2(data, -1);
+    xmlSecAssert2(transformCtx, -1);
+
+    ctx = xmlSecSymbianCryptoDigestGetCtx(transform);
+    xmlSecAssert2(ctx, -1);
+    xmlSecAssert2(ctx->dgstSize > 0, -1);
+    
+    if(dataSize != ctx->dgstSize) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_DATA,
+		    "data and digest sizes are different (data=%d, dgst=%d)", 
+		    dataSize, ctx->dgstSize);
+	transform->status = xmlSecTransformStatusFail;
+	return(0);
+    }
+    
+    if(memcmp(ctx->dgst, data, dataSize) != 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_DATA,
+		    "data and digest do not match");
+	transform->status = xmlSecTransformStatusFail;
+	return(0);
+    }
+    
+    transform->status = xmlSecTransformStatusOk;
+    return(0);
+}
+
+static int 
+xmlSecSymbianCryptoDigestExecute(xmlSecTransformPtr transform, 
+                                        int last, 
+                                        xmlSecTransformCtxPtr transformCtx) {
+    xmlSecSymbianCryptoDigestCtxPtr ctx;
+    xmlSecBufferPtr in, out;
+    int ret;
+    
+    xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) 
+                                || (transform->operation == xmlSecTransformOperationVerify), -1);
+    xmlSecAssert2(transformCtx, -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1);
+
+    ctx = xmlSecSymbianCryptoDigestGetCtx(transform);
+    xmlSecAssert2(ctx, -1);
+    xmlSecAssert2(ctx->digest != SC_MD_NONE, -1);
+    xmlSecAssert2(ctx->digestCtx, -1);
+
+    in = &(transform->inBuf);
+    out = &(transform->outBuf);
+
+    if(transform->status == xmlSecTransformStatusNone) {
+	transform->status = xmlSecTransformStatusWorking;
+    }
+    
+    if(transform->status == xmlSecTransformStatusWorking) {
+	xmlSecSize inSize;
+
+	inSize = xmlSecBufferGetSize(in);
+	if(inSize > 0) {
+	    sc_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize);
+	    
+	    ret = xmlSecBufferRemoveHead(in, inSize);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE, 
+			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+			    "xmlSecBufferRemoveHead",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "size=%d", inSize);
+		return(-1);
+	    }
+	}
+	if(last) {
+	    const xmlSecByte* buf;
+	    
+	    /* get the final digest */
+	    sc_md_final(ctx->digestCtx);
+	    
+	    /* get length before sc_md_read */
+	    ctx->dgstSize = sc_md_get_algo_dlen(ctx->digestCtx);
+	    xmlSecAssert2(ctx->dgstSize > 0, -1);
+	    xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1);
+	    
+	    buf = sc_md_read(ctx->digestCtx, ctx->digest);
+	    if(!buf) {
+		xmlSecError(XMLSEC_ERRORS_HERE, 
+			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+			    "sc_md_read",
+			    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+	        return(-1);
+	    }
+	    
+	    /* copy it to our internal buffer */
+	    memcpy(ctx->dgst, buf, ctx->dgstSize);
+
+	    /* and to the output if needed */
+	    if(transform->operation == xmlSecTransformOperationSign) {
+		ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize);
+		if(ret < 0) {
+		    xmlSecError(XMLSEC_ERRORS_HERE, 
+				xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+				"xmlSecBufferAppend",
+				XMLSEC_ERRORS_R_XMLSEC_FAILED,
+				"size=%d", ctx->dgstSize);
+		    return(-1);
+		}
+	    }
+	    transform->status = xmlSecTransformStatusFinished;
+	}
+    } else if(transform->status == xmlSecTransformStatusFinished) {
+	/* the only way we can get here is if there is no input */
+	xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+    } else {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_STATUS,
+		    "status=%d", transform->status);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+#ifndef XMLSEC_NO_SHA1
+/******************************************************************************
+ *
+ * SHA1 Digest transforms
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecSymbianCryptoSha1Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),		/* xmlSecSize klassSize */
+    xmlSecSymbianCryptoDigestSize,			/* xmlSecSize objSize */
+
+    /* data */
+    xmlSecNameSha1,						/* const xmlChar* name; */
+    xmlSecHrefSha1, 						/* const xmlChar* href; */
+    xmlSecTransformUsageDigestMethod,		/* xmlSecTransformUsage usage; */
+    
+    /* methods */
+    xmlSecSymbianCryptoDigestInitialize,		/* xmlSecTransformInitializeMethod initialize; */
+    xmlSecSymbianCryptoDigestFinalize,			/* xmlSecTransformFinalizeMethod finalize; */
+    NULL,					/* xmlSecTransformNodeReadMethod readNode; */
+    NULL,					/* xmlSecTransformNodeWriteMethod writeNode; */
+    NULL,					/* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    NULL,					/* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecSymbianCryptoDigestVerify,			/* xmlSecTransformVerifyMethod verify; */
+    xmlSecCrpytoGetDataTypeMethod,		/* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecCryptoPushBinMethod,		/* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecCryptoPopBinMethod,		/* xmlSecTransformPopBinMethod popBin; */
+    NULL,					/* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,					/* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecSymbianCryptoDigestExecute,			/* xmlSecTransformExecuteMethod execute; */
+    
+    NULL,					/* void* reserved0; */
+    NULL,					/* void* reserved1; */
+};
+
+/** 
+ * xmlSecSymbianCryptoTransformSha1GetKlass:
+ *
+ * SHA-1 digest transform klass.
+ *
+ * Returns pointer to SHA-1 digest transform klass.
+ */
+EXPORT_C
+xmlSecTransformId 
+xmlSecSymbianCryptoTransformSha1GetKlass(void) {
+    return(&xmlSecSymbianCryptoSha1Klass);
+}
+#endif /* XMLSEC_NO_SHA1 */
+
+
+
+