[xmlsec] add des kw support for xmlsec-gnutls



commit 2e681eb13ac301e53062e41470af2ceedfb1a4f0
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Sun May 9 12:59:11 2010 -0700

    add des kw support for xmlsec-gnutls

 src/gnutls/kw_des.c |  610 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 610 insertions(+), 0 deletions(-)
---
diff --git a/src/gnutls/kw_des.c b/src/gnutls/kw_des.c
new file mode 100644
index 0000000..a16a711
--- /dev/null
+++ b/src/gnutls/kw_des.c
@@ -0,0 +1,610 @@
+/**
+ *
+ * XMLSec library
+ *
+ * DES Algorithm support
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#ifndef XMLSEC_NO_DES
+#include "globals.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gnutls/gnutls.h>
+#include <gcrypt.h>
+
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+#include "../kw_aes_des.h"
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int       xmlSecGnuTLSKWDes3GenerateRandom               (void * context,
+                                                                 xmlSecByte * out, 
+                                                                 xmlSecSize outSize);
+static int       xmlSecGnuTLSKWDes3Sha1                         (void * context,
+                                                                 const xmlSecByte * in, 
+                                                                 xmlSecSize inSize, 
+                                                                 xmlSecByte * out, 
+                                                                 xmlSecSize outSize);
+static int      xmlSecGnuTLSKWDes3BlockEncrypt                  (void * context,
+                                                                 const xmlSecByte * iv, 
+                                                                 xmlSecSize ivSize,
+                                                                 const xmlSecByte * in, 
+                                                                 xmlSecSize inSize,
+                                                                 xmlSecByte * out, 
+                                                                 xmlSecSize outSize);
+static int      xmlSecGnuTLSKWDes3BlockDecrypt                  (void * context,
+                                                                 const xmlSecByte * iv, 
+                                                                 xmlSecSize ivSize,
+                                                                 const xmlSecByte * in, 
+                                                                 xmlSecSize inSize,
+                                                                 xmlSecByte * out, 
+                                                                 xmlSecSize outSize);
+
+static xmlSecKWDes3Klass xmlSecGnuTLSKWDes3ImplKlass = {
+    /* callbacks */
+    xmlSecGnuTLSKWDes3GenerateRandom,       /* xmlSecKWDes3GenerateRandomMethod     generateRandom; */
+    xmlSecGnuTLSKWDes3Sha1,                 /* xmlSecKWDes3Sha1Method               sha1; */
+    xmlSecGnuTLSKWDes3BlockEncrypt,         /* xmlSecKWDes3BlockEncryptMethod       encrypt; */
+    xmlSecGnuTLSKWDes3BlockDecrypt,         /* xmlSecKWDes3BlockDecryptMethod       decrypt; */
+
+    /* for the future */
+    NULL,                                   /* void*                               reserved0; */
+    NULL,                                   /* void*                               reserved1; */
+};
+
+static int      xmlSecGnuTLSKWDes3Encrypt                       (const xmlSecByte *key, 
+                                                                 xmlSecSize keySize,
+                                                                 const xmlSecByte *iv, 
+                                                                 xmlSecSize ivSize,
+                                                                 const xmlSecByte *in, 
+                                                                 xmlSecSize inSize,
+                                                                 xmlSecByte *out, 
+                                                                 xmlSecSize outSize, 
+                                                                 int enc);
+
+
+/*********************************************************************
+ *
+ * Triple DES Key Wrap transform
+ *
+ * key (xmlSecBuffer) is located after xmlSecTransform structure
+ *
+ ********************************************************************/
+typedef struct _xmlSecGnuTLSKWDes3Ctx              xmlSecGnuTLSKWDes3Ctx,
+                                                  *xmlSecGnuTLSKWDes3CtxPtr;
+struct _xmlSecGnuTLSKWDes3Ctx {
+    xmlSecBuffer        keyBuffer;
+};
+#define xmlSecGnuTLSKWDes3Size     \
+    (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSKWDes3Ctx))
+#define xmlSecGnuTLSKWDes3GetCtx(transform) \
+    ((xmlSecGnuTLSKWDes3CtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int      xmlSecGnuTLSKWDes3Initialize                    (xmlSecTransformPtr transform);
+static void     xmlSecGnuTLSKWDes3Finalize                      (xmlSecTransformPtr transform);
+static int      xmlSecGnuTLSKWDes3SetKeyReq                     (xmlSecTransformPtr transform,
+                                                                 xmlSecKeyReqPtr keyReq);
+static int      xmlSecGnuTLSKWDes3SetKey                        (xmlSecTransformPtr transform,
+                                                                 xmlSecKeyPtr key);
+static int      xmlSecGnuTLSKWDes3Execute                       (xmlSecTransformPtr transform,
+                                                                 int last,
+                                                                 xmlSecTransformCtxPtr transformCtx);
+static xmlSecTransformKlass xmlSecGnuTLSKWDes3Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
+    xmlSecGnuTLSKWDes3Size,                     /* xmlSecSize objSize */
+
+    xmlSecNameKWDes3,                           /* const xmlChar* name; */
+    xmlSecHrefKWDes3,                           /* const xmlChar* href; */
+    xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
+
+    xmlSecGnuTLSKWDes3Initialize,               /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecGnuTLSKWDes3Finalize,                 /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecGnuTLSKWDes3SetKeyReq,                /* xmlSecTransformSetKeyMethod setKeyReq; */
+    xmlSecGnuTLSKWDes3SetKey,                   /* xmlSecTransformSetKeyMethod setKey; */
+    NULL,                                       /* xmlSecTransformValidateMethod validate; */
+    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecGnuTLSKWDes3Execute,                  /* xmlSecTransformExecuteMethod execute; */
+
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSTransformKWDes3GetKlass:
+ *
+ * The Triple DES key wrapper transform klass.
+ *
+ * Returns: Triple DES key wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecGnuTLSTransformKWDes3GetKlass(void) {
+    return(&xmlSecGnuTLSKWDes3Klass);
+}
+
+static int
+xmlSecGnuTLSKWDes3Initialize(xmlSecTransformPtr transform) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx;
+    int ret;
+
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformKWDes3Id), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSKWDes3Size), -1);
+
+    ctx = xmlSecGnuTLSKWDes3GetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    "xmlSecBufferInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    return(0);
+}
+
+static void
+xmlSecGnuTLSKWDes3Finalize(xmlSecTransformPtr transform) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx;
+
+    xmlSecAssert(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformKWDes3Id));
+    xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSKWDes3Size));
+
+    ctx = xmlSecGnuTLSKWDes3GetCtx(transform);
+    xmlSecAssert(ctx != NULL);
+
+    xmlSecBufferFinalize(&(ctx->keyBuffer));
+}
+
+static int
+xmlSecGnuTLSKWDes3SetKeyReq(xmlSecTransformPtr transform,  xmlSecKeyReqPtr keyReq) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx;
+
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformKWDes3Id), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSKWDes3Size), -1);
+    xmlSecAssert2(keyReq != NULL, -1);
+
+    ctx = xmlSecGnuTLSKWDes3GetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    keyReq->keyId       = xmlSecGnuTLSKeyDataDesId;
+    keyReq->keyType     = xmlSecKeyDataTypeSymmetric;
+    if(transform->operation == xmlSecTransformOperationEncrypt) {
+        keyReq->keyUsage= xmlSecKeyUsageEncrypt;
+    } else {
+        keyReq->keyUsage= xmlSecKeyUsageDecrypt;
+    }
+    keyReq->keyBitsSize = 8 * XMLSEC_KW_DES3_KEY_LENGTH;
+    return(0);
+}
+
+static int
+xmlSecGnuTLSKWDes3SetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx;
+    xmlSecBufferPtr buffer;
+    xmlSecSize keySize;
+    int ret;
+
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformKWDes3Id), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSKWDes3Size), -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGnuTLSKeyDataDesId), -1);
+
+    ctx = xmlSecGnuTLSKWDes3GetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+    xmlSecAssert2(buffer != NULL, -1);
+
+    keySize = xmlSecBufferGetSize(buffer);
+    if(keySize < XMLSEC_KW_DES3_KEY_LENGTH) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+                    "key length %d is not enough (%d expected)",
+                    keySize, XMLSEC_KW_DES3_KEY_LENGTH);
+        return(-1);
+    }
+
+    ret = xmlSecBufferSetData(&(ctx->keyBuffer), xmlSecBufferGetData(buffer), XMLSEC_KW_DES3_KEY_LENGTH);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    "xmlSecBufferSetData",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "size=%d", XMLSEC_KW_DES3_KEY_LENGTH);
+        return(-1);
+    }
+
+    return(0);
+}
+
+static int
+xmlSecGnuTLSKWDes3Execute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx;
+    xmlSecBufferPtr in, out;
+    xmlSecSize inSize, outSize, keySize;
+    int ret;
+
+    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformKWDes3Id), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSKWDes3Size), -1);
+    xmlSecAssert2(transformCtx != NULL, -1);
+
+    ctx = xmlSecGnuTLSKWDes3GetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    keySize = xmlSecBufferGetSize(&(ctx->keyBuffer));
+    xmlSecAssert2(keySize == XMLSEC_KW_DES3_KEY_LENGTH, -1);
+
+    in = &(transform->inBuf);
+    out = &(transform->outBuf);
+    inSize = xmlSecBufferGetSize(in);
+    outSize = xmlSecBufferGetSize(out);
+    xmlSecAssert2(outSize == 0, -1);
+
+    if(transform->status == xmlSecTransformStatusNone) {
+        transform->status = xmlSecTransformStatusWorking;
+    }
+
+    if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+        /* just do nothing */
+    } else  if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+        if((inSize % XMLSEC_KW_DES3_BLOCK_LENGTH) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        NULL,
+                        XMLSEC_ERRORS_R_INVALID_SIZE,
+                        "%d bytes - not %d bytes aligned",
+                        inSize, XMLSEC_KW_DES3_BLOCK_LENGTH);
+            return(-1);
+        }
+
+        if(transform->operation == xmlSecTransformOperationEncrypt) {
+            /* the encoded key might be 16 bytes longer plus one block just in case */
+            outSize = inSize + XMLSEC_KW_DES3_IV_LENGTH +
+                               XMLSEC_KW_DES3_BLOCK_LENGTH +
+                               XMLSEC_KW_DES3_BLOCK_LENGTH;
+        } else {
+            /* just in case, add a block */
+            outSize = inSize + XMLSEC_KW_DES3_BLOCK_LENGTH;
+        }
+
+        ret = xmlSecBufferSetMaxSize(out, outSize);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        "xmlSecBufferSetMaxSize",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "size=%d", outSize);
+            return(-1);
+        }
+
+        if(transform->operation == xmlSecTransformOperationEncrypt) {
+            ret = xmlSecKWDes3Encode(&xmlSecGnuTLSKWDes3ImplKlass, ctx,
+                                    xmlSecBufferGetData(in), inSize,
+                                    xmlSecBufferGetData(out), outSize);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                            "xmlSecKWDes3Encode",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "key=%d,in=%d,out=%d",
+                            keySize, inSize, outSize);
+                return(-1);
+            }
+            outSize = ret;
+        } else {
+            ret = xmlSecKWDes3Decode(&xmlSecGnuTLSKWDes3ImplKlass, ctx,
+                                    xmlSecBufferGetData(in), inSize,
+                                    xmlSecBufferGetData(out), outSize);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                            "xmlSecKWDes3Decode",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "key=%d,in=%d,out=%d",
+                            keySize, inSize, outSize);
+                return(-1);
+            }
+            outSize = ret;
+        }
+
+        ret = xmlSecBufferSetSize(out, outSize);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        "xmlSecBufferSetSize",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "size=%d", outSize);
+            return(-1);
+        }
+
+        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);
+        }
+
+        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);
+}
+
+/*********************************************************************
+ *
+ * DES KW implementation
+ *
+ *********************************************************************/
+static int
+xmlSecGnuTLSKWDes3Sha1(void * context,
+                       const xmlSecByte * in, xmlSecSize inSize,
+                       xmlSecByte * out, xmlSecSize outSize) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx = (xmlSecGnuTLSKWDes3CtxPtr)context;
+    gcry_md_hd_t digestCtx;
+    unsigned char * res;
+    unsigned int len;
+    gpg_err_code_t ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize > 0, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize > 0, -1);
+
+    len = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+    xmlSecAssert2(outSize >= len, -1);
+
+    ret = gcry_md_open(&digestCtx, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+    if(ret != GPG_ERR_NO_ERROR) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_md_open(GCRY_MD_SHA1)",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    gcry_md_write(digestCtx, in, inSize);
+
+    ret = gcry_md_final(digestCtx);
+    if(ret != GPG_ERR_NO_ERROR) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_md_final",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gcry_md_close(digestCtx);
+        return(-1);
+    }
+
+    res = gcry_md_read(digestCtx, GCRY_MD_SHA1);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_md_read(GCRY_MD_SHA1)",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gcry_md_close(digestCtx);
+        return(-1);
+    }
+
+    /* done */
+    xmlSecAssert2(outSize >= len, -1);
+    memcpy(out, res, len);
+    gcry_md_close(digestCtx);
+    return(len);
+}
+
+static int
+xmlSecGnuTLSKWDes3GenerateRandom(void * context,
+                                 xmlSecByte * out, xmlSecSize outSize) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx = (xmlSecGnuTLSKWDes3CtxPtr)context;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize > 0, -1);
+
+    gcry_randomize(out, outSize, GCRY_STRONG_RANDOM);
+    return((int)outSize);
+}
+
+static int
+xmlSecGnuTLSKWDes3BlockEncrypt(void * context,
+                               const xmlSecByte * iv, xmlSecSize ivSize,
+                               const xmlSecByte * in, xmlSecSize inSize,
+                               xmlSecByte * out, xmlSecSize outSize) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx = (xmlSecGnuTLSKWDes3CtxPtr)context;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+    xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+    xmlSecAssert2(iv != NULL, -1);
+    xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= 0, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= inSize, -1);
+
+    ret = xmlSecGnuTLSKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)),
+                                    XMLSEC_KW_DES3_KEY_LENGTH,
+                                    iv, XMLSEC_KW_DES3_IV_LENGTH,
+                                    in, inSize,
+                                    out, outSize,
+                                    1); /* encrypt */
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSKWDes3Encrypt",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    return(ret);
+}
+
+static int
+xmlSecGnuTLSKWDes3BlockDecrypt(void * context,
+                               const xmlSecByte * iv, xmlSecSize ivSize,
+                               const xmlSecByte * in, xmlSecSize inSize,
+                               xmlSecByte * out, xmlSecSize outSize) {
+    xmlSecGnuTLSKWDes3CtxPtr ctx = (xmlSecGnuTLSKWDes3CtxPtr)context;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1);
+    xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1);
+    xmlSecAssert2(iv != NULL, -1);
+    xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1);
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= 0, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= inSize, -1);
+
+    ret = xmlSecGnuTLSKWDes3Encrypt(xmlSecBufferGetData(&(ctx->keyBuffer)),
+                                    XMLSEC_KW_DES3_KEY_LENGTH,
+                                    iv, XMLSEC_KW_DES3_IV_LENGTH,
+                                    in, inSize,
+                                    out, outSize,
+                                    0); /* decrypt */
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSKWDes3Encrypt",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    return(ret);
+}
+
+static int
+xmlSecGnuTLSKWDes3Encrypt(const xmlSecByte *key, xmlSecSize keySize,
+                           const xmlSecByte *iv, xmlSecSize ivSize,
+                           const xmlSecByte *in, xmlSecSize inSize,
+                           xmlSecByte *out, xmlSecSize outSize,
+                           int enc) {
+    size_t key_len = gcry_cipher_get_algo_keylen(GCRY_CIPHER_3DES);
+    size_t block_len = gcry_cipher_get_algo_blklen(GCRY_CIPHER_3DES);
+    gcry_cipher_hd_t cipherCtx;
+    gpg_err_code_t ret;
+
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(keySize >= key_len, -1);
+    xmlSecAssert2(iv != NULL, -1);
+    xmlSecAssert2(ivSize >= block_len, -1);
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize > 0, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= inSize, -1);
+
+    ret = gcry_cipher_open(&cipherCtx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE); /* we are paranoid */
+    if(ret != GPG_ERR_NO_ERROR) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_cipher_open(GCRY_CIPHER_3DES)",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = gcry_cipher_setkey(cipherCtx, key, keySize);
+    if(ret != GPG_ERR_NO_ERROR) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_cipher_setkey",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    "keySize=%d,ret=%d", 
+                    keySize, ret);
+        return(-1);
+    }
+
+    ret = gcry_cipher_setiv(cipherCtx, iv, ivSize);
+    if(ret != GPG_ERR_NO_ERROR) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_cipher_setiv",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    "ivSize=%d,ret=%d", 
+                    ivSize, ret);
+        return(-1);
+    }
+
+    if(enc) {
+        ret = gcry_cipher_encrypt(cipherCtx, out, outSize, in, inSize);
+        if(ret != GPG_ERR_NO_ERROR) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gcry_cipher_encrypt",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        "ret=%d", ret);
+            gcry_cipher_close(cipherCtx);
+            return(-1);
+        }
+    } else {
+        ret = gcry_cipher_decrypt(cipherCtx, out, outSize, in, inSize);
+        if(ret != GPG_ERR_NO_ERROR) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gcry_cipher_decrypt",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        "ret=%d", ret);
+            gcry_cipher_close(cipherCtx);
+            return(-1);
+        }
+    }
+
+    /* done */
+    gcry_cipher_close(cipherCtx);
+    return((int)inSize); /* out size == in size */
+}
+
+
+#endif /* XMLSEC_NO_DES */
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]