summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-05-18 23:18:07 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-03 19:42:02 +0200
commit68b714494d6b99104897738ccec676a81be7a35d (patch)
treedc0f04569bc144dec9120bd423fedb306c70ff23 /lib/x509
parent4d8be74bbc3b60f539bff11a20544d80339ff34f (diff)
downloadgnutls-68b714494d6b99104897738ccec676a81be7a35d.tar.gz
Added operations to sign CRLs, certificates and requests with an abstract key and thus with a PKCS #11 key as well.
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/crl_write.c74
-rw-r--r--lib/x509/crq.c143
-rw-r--r--lib/x509/mpi.c3
-rw-r--r--lib/x509/sign.c39
-rw-r--r--lib/x509/x509_int.h12
-rw-r--r--lib/x509/x509_write.c75
6 files changed, 269 insertions, 77 deletions
diff --git a/lib/x509/crl_write.c b/lib/x509/crl_write.c
index d355c4f351..c9c784d0aa 100644
--- a/lib/x509/crl_write.c
+++ b/lib/x509/crl_write.c
@@ -101,6 +101,7 @@ gnutls_x509_crl_sign2 (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer,
gnutls_digest_algorithm_t dig, unsigned int flags)
{
int result;
+ gnutls_privkey_t privkey;
if (crl == NULL || issuer == NULL)
{
@@ -108,19 +109,33 @@ gnutls_x509_crl_sign2 (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer,
return GNUTLS_E_INVALID_REQUEST;
}
- /* disable all the unneeded OPTIONAL fields.
- */
- disable_optional_stuff (crl);
-
- result = _gnutls_x509_pkix_sign (crl->crl, "tbsCertList",
- dig, issuer, issuer_key);
+ result = gnutls_privkey_init(&privkey);
if (result < 0)
{
gnutls_assert ();
return result;
}
- return 0;
+ result = gnutls_privkey_import_x509(privkey, issuer_key, 0);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto fail;
+ }
+
+ result = gnutls_x509_crl_privkey_sign (crl, issuer, privkey, dig, flags);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto fail;
+ }
+
+ result = 0;
+
+fail:
+ gnutls_privkey_deinit(privkey);
+
+ return result;
}
/**
@@ -441,4 +456,49 @@ gnutls_x509_crl_set_number (gnutls_x509_crl_t crl,
return 0;
}
+/**
+ * gnutls_x509_crl_privkey_sign:
+ * @crl: should contain a gnutls_x509_crl_t structure
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing.
+ * @flags: must be 0
+ *
+ * This function will sign the CRL with the issuer's private key, and
+ * will copy the issuer's information into the CRL.
+ *
+ * This must be the last step in a certificate CRL since all
+ * the previously set parameters are now signed.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crl_privkey_sign (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer,
+ gnutls_privkey_t issuer_key,
+ gnutls_digest_algorithm_t dig, unsigned int flags)
+{
+ int result;
+
+ if (crl == NULL || issuer == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* disable all the unneeded OPTIONAL fields.
+ */
+ disable_optional_stuff (crl);
+
+ result = _gnutls_x509_pkix_sign (crl->crl, "tbsCertList",
+ dig, issuer, issuer_key);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ return 0;
+}
+
#endif /* ENABLE_PKI */
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 6a9113b9b1..e18578f99b 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -1010,7 +1010,7 @@ gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key,
gnutls_digest_algorithm_t dig, unsigned int flags)
{
int result;
- gnutls_datum_t signature;
+ gnutls_privkey_t privkey;
if (crq == NULL)
{
@@ -1018,55 +1018,33 @@ gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key,
return GNUTLS_E_INVALID_REQUEST;
}
- /* Make sure version field is set. */
- if (gnutls_x509_crq_get_version (crq) == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
- {
- result = gnutls_x509_crq_set_version (crq, 1);
- if (result < 0)
- {
- gnutls_assert ();
- return result;
- }
- }
-
- /* Step 1. Self sign the request.
- */
- result =
- _gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo",
- dig, key, &signature);
-
+ result = gnutls_privkey_init(&privkey);
if (result < 0)
{
gnutls_assert ();
return result;
}
- /* Step 2. write the signature (bits)
- */
- result =
- asn1_write_value (crq->crq, "signature", signature.data,
- signature.size * 8);
-
- _gnutls_free_datum (&signature);
-
- if (result != ASN1_SUCCESS)
+ result = gnutls_privkey_import_x509(privkey, key, 0);
+ if (result < 0)
{
gnutls_assert ();
- return _gnutls_asn2err (result);
+ goto fail;
}
- /* Step 3. Write the signatureAlgorithm field.
- */
- result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm",
- key->pk_algorithm, dig, key->params,
- key->params_size);
+ result = gnutls_x509_crq_privkey_sign (crq, privkey, dig, flags);
if (result < 0)
{
gnutls_assert ();
- return result;
+ goto fail;
}
- return 0;
+ result = 0;
+
+fail:
+ gnutls_privkey_deinit(privkey);
+
+ return result;
}
/**
@@ -2445,5 +2423,100 @@ gnutls_x509_crq_get_key_id (gnutls_x509_crq_t crq, unsigned int flags,
return result;
}
+/**
+ * gnutls_x509_crq_privkey_sign:
+ * @crq: should contain a #gnutls_x509_crq_t structure
+ * @key: holds a private key
+ * @dig: The message digest to use, i.e., %GNUTLS_DIG_SHA1
+ * @flags: must be 0
+ *
+ * This function will sign the certificate request with a private key.
+ * This must be the same key as the one used in
+ * gnutls_x509_crt_set_key() since a certificate request is self
+ * signed.
+ *
+ * This must be the last step in a certificate request generation
+ * since all the previously set parameters are now signed.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ * %GNUTLS_E_ASN1_VALUE_NOT_FOUND is returned if you didn't set all
+ * information in the certificate request (e.g., the version using
+ * gnutls_x509_crq_set_version()).
+ *
+ **/
+int
+gnutls_x509_crq_privkey_sign (gnutls_x509_crq_t crq, gnutls_privkey_t key,
+ gnutls_digest_algorithm_t dig, unsigned int flags)
+{
+ int result;
+ gnutls_datum_t signature;
+ gnutls_datum_t tbs;
+
+ if (crq == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Make sure version field is set. */
+ if (gnutls_x509_crq_get_version (crq) == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
+ {
+ result = gnutls_x509_crq_set_version (crq, 1);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+ }
+
+ /* Step 1. Self sign the request.
+ */
+ result =
+ _gnutls_x509_get_tbs (crq->crq, "certificationRequestInfo",
+ &tbs);
+
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ result = gnutls_privkey_sign_data (key, dig, 0, &tbs, &signature);
+ gnutls_free(tbs.data);
+
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ /* Step 2. write the signature (bits)
+ */
+ result =
+ asn1_write_value (crq->crq, "signature", signature.data,
+ signature.size * 8);
+
+ _gnutls_free_datum (&signature);
+
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ return _gnutls_asn2err (result);
+ }
+
+ /* Step 3. Write the signatureAlgorithm field.
+ */
+ result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm",
+ gnutls_privkey_get_pk_algorithm(key, NULL), dig);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ return 0;
+}
+
+
#endif /* ENABLE_PKI */
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 76747f251c..7b4e7d4596 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -422,8 +422,7 @@ cleanup:
int
_gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name,
gnutls_pk_algorithm_t pk_algorithm,
- gnutls_digest_algorithm_t dig,
- bigint_t * params, int params_size)
+ gnutls_digest_algorithm_t dig)
{
int result;
char name[128];
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index f272c08e6f..31c7c4f579 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -42,6 +42,7 @@
#include <x509_int.h>
#include <common.h>
#include <sign.h>
+#include <gnutls/abstract.h>
/* Writes the digest information and the digest in a DER encoded
* structure. The digest info is allocated and stored into the info structure.
@@ -199,15 +200,12 @@ pk_dsa_hash (const gnutls_datum_t * text, gnutls_datum_t * hash)
* of the TBS and sign it on the fly.
*/
int
-_gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name,
- gnutls_digest_algorithm_t hash,
- gnutls_x509_privkey_t signer,
- gnutls_datum_t * signature)
+_gnutls_x509_get_tbs (ASN1_TYPE cert, const char *tbs_name,
+ gnutls_datum_t * tbs)
{
int result;
opaque *buf;
int buf_size;
- gnutls_datum_t tbs;
buf_size = 0;
asn1_der_coding (cert, tbs_name, NULL, &buf_size, NULL);
@@ -228,13 +226,10 @@ _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name,
return _gnutls_asn2err (result);
}
- tbs.data = buf;
- tbs.size = buf_size;
-
- result = gnutls_x509_privkey_sign_data2 (signer, hash, 0, &tbs, signature);
- gnutls_free (buf);
+ tbs->data = buf;
+ tbs->size = buf_size;
- return result;
+ return 0;
}
/*-
@@ -253,10 +248,11 @@ int
_gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
gnutls_digest_algorithm_t dig,
gnutls_x509_crt_t issuer,
- gnutls_x509_privkey_t issuer_key)
+ gnutls_privkey_t issuer_key)
{
int result;
gnutls_datum_t signature;
+ gnutls_datum_t tbs;
char name[128];
/* Step 1. Copy the issuer's name into the certificate.
@@ -277,9 +273,7 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
_gnutls_str_cat (name, sizeof (name), ".signature");
result = _gnutls_x509_write_sig_params (src, name,
- issuer_key->pk_algorithm, dig,
- issuer_key->params,
- issuer_key->params_size);
+ gnutls_privkey_get_pk_algorithm(issuer_key, NULL), dig);
if (result < 0)
{
gnutls_assert ();
@@ -288,7 +282,16 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
/* Step 2. Sign the certificate.
*/
- result = _gnutls_x509_sign_tbs (src, src_name, dig, issuer_key, &signature);
+ result = _gnutls_x509_get_tbs (src, src_name, &tbs);
+
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ result = gnutls_privkey_sign_data (issuer_key, dig, 0, &tbs, &signature);
+ gnutls_free(tbs.data);
if (result < 0)
{
@@ -314,9 +317,7 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
*/
result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm",
- issuer_key->pk_algorithm, dig,
- issuer_key->params,
- issuer_key->params_size);
+ gnutls_privkey_get_pk_algorithm(issuer_key, NULL), dig);
if (result < 0)
{
gnutls_assert ();
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index ede4814bac..ea68d59d23 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -27,6 +27,7 @@
# define X509_H
#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
#include <libtasn1.h>
@@ -134,14 +135,12 @@ int _gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
gnutls_datum_t * dn);
/* sign.c */
-int _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name,
- gnutls_digest_algorithm_t hash,
- gnutls_x509_privkey_t signer,
- gnutls_datum_t * signature);
+int _gnutls_x509_get_tbs (ASN1_TYPE cert, const char *tbs_name,
+ gnutls_datum_t * tbs);
int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
gnutls_digest_algorithm_t,
gnutls_x509_crt_t issuer,
- gnutls_x509_privkey_t issuer_key);
+ gnutls_privkey_t issuer_key);
/* dn.c */
#define OID_X520_COUNTRY_NAME "2.5.4.6"
@@ -303,8 +302,7 @@ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value,
int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name,
gnutls_pk_algorithm_t pk_algorithm,
- gnutls_digest_algorithm_t,
- bigint_t * params, int params_size);
+ gnutls_digest_algorithm_t);
/* pkcs12.h */
#include <gnutls/pkcs12.h>
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index f65e7af96b..dc47af20c3 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -752,6 +752,7 @@ gnutls_x509_crt_sign2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
gnutls_digest_algorithm_t dig, unsigned int flags)
{
int result;
+ gnutls_privkey_t privkey;
if (crt == NULL || issuer == NULL || issuer_key == NULL)
{
@@ -759,19 +760,33 @@ gnutls_x509_crt_sign2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
return GNUTLS_E_INVALID_REQUEST;
}
- /* disable all the unneeded OPTIONAL fields.
- */
- disable_optional_stuff (crt);
-
- result = _gnutls_x509_pkix_sign (crt->cert, "tbsCertificate",
- dig, issuer, issuer_key);
+ result = gnutls_privkey_init(&privkey);
if (result < 0)
{
gnutls_assert ();
return result;
}
- return 0;
+ result = gnutls_privkey_import_x509(privkey, issuer_key, 0);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto fail;
+ }
+
+ result = gnutls_x509_crt_privkey_sign (crt, issuer, privkey, dig, flags);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto fail;
+ }
+
+ result = 0;
+
+fail:
+ gnutls_privkey_deinit(privkey);
+
+ return result;
}
/**
@@ -1279,4 +1294,50 @@ gnutls_x509_crt_set_key_purpose_oid (gnutls_x509_crt_t cert,
}
+/**
+ * gnutls_x509_crt_privkey_sign:
+ * @crt: a certificate of type #gnutls_x509_crt_t
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ * @dig: The message digest to use, %GNUTLS_DIG_SHA1 is a safe choice
+ * @flags: must be 0
+ *
+ * This function will sign the certificate with the issuer's private key, and
+ * will copy the issuer's information into the certificate.
+ *
+ * This must be the last step in a certificate generation since all
+ * the previously set parameters are now signed.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crt_privkey_sign (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
+ gnutls_privkey_t issuer_key,
+ gnutls_digest_algorithm_t dig, unsigned int flags)
+{
+ int result;
+
+ if (crt == NULL || issuer == NULL || issuer_key == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* disable all the unneeded OPTIONAL fields.
+ */
+ disable_optional_stuff (crt);
+
+ result = _gnutls_x509_pkix_sign (crt->cert, "tbsCertificate",
+ dig, issuer, issuer_key);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ return 0;
+}
+
+
#endif /* ENABLE_PKI */