summaryrefslogtreecommitdiff
path: root/src/gnutls/asymkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnutls/asymkeys.c')
-rw-r--r--src/gnutls/asymkeys.c455
1 files changed, 455 insertions, 0 deletions
diff --git a/src/gnutls/asymkeys.c b/src/gnutls/asymkeys.c
new file mode 100644
index 00000000..6ac68a78
--- /dev/null
+++ b/src/gnutls/asymkeys.c
@@ -0,0 +1,455 @@
+/**
+ * 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 <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+
+/**************************************************************************
+ *
+ * We use xmlsec-gcrypt for all the basic crypto ops
+ *
+ *****************************************************************************/
+#include <xmlsec/gcrypt/crypto.h>
+#include <gcrypt.h>
+
+static void xmlSecGnuTLSDestroyParams(gnutls_datum_t * params, xmlSecSize num) {
+ xmlSecSize ii;
+
+ xmlSecAssert(params != NULL);
+ for(ii = 0; ii < num; ++ii) {
+ gnutls_free(params[ii].data);
+ }
+}
+
+static void xmlSecGnuTLSDestroyMpis(gcry_mpi_t * mpis, xmlSecSize num) {
+ xmlSecSize ii;
+
+ xmlSecAssert(mpis != NULL);
+ for(ii = 0; ii < num; ++ii) {
+ gcry_mpi_release(mpis[ii]);
+ }
+}
+
+static int xmlSecGnuTLSConvertParamsToMpis(gnutls_datum_t * params, xmlSecSize paramsNum,
+ gcry_mpi_t * mpis, xmlSecSize mpisNum) {
+
+ xmlSecSize ii;
+ int rc;
+
+ xmlSecAssert2(params != NULL, -1);
+ xmlSecAssert2(mpis != NULL, -1);
+ xmlSecAssert2(paramsNum == mpisNum, -1);
+
+ for(ii = 0; ii < paramsNum; ++ii) {
+ rc = gcry_mpi_scan(&(mpis[ii]), GCRYMPI_FMT_USG, params[ii].data, params[ii].size, NULL);
+ if((rc != GPG_ERR_NO_ERROR) || (mpis[ii] == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_mpi_scan",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, ii); /* destroy up to now */
+ return(-1);
+ }
+ }
+
+ /* done */
+ return(0);
+}
+
+#ifndef XMLSEC_NO_DSA
+
+/**
+ * xmlSecGnuTLSKeyDataDsaGetKlass:
+ *
+ * The DSA key data klass.
+ *
+ * Returns: pointer to DSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataDsaGetKlass(void) {
+ return (xmlSecGCryptKeyDataDsaGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSKeyDataDsaAdoptPrivateKey:
+ * @data: the pointer to DSA key data.
+ * @dsa_key: the pointer to GnuTLS DSA private key.
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t dsa_key) {
+ gnutls_datum_t params[5];
+ gcry_mpi_t mpis[5];
+ gcry_sexp_t priv_key = NULL;
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int err;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDsaId), -1);
+ xmlSecAssert2(dsa_key != NULL, -1);
+ xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(dsa_key) == GNUTLS_PK_DSA, -1);
+
+ /* get raw values */
+ err = gnutls_x509_privkey_export_dsa_raw(dsa_key,
+ &(params[0]), &(params[1]), &(params[2]),
+ &(params[3]), &(params[4]));
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_export_dsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3], mpis[4]);
+ if((rc != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/dsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ gcry_sexp_release(priv_key);
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ gcry_sexp_release(priv_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_x509_privkey_deinit(dsa_key);
+ return(0);
+}
+
+
+/**
+ * xmlSecGnuTLSKeyDataDsaAdoptPublicKey:
+ * @data: the pointer to DSA key data.
+ * @p: the pointer to p component of the DSA public key
+ * @q: the pointer to q component of the DSA public key
+ * @g: the pointer to g component of the DSA public key
+ * @y: the pointer to y component of the DSA public key
+ *
+ * Sets the value of DSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataDsaAdoptPublicKey(xmlSecKeyDataPtr data,
+ gnutls_datum_t * p, gnutls_datum_t * q,
+ gnutls_datum_t * g, gnutls_datum_t * y) {
+ gnutls_datum_t params[4];
+ gcry_mpi_t mpis[4];
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDsaId), -1);
+ xmlSecAssert2(p != NULL, -1);
+ xmlSecAssert2(q != NULL, -1);
+ xmlSecAssert2(g != NULL, -1);
+ xmlSecAssert2(y != NULL, -1);
+
+ /* copy */
+ memcpy(&(params[0]), p, sizeof(*p));
+ memcpy(&(params[1]), q, sizeof(*q));
+ memcpy(&(params[2]), g, sizeof(*g));
+ memcpy(&(params[3]), y, sizeof(*y));
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ /* don't destroy params - we got them from outside !!! */
+ return(-1);
+ }
+ /* don't destroy params - we got them from outside !!! */
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+ mpis[0], mpis[1], mpis[2], mpis[3]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_free(p->data);
+ gnutls_free(q->data);
+ gnutls_free(g->data);
+ gnutls_free(y->data);
+ return(0);
+}
+
+#endif /* XMLSEC_NO_DSA */
+
+
+#ifndef XMLSEC_NO_RSA
+
+/**
+ * xmlSecGnuTLSKeyDataRsaGetKlass:
+ *
+ * The GnuTLS RSA key data klass.
+ *
+ * Returns: pointer to GnuTLS RSA key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataRsaGetKlass(void) {
+ return (xmlSecGCryptKeyDataRsaGetKlass());
+}
+
+/**
+ * xmlSecGnuTLSKeyDataRsaAdoptPrivateKey:
+ * @data: the pointer to RSA key data.
+ * @rsa_key: the pointer to GnuTLS RSA private key.
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t rsa_key) {
+ gnutls_datum_t params[6];
+ gcry_mpi_t mpis[6];
+ gcry_sexp_t priv_key = NULL;
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int err;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataRsaId), -1);
+ xmlSecAssert2(rsa_key != NULL, -1);
+ xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(rsa_key) == GNUTLS_PK_RSA, -1);
+
+ /* get raw values */
+ err = gnutls_x509_privkey_export_rsa_raw(rsa_key,
+ &(params[0]), &(params[1]), &(params[2]),
+ &(params[3]), &(params[4]), &(params[5]));
+ if(err != GNUTLS_E_SUCCESS) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gnutls_x509_privkey_export_rsa_raw",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_GNUTLS_REPORT_ERROR(err));
+ return(-1);
+ }
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
+ mpis[0], mpis[1], mpis[2],
+ mpis[3], mpis[4], mpis[5]);
+ if((rc != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(rsa((n%m)(e%m))))",
+ mpis[0], mpis[1]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ gcry_sexp_release(priv_key);
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ gcry_sexp_release(priv_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_x509_privkey_deinit(rsa_key);
+ return(0);
+}
+
+
+/**
+ * xmlSecGnuTLSKeyDataRsaAdoptPublicKey:
+ * @data: the pointer to RSA key data.
+ * @m: the pointer to m component of the RSA public key
+ * @e: the pointer to e component of the RSA public key
+ *
+ * Sets the value of RSA key data.
+ *
+ * Returns: 0 on success or a negative value otherwise.
+ */
+int
+xmlSecGnuTLSKeyDataRsaAdoptPublicKey(xmlSecKeyDataPtr data,
+ gnutls_datum_t * m, gnutls_datum_t * e) {
+ gnutls_datum_t params[2];
+ gcry_mpi_t mpis[2];
+ gcry_sexp_t pub_key = NULL;
+ int rc;
+ int ret;
+
+ xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataRsaId), -1);
+ xmlSecAssert2(m != NULL, -1);
+ xmlSecAssert2(e != NULL, -1);
+
+ /* copy */
+ memcpy(&(params[0]), m, sizeof(*m));
+ memcpy(&(params[1]), e, sizeof(*e));
+
+ /* convert to mpis */
+ ret = xmlSecGnuTLSConvertParamsToMpis(
+ params, sizeof(params)/sizeof(params[0]),
+ mpis, sizeof(mpis)/sizeof(mpis[0]));
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGnuTLSConvertParamsToMpis",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ /* don't destroy params - we got them from outside !!! */
+ return(-1);
+ }
+ /* don't destroy params - we got them from outside !!! */
+
+ /* build expressions */
+ rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(rsa((n%m)(e%m))))",
+ mpis[0], mpis[1]);
+ if((rc != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "gcry_sexp_build(private/rsa)",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(rc));
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+ return(-1);
+ }
+ xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+ ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, NULL);
+ if(ret < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ gcry_sexp_release(pub_key);
+ return(-1);
+ }
+
+ /* done, we "adopted" the key - destroy it! */
+ gnutls_free(m->data);
+ gnutls_free(e->data);
+ return(0);
+}
+#endif /* XMLSEC_NO_RSA */