summaryrefslogtreecommitdiff
path: root/src/gcrypt/signatures.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gcrypt/signatures.c')
-rw-r--r--src/gcrypt/signatures.c1490
1 files changed, 1490 insertions, 0 deletions
diff --git a/src/gcrypt/signatures.c b/src/gcrypt/signatures.c
new file mode 100644
index 00000000..c49638e4
--- /dev/null
+++ b/src/gcrypt/signatures.c
@@ -0,0 +1,1490 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include "globals.h"
+
+#include <string.h>
+
+#include <gcrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gcrypt/crypto.h>
+
+
+/**************************************************************************
+ *
+ * Forward declarations for actual sign/verify implementations
+ *
+ *****************************************************************************/
+typedef int (*xmlSecGCryptPkSignMethod) (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+typedef int (*xmlSecGCryptPkVerifyMethod) (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+
+#ifndef XMLSEC_NO_DSA
+static int xmlSecGCryptDsaPkSign (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+static int xmlSecGCryptDsaPkVerify (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+static int xmlSecGCryptRsaPkcs1PkSign (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ xmlSecBufferPtr out);
+static int xmlSecGCryptRsaPkcs1PkVerify (int digest,
+ xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst,
+ xmlSecSize dgstSize,
+ const xmlSecByte* data,
+ xmlSecSize dataSize);
+#endif /* XMLSEC_NO_RSA */
+
+
+/**************************************************************************
+ *
+ * Internal GCrypt signatures ctx
+ *
+ *****************************************************************************/
+typedef struct _xmlSecGCryptPkSignatureCtx xmlSecGCryptPkSignatureCtx,
+ *xmlSecGCryptPkSignatureCtxPtr;
+
+
+struct _xmlSecGCryptPkSignatureCtx {
+ int digest;
+ xmlSecKeyDataId keyId;
+ xmlSecGCryptPkSignMethod sign;
+ xmlSecGCryptPkVerifyMethod verify;
+
+ gcry_md_hd_t digestCtx;
+ xmlSecKeyDataPtr key_data;
+
+ xmlSecByte dgst[XMLSEC_GCRYPT_MAX_DIGEST_SIZE];
+ xmlSecSize dgstSize; /* dgst size in bytes */
+};
+
+
+/******************************************************************************
+ *
+ * Pk Signature transforms
+ *
+ * xmlSecGCryptPkSignatureCtx is located after xmlSecTransform
+ *
+ *****************************************************************************/
+#define xmlSecGCryptPkSignatureSize \
+ (sizeof(xmlSecTransform) + sizeof(xmlSecGCryptPkSignatureCtx))
+#define xmlSecGCryptPkSignatureGetCtx(transform) \
+ ((xmlSecGCryptPkSignatureCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
+
+static int xmlSecGCryptPkSignatureCheckId (xmlSecTransformPtr transform);
+static int xmlSecGCryptPkSignatureInitialize (xmlSecTransformPtr transform);
+static void xmlSecGCryptPkSignatureFinalize (xmlSecTransformPtr transform);
+static int xmlSecGCryptPkSignatureSetKeyReq (xmlSecTransformPtr transform,
+ xmlSecKeyReqPtr keyReq);
+static int xmlSecGCryptPkSignatureSetKey (xmlSecTransformPtr transform,
+ xmlSecKeyPtr key);
+static int xmlSecGCryptPkSignatureVerify (xmlSecTransformPtr transform,
+ const xmlSecByte* data,
+ xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx);
+static int xmlSecGCryptPkSignatureExecute (xmlSecTransformPtr transform,
+ int last,
+ xmlSecTransformCtxPtr transformCtx);
+
+static int
+xmlSecGCryptPkSignatureCheckId(xmlSecTransformPtr transform) {
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) {
+ return(1);
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ {
+ return(0);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptPkSignatureInitialize(xmlSecTransformPtr transform) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ gcry_error_t err;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+
+ memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx));
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformDsaSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ ctx->keyId = xmlSecGCryptKeyDataDsaId;
+ ctx->sign = xmlSecGCryptDsaPkSign;
+ ctx->verify = xmlSecGCryptDsaPkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+#ifndef XMLSEC_NO_MD5
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaMd5Id)) {
+ ctx->digest = GCRY_MD_MD5;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaRipemd160Id)) {
+ ctx->digest = GCRY_MD_RMD160;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha1Id)) {
+ ctx->digest = GCRY_MD_SHA1;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA1 */
+
+#ifndef XMLSEC_NO_SHA256
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha256Id)) {
+ ctx->digest = GCRY_MD_SHA256;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha384Id)) {
+ ctx->digest = GCRY_MD_SHA384;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+ if(xmlSecTransformCheckId(transform, xmlSecGCryptTransformRsaSha512Id)) {
+ ctx->digest = GCRY_MD_SHA512;
+ ctx->keyId = xmlSecGCryptKeyDataRsaId;
+ ctx->sign = xmlSecGCryptRsaPkcs1PkSign;
+ ctx->verify = xmlSecGCryptRsaPkcs1PkVerify;
+ } else
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+ if(1) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ NULL,
+ XMLSEC_ERRORS_R_INVALID_TRANSFORM,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* create digest ctx */
+ err = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_open",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* done */
+ return(0);
+}
+
+static void
+xmlSecGCryptPkSignatureFinalize(xmlSecTransformPtr transform) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+
+ xmlSecAssert(xmlSecGCryptPkSignatureCheckId(transform));
+ xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize));
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert(ctx != NULL);
+
+ if(ctx->key_data != NULL) {
+ xmlSecKeyDataDestroy(ctx->key_data);
+ }
+ if(ctx->digestCtx != NULL) {
+ gcry_md_close(ctx->digestCtx);
+ }
+
+ memset(ctx, 0, sizeof(xmlSecGCryptPkSignatureCtx));
+}
+
+static int
+xmlSecGCryptPkSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ xmlSecKeyDataPtr key_data;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(key != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+ xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
+
+ key_data = xmlSecKeyGetValue(key);
+ xmlSecAssert2(key_data != NULL, -1);
+
+ if(ctx->key_data != NULL) {
+ xmlSecKeyDataDestroy(ctx->key_data);
+ }
+
+ ctx->key_data = xmlSecKeyDataDuplicate(key_data);
+ if(ctx->key_data == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "xmlSecKeyDataDuplicate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ return(0);
+}
+
+static int
+xmlSecGCryptPkSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(keyReq != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->keyId != NULL, -1);
+
+ keyReq->keyId = ctx->keyId;
+ if(transform->operation == xmlSecTransformOperationSign) {
+ keyReq->keyType = xmlSecKeyDataTypePrivate;
+ keyReq->keyUsage = xmlSecKeyUsageSign;
+ } else {
+ keyReq->keyType = xmlSecKeyDataTypePublic;
+ keyReq->keyUsage = xmlSecKeyUsageVerify;
+ }
+ return(0);
+}
+
+
+static int
+xmlSecGCryptPkSignatureVerify(xmlSecTransformPtr transform,
+ const xmlSecByte* data, xmlSecSize dataSize,
+ xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->sign != NULL, -1);
+ xmlSecAssert2(ctx->verify != NULL, -1);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+ xmlSecAssert2(ctx->key_data != NULL, -1);
+
+ ret = ctx->verify(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, data, dataSize);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* check result */
+ if(ret == 1) {
+ transform->status = xmlSecTransformStatusOk;
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->verify",
+ XMLSEC_ERRORS_R_DATA_NOT_MATCH,
+ "signature do not match");
+ transform->status = xmlSecTransformStatusFail;
+ }
+
+ /* done */
+ return(0);
+}
+
+static int
+xmlSecGCryptPkSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+ xmlSecGCryptPkSignatureCtxPtr ctx;
+ xmlSecBufferPtr in, out;
+ xmlSecSize inSize;
+ xmlSecSize outSize;
+ int ret;
+
+ xmlSecAssert2(xmlSecGCryptPkSignatureCheckId(transform), -1);
+ xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
+ xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGCryptPkSignatureSize), -1);
+ xmlSecAssert2(transformCtx != NULL, -1);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->sign != NULL, -1);
+ xmlSecAssert2(ctx->verify != NULL, -1);
+
+ in = &(transform->inBuf);
+ out = &(transform->outBuf);
+ inSize = xmlSecBufferGetSize(in);
+ outSize = xmlSecBufferGetSize(out);
+
+ ctx = xmlSecGCryptPkSignatureGetCtx(transform);
+ xmlSecAssert2(ctx != NULL, -1);
+ xmlSecAssert2(ctx->key_data != NULL, -1);
+
+ if(transform->status == xmlSecTransformStatusNone) {
+ /* do nothing, already initialized */
+ transform->status = xmlSecTransformStatusWorking;
+ }
+
+ if(transform->status == xmlSecTransformStatusWorking) {
+ xmlSecAssert2(outSize == 0, -1);
+
+ /* update the digest */
+ if(inSize > 0) {
+ gcry_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);
+ }
+ }
+
+ /* generate digest and signature */
+ if(last != 0) {
+ xmlSecByte* buf;
+
+ /* get the final digest */
+ gcry_md_final(ctx->digestCtx);
+ buf = gcry_md_read(ctx->digestCtx, ctx->digest);
+ if(buf == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "gcry_md_read",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+
+ /* copy it to our internal buffer */
+ ctx->dgstSize = gcry_md_get_algo_dlen(ctx->digest);
+ xmlSecAssert2(ctx->dgstSize > 0, -1);
+ xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1);
+ memcpy(ctx->dgst, buf, ctx->dgstSize);
+
+ xmlSecAssert2(outSize == 0, -1);
+ if(transform->operation == xmlSecTransformOperationSign) {
+ ret = ctx->sign(ctx->digest, ctx->key_data, ctx->dgst, ctx->dgstSize, out);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+ "ctx->sign",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ }
+
+ /* done */
+ transform->status = xmlSecTransformStatusFinished;
+ }
+ }
+
+ if((transform->status == xmlSecTransformStatusWorking) || (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);
+}
+
+/*****************************************************************************
+ *
+ * Helper
+ *
+ ****************************************************************************/
+static int
+xmlSecGCryptAppendMpi(gcry_mpi_t a, xmlSecBufferPtr out, xmlSecSize min_size) {
+ xmlSecSize outSize;
+ size_t written;
+ gpg_error_t err;
+ int ret;
+
+ xmlSecAssert2(a != NULL, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* current size */
+ outSize = xmlSecBufferGetSize(out);
+
+ /* figure out how much space we need */
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* add zeros at the beggining (if needed) */
+ if((min_size > 0) && (written < min_size)) {
+ outSize += (min_size - written);
+ }
+
+ /* allocate space */
+ ret = xmlSecBufferSetMaxSize(out, outSize + written + 1);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetMaxSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d", (int)(outSize + written + 1));
+ return(-1);
+ }
+ xmlSecAssert2(xmlSecBufferGetMaxSize(out) > outSize, -1);
+
+ /* add zeros at the beggining (if needed) */
+ if((min_size > 0) && (written < min_size)) {
+ xmlSecSize ii;
+ xmlSecByte * p = xmlSecBufferGetData(out);
+
+ for(ii = 0; ii < (min_size - written); ++ii) {
+ p[outSize - ii - 1] = 0;
+ }
+ }
+
+ /* write out */
+ written = 0;
+ err = gcry_mpi_print(GCRYMPI_FMT_USG,
+ xmlSecBufferGetData(out) + outSize,
+ xmlSecBufferGetMaxSize(out) - outSize,
+ &written, a);
+ if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_print",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* reset size */
+ ret = xmlSecBufferSetSize(out, outSize + written);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecBufferSetSize",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ "size=%d",
+ (int)(outSize + written));
+ return(-1);
+ }
+
+ /* done */
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * DSA-SHA1 signature transform
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg:
+ *
+ * The output of the DSA algorithm consists of a pair of integers
+ * usually referred by the pair (r, s). The signature value consists of
+ * the base64 encoding of the concatenation of two octet-streams that
+ * respectively result from the octet-encoding of the values r and s in
+ * that order. Integer to octet-stream conversion must be done according
+ * to the I2OSP operation defined in the RFC 2437 [PKCS1] specification
+ * with a l parameter equal to 20. For example, the SignatureValue element
+ * for a DSA signature (r, s) with values specified in hexadecimal:
+ *
+ * r = 8BAC1AB6 6410435C B7181F95 B16AB97C 92B341C0
+ * s = 41E2345F 1F56DF24 58F426D1 55B4BA2D B6DCD8C8
+ *
+ * from the example in Appendix 5 of the DSS standard would be
+ *
+ * <SignatureValue>i6watmQQQ1y3GB+VsWq5fJKzQcBB4jRfH1bfJFj0JtFVtLotttzYyA==</SignatureValue>
+ *
+ ***************************************************************************/
+static int
+xmlSecGCryptDsaPkSign(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ xmlSecBufferPtr out) {
+ gcry_mpi_t m_hash = NULL;
+ gcry_sexp_t s_data = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gcry_sexp_t s_r = NULL;
+ gcry_sexp_t s_s = NULL;
+ gcry_mpi_t m_r = NULL;
+ gcry_mpi_t m_s = NULL;
+ gcry_sexp_t s_tmp;
+ gpg_error_t err;
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPrivateKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* get the current digest, can't use "hash" :( */
+ err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(hash)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags raw)(value %m))",
+ m_hash);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* create signature */
+ err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataDsaGetPrivateKey(key_data));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_sign",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* find signature value */
+ s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "dsa", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ /* r */
+ s_r = gcry_sexp_find_token(s_sig, "r", 0);
+ if(s_r == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ m_r = gcry_sexp_nth_mpi(s_r, 1, GCRYMPI_FMT_USG);
+ if(m_r == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* s */
+ s_s = gcry_sexp_find_token(s_sig, "s", 0);
+ if(s_s == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ m_s = gcry_sexp_nth_mpi(s_s, 1, GCRYMPI_FMT_USG);
+ if(m_s == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* write out: r + s */
+ ret = xmlSecGCryptAppendMpi(m_r, out, 20);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBufferGetSize(out) == 20, -1);
+ ret = xmlSecGCryptAppendMpi(m_s, out, 20);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ xmlSecAssert2(xmlSecBufferGetSize(out) == (20 + 20), -1);
+
+ /* done */
+ res = 0;
+
+done:
+ if(m_hash != NULL) {
+ gcry_mpi_release(m_hash);
+ }
+ if(m_r != NULL) {
+ gcry_mpi_release(m_r);
+ }
+ if(m_s != NULL) {
+ gcry_mpi_release(m_s);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+ if(s_r != NULL) {
+ gcry_sexp_release(s_r);
+ }
+ if(s_s != NULL) {
+ gcry_sexp_release(s_s);
+ }
+
+ return(res);
+}
+
+static int
+xmlSecGCryptDsaPkVerify(int digest ATTRIBUTE_UNUSED, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ gcry_mpi_t m_hash = NULL;
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig_r = NULL;
+ gcry_mpi_t m_sig_s = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gpg_error_t err;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataDsaGetPublicKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize == (20 + 20), -1);
+
+ /* get the current digest, can't use "hash" :( */
+ err = gcry_mpi_scan(&m_hash, GCRYMPI_FMT_USG, dgst, dgstSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_hash == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(hash)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags raw)(value %m))",
+ m_hash);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* get the existing signature */
+ err = gcry_mpi_scan(&m_sig_r, GCRYMPI_FMT_USG, data, 20, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig_r == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(r)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+ err = gcry_mpi_scan(&m_sig_s, GCRYMPI_FMT_USG, data + 20, 20, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig_s == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_sig, NULL,
+ "(sig-val(dsa(r %m)(s %m)))",
+ m_sig_r, m_sig_s);
+ if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* verify signature */
+ err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataDsaGetPublicKey(key_data));
+ if(err == GPG_ERR_NO_ERROR) {
+ res = 1; /* good signature */
+ } else if(err == GPG_ERR_BAD_SIGNATURE) {
+ res = 0; /* bad signature */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* done */
+done:
+ if(m_hash != NULL) {
+ gcry_mpi_release(m_hash);
+ }
+ if(m_sig_r != NULL) {
+ gcry_mpi_release(m_sig_r);
+ }
+ if(m_sig_s != NULL) {
+ gcry_mpi_release(m_sig_s);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+
+static xmlSecTransformKlass xmlSecGCryptDsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameDsaSha1, /* const xmlChar* name; */
+ xmlSecHrefDsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformDsaSha1GetKlass:
+ *
+ * The DSA-SHA1 signature transform klass.
+ *
+ * Returns: DSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformDsaSha1GetKlass(void) {
+ return(&xmlSecGCryptDsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+#endif /* XMLSEC_NO_DSA */
+
+#ifndef XMLSEC_NO_RSA
+
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ * http://www.w3.org/TR/xmldsig-core/#sec-SignatureAlg:
+ *
+ * The SignatureValue content for an RSA signature is the base64 [MIME]
+ * encoding of the octet string computed as per RFC 2437 [PKCS1,
+ * section 8.1.1: Signature generation for the RSASSA-PKCS1-v1_5 signature
+ * scheme]. As specified in the EMSA-PKCS1-V1_5-ENCODE function RFC 2437
+ * [PKCS1, section 9.2.1], the value input to the signature function MUST
+ * contain a pre-pended algorithm object identifier for the hash function,
+ * but the availability of an ASN.1 parser and recognition of OIDs is not
+ * required of a signature verifier. The PKCS#1 v1.5 representation appears
+ * as:
+ *
+ * CRYPT (PAD (ASN.1 (OID, DIGEST (data))))
+ *
+ * Note that the padded ASN.1 will be of the following form:
+ *
+ * 01 | FF* | 00 | prefix | hash
+ *
+ * where "|" is concatenation, "01", "FF", and "00" are fixed octets of
+ * the corresponding hexadecimal value, "hash" is the SHA1 digest of the
+ * data, and "prefix" is the ASN.1 BER SHA1 algorithm designator prefix
+ * required in PKCS1 [RFC 2437], that is,
+ *
+ * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
+ *
+ * This prefix is included to make it easier to use standard cryptographic
+ * libraries. The FF octet MUST be repeated the maximum number of times such
+ * that the value of the quantity being CRYPTed is one octet shorter than
+ * the RSA modulus.
+ *
+ ***************************************************************************/
+static int
+xmlSecGCryptRsaPkcs1PkSign(int digest, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ xmlSecBufferPtr out) {
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gcry_sexp_t s_tmp;
+ gpg_error_t err;
+ int ret;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPrivateKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(out != NULL, -1);
+
+ /* get the current digest */
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pkcs1)(hash %s %b))",
+ gcry_md_algo_name(digest),
+ (int)dgstSize, dgst);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* create signature */
+ err = gcry_pk_sign(&s_sig, s_data, xmlSecGCryptKeyDataRsaGetPrivateKey(key_data));
+ if(err != GPG_ERR_NO_ERROR) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_sign",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* find signature value */
+ s_tmp = gcry_sexp_find_token(s_sig, "sig-val", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "rsa", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(rsa)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ s_tmp = gcry_sexp_find_token(s_sig, "s", 0);
+ if(s_tmp == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_find_token(s)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+ gcry_sexp_release(s_sig);
+ s_sig = s_tmp;
+
+ m_sig = gcry_sexp_nth_mpi(s_sig, 1, GCRYMPI_FMT_USG);
+ if(m_sig == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_nth_mpi(1)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* write out */
+ ret = xmlSecGCryptAppendMpi(m_sig, out, 0);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptAppendMpi",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto done;
+ }
+
+ /* done */
+ res = 0;
+
+done:
+ if(m_sig != NULL) {
+ gcry_mpi_release(m_sig);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+static int
+xmlSecGCryptRsaPkcs1PkVerify(int digest, xmlSecKeyDataPtr key_data,
+ const xmlSecByte* dgst, xmlSecSize dgstSize,
+ const xmlSecByte* data, xmlSecSize dataSize) {
+ gcry_sexp_t s_data = NULL;
+ gcry_mpi_t m_sig = NULL;
+ gcry_sexp_t s_sig = NULL;
+ gpg_error_t err;
+ int res = -1;
+
+ xmlSecAssert2(key_data != NULL, -1);
+ xmlSecAssert2(xmlSecGCryptKeyDataRsaGetPublicKey(key_data) != NULL, -1);
+ xmlSecAssert2(dgst != NULL, -1);
+ xmlSecAssert2(dgstSize > 0, -1);
+ xmlSecAssert2(data != NULL, -1);
+ xmlSecAssert2(dataSize > 0, -1);
+
+ /* get the current digest */
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pkcs1)(hash %s %b))",
+ gcry_md_algo_name(digest),
+ (int)dgstSize, dgst);
+ if((err != GPG_ERR_NO_ERROR) || (s_data == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(data)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* get the existing signature */
+ err = gcry_mpi_scan(&m_sig, GCRYMPI_FMT_USG, data, dataSize, NULL);
+ if((err != GPG_ERR_NO_ERROR) || (m_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ err = gcry_sexp_build (&s_sig, NULL,
+ "(sig-val(rsa(s %m)))",
+ m_sig);
+ if((err != GPG_ERR_NO_ERROR) || (s_sig == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(sig-val)",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* verify signature */
+ err = gcry_pk_verify(s_sig, s_data, xmlSecGCryptKeyDataRsaGetPublicKey(key_data));
+ if(err == GPG_ERR_NO_ERROR) {
+ res = 1; /* good signature */
+ } else if(err == GPG_ERR_BAD_SIGNATURE) {
+ res = 0; /* bad signature */
+ } else {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_pk_verify",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GCRYPT_REPORT_ERROR(err));
+ goto done;
+ }
+
+ /* done */
+done:
+ if(m_sig != NULL) {
+ gcry_mpi_release(m_sig);
+ }
+
+ if(s_data != NULL) {
+ gcry_sexp_release(s_data);
+ }
+ if(s_sig != NULL) {
+ gcry_sexp_release(s_sig);
+ }
+
+ return(res);
+}
+
+
+#ifndef XMLSEC_NO_MD5
+/****************************************************************************
+ *
+ * RSA-MD5 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaMd5Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaMd5, /* const xmlChar* name; */
+ xmlSecHrefRsaMd5, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaMd5GetKlass:
+ *
+ * The RSA-MD5 signature transform klass.
+ *
+ * Returns: RSA-MD5 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaMd5GetKlass(void) {
+ return(&xmlSecGCryptRsaMd5Klass);
+}
+
+#endif /* XMLSEC_NO_MD5 */
+
+#ifndef XMLSEC_NO_RIPEMD160
+/****************************************************************************
+ *
+ * RSA-RIPEMD160 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaRipemd160Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaRipemd160, /* const xmlChar* name; */
+ xmlSecHrefRsaRipemd160, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaRipemd160GetKlass:
+ *
+ * The RSA-RIPEMD160 signature transform klass.
+ *
+ * Returns: RSA-RIPEMD160 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaRipemd160GetKlass(void) {
+ return(&xmlSecGCryptRsaRipemd160Klass);
+}
+
+#endif /* XMLSEC_NO_RIPEMD160 */
+
+#ifndef XMLSEC_NO_SHA1
+/****************************************************************************
+ *
+ * RSA-SHA1 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha1Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha1, /* const xmlChar* name; */
+ xmlSecHrefRsaSha1, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha1GetKlass:
+ *
+ * The RSA-SHA1 signature transform klass.
+ *
+ * Returns: RSA-SHA1 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha1GetKlass(void) {
+ return(&xmlSecGCryptRsaSha1Klass);
+}
+
+#endif /* XMLSEC_NO_SHA1 */
+
+
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha256Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha256, /* const xmlChar* name; */
+ xmlSecHrefRsaSha256, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha256GetKlass:
+ *
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns: RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha256GetKlass(void) {
+ return(&xmlSecGCryptRsaSha256Klass);
+}
+
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha384Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha384, /* const xmlChar* name; */
+ xmlSecHrefRsaSha384, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha384GetKlass:
+ *
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns: RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha384GetKlass(void) {
+ return(&xmlSecGCryptRsaSha384Klass);
+}
+
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecGCryptRsaSha512Klass = {
+ /* klass/object sizes */
+ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
+ xmlSecGCryptPkSignatureSize, /* xmlSecSize objSize */
+
+ xmlSecNameRsaSha512, /* const xmlChar* name; */
+ xmlSecHrefRsaSha512, /* const xmlChar* href; */
+ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */
+
+ xmlSecGCryptPkSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
+ xmlSecGCryptPkSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
+ NULL, /* xmlSecTransformNodeReadMethod readNode; */
+ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
+ xmlSecGCryptPkSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+ xmlSecGCryptPkSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
+ xmlSecGCryptPkSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
+ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
+ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
+ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
+ NULL, /* xmlSecTransformPushXmlMethod pushXml; */
+ NULL, /* xmlSecTransformPopXmlMethod popXml; */
+ xmlSecGCryptPkSignatureExecute, /* xmlSecTransformExecuteMethod execute; */
+
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * xmlSecGCryptTransformRsaSha512GetKlass:
+ *
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns: RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId
+xmlSecGCryptTransformRsaSha512GetKlass(void) {
+ return(&xmlSecGCryptRsaSha512Klass);
+}
+
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+
+