summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-26 14:18:26 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-26 14:18:26 +0000
commit95f9e0fd4a4acc9a7552e4efc0dc04627936305a (patch)
treed1ed8e1e4d785de66d9a4e0a9b145c60f9d4c1ed
parent647c0a87ec285f1426e512de977c7e1a94c189d6 (diff)
downloadgnutls-95f9e0fd4a4acc9a7552e4efc0dc04627936305a.tar.gz
Added support for generating CRLs in the library and the
certtool utility.
-rw-r--r--NEWS2
-rw-r--r--doc/TODO3
-rw-r--r--doc/tex/certificate.tex8
-rw-r--r--includes/gnutls/x509.h13
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/x509/Makefile.am2
-rw-r--r--lib/x509/crl.c2
-rw-r--r--lib/x509/sign.c115
-rw-r--r--lib/x509/sign.h2
-rw-r--r--lib/x509/x509_write.c89
-rw-r--r--src/certtool-gaa.c107
-rw-r--r--src/certtool-gaa.h30
-rw-r--r--src/certtool.c246
-rw-r--r--src/certtool.gaa2
14 files changed, 418 insertions, 206 deletions
diff --git a/NEWS b/NEWS
index 370e953722..ad73720b79 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Version 1.1.1
- Added PKCS #7 support to certtool utility.
- Added support for reading and generating CRL distribution
points extensions in certificates.
+- Added support for generating CRLs in the library and the
+ certtool utility.
- Added support for the Subject Key ID PKIX extension.
Version 1.1.0 (21/12/2003)
diff --git a/doc/TODO b/doc/TODO
index b5b327684f..3d6a8afadb 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -3,6 +3,7 @@ anything), contact the developer's mailing list (gnutls-dev@lists.gnupg.org),
in order to avoid having people working on the same thing.
Current list:
+* Add support for TLS 1.1
* Add gnutls_certificate_set_openpgp_keyring()
functions, similar to gnutls_certificate_set_openpgp_key().
* Use subkeys with the 0x20 flag in openpgp keys (if present),
@@ -10,8 +11,6 @@ Current list:
* Add function to extract the signers of an openpgp key. Should
be similar to gnutls_x509_crt_get_dn_oid().
* Add function to verify an openpgp key against a plain key.
-* Add support for generating CRLs.
-* Add support for TLS 1.1
* Drop the compatibility functions.
* Convert documentation to texinfo format
* Audit the code
diff --git a/doc/tex/certificate.tex b/doc/tex/certificate.tex
index 3a456d453d..fd9d5b2807 100644
--- a/doc/tex/certificate.tex
+++ b/doc/tex/certificate.tex
@@ -101,7 +101,13 @@ which should return a signed certificate.
A PKCS \#12 structure usually contains a user's private keys and
certificates. It is commonly used in browsers to export and import
the user's identities.
-
+\par
+In \gnutls{} the PKCS \#12 structures are handled using the
+\emph{gnutls\_pkcs12} type. This is an abstract type that
+may hold several \emph{gnutls\_pkcs12\_bag} types. The Bag types are the
+holders of the actual data, which may be certificates, private
+keys or encrypted data. An Bag of type encrypted should be decrypted
+in order for its data to be accessed.
\par
The following example is about generating a PKCS \#12 structure.
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index fc80f9dd5a..9d16eafdce 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -191,6 +191,19 @@ int gnutls_x509_crl_get_crt_serial(gnutls_x509_crl crl, int index, unsigned char
int gnutls_x509_crl_check_issuer( gnutls_x509_crl crl,
gnutls_x509_crt issuer);
+/* CRL writing.
+ */
+int gnutls_x509_crl_set_version(gnutls_x509_crl crl, unsigned int version);
+int gnutls_x509_crl_sign(gnutls_x509_crl crl, gnutls_x509_crt issuer,
+ gnutls_x509_privkey issuer_key);
+int gnutls_x509_crl_set_this_update(gnutls_x509_crl crl, time_t act_time);
+int gnutls_x509_crl_set_next_update(gnutls_x509_crl crl, time_t exp_time);
+int gnutls_x509_crl_set_crt_serial(gnutls_x509_crl crl, const void* serial,
+ size_t serial_size, time_t revocation_time);
+int gnutls_x509_crl_set_crt(gnutls_x509_crl crl, gnutls_x509_crt crt,
+ time_t revocation_time);
+
+
/* PKCS7 structures handling
*/
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ef1f5e3a25..d1142c5afc 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -56,7 +56,8 @@ libgnutls_la_LIBADD = $(MINITASN1_OBJECTS) x509/dn.lo x509/crl.lo x509/common.lo
x509/x509.lo x509/extensions.lo x509/compat.lo x509/verify.lo x509/dsa.lo \
x509/mpi.lo x509/privkey.lo x509/pkcs7.lo x509/crq.lo x509/xml.lo x509/sign.lo \
x509/pkcs5.lo x509/privkey_pkcs8.lo x509/pkcs12.lo x509/pkcs12_bag.lo \
- x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo
+ x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo \
+ x509/crl_write.lo
libgnutls_la_LDFLAGS = $(LIBASN1_LINK) $(LIBGCRYPT_LIBS) \
$(libgnutls_version_script_cmd) \
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index b90f0bd869..a27bf80fc5 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -9,7 +9,7 @@ noinst_LTLIBRARIES = libx509.la
COBJECTS = crl.c dn.c common.c x509.c extensions.c dsa.c \
rfc2818_hostname.c verify.c mpi.c privkey.c pkcs7.c \
crq.c xml.c sign.c pkcs5.c privkey_pkcs8.c pkcs12.c \
- pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c
+ pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c crl_write.c
COMPAT_OBJECTS = compat.c
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index d4e05b6cd2..be4edc4a1d 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -393,7 +393,7 @@ int gnutls_x509_crl_get_crt_count(gnutls_x509_crl crl)
}
/**
- * gnutls_x509_crl_get_crt - This function returns the serial number of a revoked certificate
+ * gnutls_x509_crl_get_crt_serial - This function returns the serial number of a revoked certificate
* @crl: should contain a gnutls_x509_crl structure
* @index: the index of the certificate to extract (starting from 0)
* @serial: where the serial number will be copied
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index bc0e0d9b9f..340a599174 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -262,4 +262,119 @@ gnutls_datum tbs;
return result;
}
+/*-
+ * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key
+ * @src: should contain an ASN1_TYPE
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ *
+ * This function will sign a CRL or a certificate with the issuer's private key, and
+ * will copy the issuer's information into the CRL or certificate.
+ *
+ * Returns 0 on success.
+ *
+ -*/
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key)
+{
+int result;
+gnutls_datum signature;
+const char* pk;
+char name[128];
+
+ /* Step 1. Copy the issuer's name into the certificate.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".issuer");
+
+ result = _gnutls_asn1_copy_node( &src, name,
+ issuer->cert, "tbsCertificate.subject");
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Step 1.5. Write the signature stuff in the tbsCertificate.
+ */
+ /* write the RSA OID
+ */
+ pk = _gnutls_x509_sign2oid( issuer_key->pk_algorithm, GNUTLS_MAC_SHA);
+ if (pk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".signature.algorithm");
+
+ result = asn1_write_value( src, name, pk, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+#warning CHECKME
+ /* disable parameters, which are not used in RSA.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".signature.parameters");
+
+ result = asn1_write_value( src, name, NULL, 0);
+ if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
+ /* Here we ignore the element not found error, since this
+ * may have been disabled before.
+ */
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+
+ /* Step 2. Sign the certificate.
+ */
+ result = _gnutls_x509_sign_tbs( src, src_name, GNUTLS_MAC_SHA,
+ issuer_key, &signature);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* write the signature (bits)
+ */
+ result = asn1_write_value( src, "signature", signature.data, signature.size*8);
+
+ _gnutls_free_datum( &signature);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ /* Step 2. Move up and write the AlgorithmIdentifier, which is also
+ * the same.
+ */
+
+ /* write the RSA or DSA OID
+ */
+ result = asn1_write_value( src, "signatureAlgorithm.algorithm", pk, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+#warning CHECKME
+ /* disable parameters, which are not used in RSA.
+ */
+ result = asn1_write_value( src, "signatureAlgorithm.parameters", NULL, 0);
+ if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
+ /* Here we ignore the element not found error, since this
+ * may have been disabled before.
+ */
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return 0;
+}
+
#endif
diff --git a/lib/x509/sign.h b/lib/x509/sign.h
index dd6936f346..08e0475f72 100644
--- a/lib/x509/sign.h
+++ b/lib/x509/sign.h
@@ -2,3 +2,5 @@ int _gnutls_x509_sign( const gnutls_datum* tbs, gnutls_mac_algorithm hash,
gnutls_x509_privkey signer, gnutls_datum* signature);
int _gnutls_x509_sign_tbs( ASN1_TYPE cert, const char* tbs_name,
gnutls_mac_algorithm hash, gnutls_x509_privkey signer, gnutls_datum* signature);
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key);
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index 403d9997b5..8de1ff010c 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -19,7 +19,7 @@
*
*/
-/* This file contains functions to handle PKCS #10 certificate requests.
+/* This file contains functions to handle X.509 certificate generation.
*/
#include <gnutls_int.h>
@@ -373,8 +373,6 @@ int gnutls_x509_crt_sign(gnutls_x509_crt crt, gnutls_x509_crt issuer,
gnutls_x509_privkey issuer_key)
{
int result;
-gnutls_datum signature;
-const char* pk;
if (crt==NULL || issuer == NULL) {
gnutls_assert();
@@ -384,89 +382,14 @@ const char* pk;
/* disable all the unneeded OPTIONAL fields.
*/
disable_optional_stuff( crt);
-
- /* Step 1. Copy the issuer's name into the certificate.
- */
- result = _gnutls_asn1_copy_node( &crt->cert, "tbsCertificate.issuer",
- issuer->cert, "tbsCertificate.subject");
- if (result < 0) {
- gnutls_assert();
- return result;
- }
- /* Step 1.5. Write the signature stuff in the tbsCertificate.
- */
- /* write the RSA OID
- */
- pk = _gnutls_x509_sign2oid( issuer_key->pk_algorithm, GNUTLS_MAC_SHA);
- if (pk == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
-
- /* Step 2. Sign the certificate.
- */
- result = _gnutls_x509_sign_tbs( crt->cert, "tbsCertificate", GNUTLS_MAC_SHA,
- issuer_key, &signature);
-
+ result = _gnutls_x509_pkix_sign( crt->cert, "tbsCertificate", issuer,
+ issuer_key);
if (result < 0) {
gnutls_assert();
return result;
}
-
- /* write the signature (bits)
- */
- result = asn1_write_value( crt->cert, "signature", signature.data, signature.size*8);
-
- _gnutls_free_datum( &signature);
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Step 2. Move up and write the AlgorithmIdentifier, which is also
- * the same.
- */
-
-
- /* write the RSA OID
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
+
return 0;
}
@@ -533,8 +456,8 @@ int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const void* serial,
return GNUTLS_E_INVALID_REQUEST;
}
- if ((ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size)) < 0)
- {
+ ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size);
+ if (ret != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(ret);
}
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index 64609465f4..7ec736b7b0 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -132,6 +132,7 @@ void gaa_help(void)
printf("Certtool help\nUsage: certtool [options]\n");
__gaa_helpsingle('s', "generate-self-signed", "", "Generate a self-signed certificate.");
__gaa_helpsingle('c', "generate-certificate", "", "Generate a signed certificate.");
+ __gaa_helpsingle(0, "generate-crl", "", "Generate a CRL.");
__gaa_helpsingle('u', "update-certificate", "", "Update a signed certificate.");
__gaa_helpsingle('p', "generate-privkey", "", "Generate a private key.");
__gaa_helpsingle('q', "generate-request", "", "Generate a PKCS #10 certificate request.");
@@ -175,35 +176,35 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 86 "certtool.gaa"
+#line 88 "certtool.gaa"
int debug;
-#line 83 "certtool.gaa"
+#line 85 "certtool.gaa"
char *infile;
-#line 80 "certtool.gaa"
+#line 82 "certtool.gaa"
char *outfile;
-#line 77 "certtool.gaa"
+#line 79 "certtool.gaa"
int bits;
-#line 74 "certtool.gaa"
+#line 76 "certtool.gaa"
int outcert_format;
-#line 71 "certtool.gaa"
+#line 73 "certtool.gaa"
int incert_format;
-#line 68 "certtool.gaa"
+#line 70 "certtool.gaa"
int export;
-#line 65 "certtool.gaa"
+#line 67 "certtool.gaa"
int dsa;
-#line 62 "certtool.gaa"
+#line 64 "certtool.gaa"
int pkcs8;
-#line 47 "certtool.gaa"
+#line 49 "certtool.gaa"
char *pass;
-#line 44 "certtool.gaa"
+#line 46 "certtool.gaa"
char *ca;
-#line 41 "certtool.gaa"
+#line 43 "certtool.gaa"
char *ca_privkey;
-#line 38 "certtool.gaa"
+#line 40 "certtool.gaa"
char *cert;
-#line 35 "certtool.gaa"
+#line 37 "certtool.gaa"
char *request;
-#line 32 "certtool.gaa"
+#line 34 "certtool.gaa"
char *privkey;
#line 17 "certtool.gaa"
int action;
@@ -261,7 +262,7 @@ int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 31
+#define GAA_NB_OPTION 32
#define GAAOPTID_copyright 1
#define GAAOPTID_version 2
#define GAAOPTID_help 3
@@ -291,8 +292,9 @@ int gaa_error = 0;
#define GAAOPTID_generate_request 27
#define GAAOPTID_generate_privkey 28
#define GAAOPTID_update_certificate 29
-#define GAAOPTID_generate_certificate 30
-#define GAAOPTID_generate_self_signed 31
+#define GAAOPTID_generate_crl 30
+#define GAAOPTID_generate_certificate 31
+#define GAAOPTID_generate_self_signed 32
#line 168 "gaa.skel"
@@ -599,6 +601,7 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECK1STR("q", GAAOPTID_generate_request);
GAA_CHECK1STR("p", GAAOPTID_generate_privkey);
GAA_CHECK1STR("u", GAAOPTID_update_certificate);
+ GAA_CHECK1STR("", GAAOPTID_generate_crl);
GAA_CHECK1STR("c", GAAOPTID_generate_certificate);
GAA_CHECK1STR("s", GAAOPTID_generate_self_signed);
@@ -634,6 +637,7 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("generate-request", GAAOPTID_generate_request);
GAA_CHECKSTR("generate-privkey", GAAOPTID_generate_privkey);
GAA_CHECKSTR("update-certificate", GAAOPTID_update_certificate);
+ GAA_CHECKSTR("generate-crl", GAAOPTID_generate_crl);
GAA_CHECKSTR("generate-certificate", GAAOPTID_generate_certificate);
GAA_CHECKSTR("generate-self-signed", GAAOPTID_generate_self_signed);
@@ -680,21 +684,21 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_copyright:
OK = 0;
-#line 92 "certtool.gaa"
+#line 94 "certtool.gaa"
{ print_license(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_version:
OK = 0;
-#line 91 "certtool.gaa"
+#line 93 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 89 "certtool.gaa"
+#line 91 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
@@ -704,7 +708,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
gaa_index++;
-#line 87 "certtool.gaa"
+#line 89 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
return GAA_OK;
@@ -714,7 +718,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
gaa_index++;
-#line 84 "certtool.gaa"
+#line 86 "certtool.gaa"
{ gaaval->infile = GAATMP_infile.arg1 ;};
return GAA_OK;
@@ -724,7 +728,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
gaa_index++;
-#line 81 "certtool.gaa"
+#line 83 "certtool.gaa"
{ gaaval->outfile = GAATMP_outfile.arg1 ;};
return GAA_OK;
@@ -734,84 +738,84 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
gaa_index++;
-#line 78 "certtool.gaa"
+#line 80 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_outder:
OK = 0;
-#line 75 "certtool.gaa"
+#line 77 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inder:
OK = 0;
-#line 72 "certtool.gaa"
+#line 74 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_export_ciphers:
OK = 0;
-#line 69 "certtool.gaa"
+#line 71 "certtool.gaa"
{ gaaval->export=1 ;};
return GAA_OK;
break;
case GAAOPTID_dsa:
OK = 0;
-#line 66 "certtool.gaa"
+#line 68 "certtool.gaa"
{ gaaval->dsa=1 ;};
return GAA_OK;
break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 63 "certtool.gaa"
+#line 65 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
return GAA_OK;
break;
case GAAOPTID_to_p12:
OK = 0;
-#line 60 "certtool.gaa"
+#line 62 "certtool.gaa"
{ gaaval->action = 8; ;};
return GAA_OK;
break;
case GAAOPTID_key_info:
OK = 0;
-#line 58 "certtool.gaa"
+#line 60 "certtool.gaa"
{ gaaval->action = 6; ;};
return GAA_OK;
break;
case GAAOPTID_p7_info:
OK = 0;
-#line 56 "certtool.gaa"
+#line 58 "certtool.gaa"
{ gaaval->action = 12; ;};
return GAA_OK;
break;
case GAAOPTID_p12_info:
OK = 0;
-#line 54 "certtool.gaa"
+#line 56 "certtool.gaa"
{ gaaval->action = 9; ;};
return GAA_OK;
break;
case GAAOPTID_crl_info:
OK = 0;
-#line 52 "certtool.gaa"
+#line 54 "certtool.gaa"
{ gaaval->action = 11; ;};
return GAA_OK;
break;
case GAAOPTID_certificate_info:
OK = 0;
-#line 50 "certtool.gaa"
+#line 52 "certtool.gaa"
{ gaaval->action = 2; ;};
return GAA_OK;
@@ -821,7 +825,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_password.arg1, gaa_getstr, GAATMP_password.size1);
gaa_index++;
-#line 48 "certtool.gaa"
+#line 50 "certtool.gaa"
{ gaaval->pass = GAATMP_password.arg1 ;};
return GAA_OK;
@@ -831,7 +835,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_certificate.arg1, gaa_getstr, GAATMP_load_ca_certificate.size1);
gaa_index++;
-#line 45 "certtool.gaa"
+#line 47 "certtool.gaa"
{ gaaval->ca = GAATMP_load_ca_certificate.arg1 ;};
return GAA_OK;
@@ -841,7 +845,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, GAATMP_load_ca_privkey.size1);
gaa_index++;
-#line 42 "certtool.gaa"
+#line 44 "certtool.gaa"
{ gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;};
return GAA_OK;
@@ -851,7 +855,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, GAATMP_load_certificate.size1);
gaa_index++;
-#line 39 "certtool.gaa"
+#line 41 "certtool.gaa"
{ gaaval->cert = GAATMP_load_certificate.arg1 ;};
return GAA_OK;
@@ -861,7 +865,7 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_request.arg1, gaa_getstr, GAATMP_load_request.size1);
gaa_index++;
-#line 36 "certtool.gaa"
+#line 38 "certtool.gaa"
{ gaaval->request = GAATMP_load_request.arg1 ;};
return GAA_OK;
@@ -871,46 +875,53 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, GAATMP_load_privkey.size1);
gaa_index++;
-#line 33 "certtool.gaa"
+#line 35 "certtool.gaa"
{ gaaval->privkey = GAATMP_load_privkey.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_generate_dh_params:
OK = 0;
-#line 30 "certtool.gaa"
+#line 32 "certtool.gaa"
{ gaaval->action=10; ;};
return GAA_OK;
break;
case GAAOPTID_verify_chain:
OK = 0;
-#line 28 "certtool.gaa"
+#line 30 "certtool.gaa"
{ gaaval->action=5; ;};
return GAA_OK;
break;
case GAAOPTID_generate_request:
OK = 0;
-#line 26 "certtool.gaa"
+#line 28 "certtool.gaa"
{ gaaval->action=3; ;};
return GAA_OK;
break;
case GAAOPTID_generate_privkey:
OK = 0;
-#line 24 "certtool.gaa"
+#line 26 "certtool.gaa"
{ gaaval->action=1; ;};
return GAA_OK;
break;
case GAAOPTID_update_certificate:
OK = 0;
-#line 22 "certtool.gaa"
+#line 24 "certtool.gaa"
{ gaaval->action=7; ;};
return GAA_OK;
break;
+ case GAAOPTID_generate_crl:
+ OK = 0;
+#line 22 "certtool.gaa"
+{ gaaval->action=13; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_generate_certificate:
OK = 0;
#line 20 "certtool.gaa"
@@ -949,7 +960,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 94 "certtool.gaa"
+#line 96 "certtool.gaa"
{ gaaval->bits = 1024; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index 9a289ed0ee..18cca0ca96 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,35 +8,35 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 86 "certtool.gaa"
+#line 88 "certtool.gaa"
int debug;
-#line 83 "certtool.gaa"
+#line 85 "certtool.gaa"
char *infile;
-#line 80 "certtool.gaa"
+#line 82 "certtool.gaa"
char *outfile;
-#line 77 "certtool.gaa"
+#line 79 "certtool.gaa"
int bits;
-#line 74 "certtool.gaa"
+#line 76 "certtool.gaa"
int outcert_format;
-#line 71 "certtool.gaa"
+#line 73 "certtool.gaa"
int incert_format;
-#line 68 "certtool.gaa"
+#line 70 "certtool.gaa"
int export;
-#line 65 "certtool.gaa"
+#line 67 "certtool.gaa"
int dsa;
-#line 62 "certtool.gaa"
+#line 64 "certtool.gaa"
int pkcs8;
-#line 47 "certtool.gaa"
+#line 49 "certtool.gaa"
char *pass;
-#line 44 "certtool.gaa"
+#line 46 "certtool.gaa"
char *ca;
-#line 41 "certtool.gaa"
+#line 43 "certtool.gaa"
char *ca_privkey;
-#line 38 "certtool.gaa"
+#line 40 "certtool.gaa"
char *cert;
-#line 35 "certtool.gaa"
+#line 37 "certtool.gaa"
char *request;
-#line 32 "certtool.gaa"
+#line 34 "certtool.gaa"
char *privkey;
#line 17 "certtool.gaa"
int action;
diff --git a/src/certtool.c b/src/certtool.c
index 28bb34c908..0d62ed2f12 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -32,6 +32,7 @@
#include <gnutls/pkcs12.h>
#include <unistd.h>
+static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all);
int generate_prime(int bits);
void pkcs7_info( void);
void pkcs12_info( void);
@@ -49,6 +50,7 @@ static void print_certificate_info( gnutls_x509_crt crt, FILE* out, unsigned int
static void gaa_parser(int argc, char **argv);
void generate_self_signed( void);
void generate_request(void);
+gnutls_x509_crt* load_cert_list(int mand, int *size);
static gaainfo info;
FILE* outfile;
@@ -460,6 +462,56 @@ gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
}
+gnutls_x509_crl generate_crl( void)
+{
+ gnutls_x509_crl crl;
+ gnutls_x509_crt * crts;
+ int size;
+ int days, result, i;
+ int vers = 2; /* the default version in the CRL
+ */
+
+ result = gnutls_x509_crl_init(&crl);
+ if (result < 0) {
+ fprintf(stderr, "crl_init: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ crts = load_cert_list(1, &size);
+
+ for (i=0;i<size;i++) {
+
+ result = gnutls_x509_crl_set_crt( crl, crts[i], time(0));
+ if (result < 0) {
+ fprintf(stderr, "serial: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+ }
+
+ fprintf(stderr, "\n\nthisUpdate/nextUpdate time.\n");
+ gnutls_x509_crl_set_this_update( crl, time(NULL));
+
+ do {
+ days = read_int( "The next CRL will be issued in (days): ");
+ } while( days==0);
+
+ result = gnutls_x509_crl_set_next_update( crl, time(NULL)+days*24*60*60);
+ if (result < 0) {
+ fprintf(stderr, "next_update: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ /* Version.
+ */
+ result = gnutls_x509_crl_set_version( crl, vers);
+ if (result < 0) {
+ fprintf(stderr, "set_version: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ return crl;
+}
+
gnutls_x509_crt update_certificate( void)
{
gnutls_x509_crt crt;
@@ -565,6 +617,43 @@ void generate_signed_certificate( void)
gnutls_x509_privkey_deinit(key);
}
+void generate_signed_crl( void)
+{
+ gnutls_x509_crl crl;
+ size_t size;
+ int result;
+ gnutls_x509_privkey ca_key;
+ gnutls_x509_crt ca_crt;
+
+ fprintf(stderr, "Generating a signed CRLe...\n");
+
+ ca_key = load_ca_private_key();
+ ca_crt = load_ca_cert();
+
+ crl = generate_crl();
+
+ print_crl_info( crl, stderr, 0);
+
+ fprintf(stderr, "\n\nSigning CRL...\n");
+
+ result = gnutls_x509_crl_sign( crl, ca_crt, ca_key);
+ if (result < 0) {
+ fprintf(stderr, "crl_sign: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ size = sizeof(buffer);
+ result = gnutls_x509_crl_export( crl, out_cert_format, buffer, &size);
+ if (result < 0) {
+ fprintf(stderr, "crl_export: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ fwrite( buffer, 1, size, outfile);
+
+ gnutls_x509_crl_deinit(crl);
+}
+
void update_signed_certificate( void)
{
gnutls_x509_crt crt;
@@ -680,6 +769,9 @@ int ret;
case 12:
pkcs7_info();
break;
+ case 13:
+ generate_signed_crl();
+ break;
default:
fprintf(stderr, "GnuTLS' certtool utility.\n");
fprintf(stderr, "Please use the --help to get help on this program.\n");
@@ -1011,84 +1103,98 @@ static void print_certificate_info( gnutls_x509_crt crt, FILE* out, unsigned int
}
}
-void crl_info(void)
+static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all)
{
- gnutls_x509_crl crl;
int ret, rc;
- size_t size;
time_t tim;
- unsigned int i;
- gnutls_datum pem;
- unsigned char serial[40];
+ unsigned int i, j;
+ char serial[128];
size_t serial_size = sizeof(serial), dn_size;
char printable[256];
char *print, dn[256];
const char* cprint;
-
- size = fread( buffer, 1, sizeof(buffer)-1, infile);
- buffer[size] = 0;
- gnutls_x509_crl_init(&crl);
-
- pem.data = buffer;
- pem.size = size;
-
- ret = gnutls_x509_crl_import(crl, &pem, in_cert_format);
- if (ret < 0) {
- fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
- exit(1);
- }
-
- fprintf(outfile, "Version: %d\n", gnutls_x509_crl_get_version(crl));
+ fprintf(out, "Version: %d\n", gnutls_x509_crl_get_version(crl));
/* Issuer
*/
- dn_size = sizeof(dn);
+ if (all) {
+ dn_size = sizeof(dn);
- ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
- if (ret >= 0)
- fprintf(outfile, "Issuer: %s\n", dn);
+ ret = gnutls_x509_crl_get_issuer_dn(crl, dn, &dn_size);
+ if (ret >= 0)
+ fprintf(out, "Issuer: %s\n", dn);
- fprintf(outfile, "Signature Algorithm: ");
- ret = gnutls_x509_crl_get_signature_algorithm(crl);
+ fprintf(out, "Signature Algorithm: ");
+ ret = gnutls_x509_crl_get_signature_algorithm(crl);
- cprint = get_algorithm( ret);
- fprintf(outfile, "%s\n", cprint);
+ cprint = get_algorithm( ret);
+ fprintf(out, "%s\n", cprint);
+ }
/* Validity
*/
- fprintf(outfile, "Update dates:\n");
+ fprintf(out, "Update dates:\n");
tim = gnutls_x509_crl_get_this_update(crl);
- fprintf(outfile, "\tIssued at: %s", ctime(&tim));
+ fprintf(out, "\tIssued at: %s", ctime(&tim));
tim = gnutls_x509_crl_get_next_update(crl);
- fprintf(outfile, "\tNext at: %s", ctime(&tim));
+ fprintf(out, "\tNext at: %s", ctime(&tim));
- fprintf(outfile, "\n");
+ fprintf(out, "\n");
/* Count the certificates.
*/
rc = gnutls_x509_crl_get_crt_count( crl);
- fprintf(outfile, "Revoked certificates: %d\n", rc);
+ fprintf(out, "Revoked certificates: %d\n", rc);
- for (i=0;i<(unsigned int)rc;i++) {
+ for (j=0;j<(unsigned int)rc;j++) {
/* serial number
*/
serial_size = sizeof(serial);
- if (gnutls_x509_crl_get_crt_serial(crl, i, serial, &serial_size, &tim) >= 0) {
+ ret = gnutls_x509_crl_get_crt_serial(crl, j, serial, &serial_size, &tim);
+
+ if (ret < 0) {
+ fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
+ } else {
print = printable;
for (i = 0; i < serial_size; i++) {
sprintf(print, "%.2x ",
(unsigned char) serial[i]);
print += 3;
}
- fprintf(outfile, "\tCertificate SN: %s\n", printable);
- fprintf(outfile, "\tRevoked at: %s\n", ctime( &tim));
+ fprintf(out, "\tCertificate SN: %s\n", printable);
+ fprintf(out, "\tRevoked at: %s\n", ctime( &tim));
}
+ }
+
+}
+
+void crl_info()
+{
+ gnutls_x509_crl crl;
+ int ret;
+ size_t size;
+ gnutls_datum pem;
+
+ size = fread( buffer, 1, sizeof(buffer)-1, infile);
+ buffer[size] = 0;
+
+ gnutls_x509_crl_init(&crl);
+ pem.data = buffer;
+ pem.size = size;
+
+ ret = gnutls_x509_crl_import(crl, &pem, in_cert_format);
+ if (ret < 0) {
+ fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
+ exit(1);
}
+
+ print_crl_info( crl, outfile, 1);
+
}
void privkey_info( void)
@@ -1350,13 +1456,29 @@ size_t size;
*/
gnutls_x509_crt load_cert(int mand)
{
+gnutls_x509_crt *crt;
+int size;
+
+ crt = load_cert_list( mand, &size);
+
+ return crt[0];
+}
+
+#define MAX_CERTS 256
+
+/* Loads a certificate list
+ */
+gnutls_x509_crt* load_cert_list(int mand, int *crt_size)
+{
FILE* fd;
-gnutls_x509_crt crt;
-int ret;
+static gnutls_x509_crt crt[MAX_CERTS];
+char* ptr;
+int ret, i;
gnutls_datum dat;
-size_t size;
+size_t size, ptr_size;
- fprintf(stderr, "Loading certificate...\n");
+ *crt_size = 0;
+ fprintf(stderr, "Loading certificate list...\n");
if (info.cert==NULL) {
fprintf(stderr, "You must specify a certificate.\n");
@@ -1375,20 +1497,36 @@ size_t size;
fclose(fd);
- ret = gnutls_x509_crt_init(&crt);
- if (ret < 0) {
- fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
- exit(1);
- }
+ ptr = buffer;
+ ptr_size = size;
+
+ for (i=0;i<MAX_CERTS;i++) {
+ ret = gnutls_x509_crt_init(&crt[i]);
+ if (ret < 0) {
+ fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
- dat.data = buffer;
- dat.size = size;
+ dat.data = ptr;
+ dat.size = ptr_size;
- ret = gnutls_x509_crt_import( crt, &dat, in_cert_format);
- if (ret < 0) {
- fprintf(stderr, "crt_import: %s\n", gnutls_strerror(ret));
- exit(1);
- }
+ ret = gnutls_x509_crt_import( crt[i], &dat, in_cert_format);
+ if (ret < 0 && *crt_size > 0) break;
+ if (ret < 0) {
+ fprintf(stderr, "crt_import: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ptr = strstr( ptr, "---END");
+ if (ptr==NULL) break;
+ ptr++;
+
+ ptr_size = size;
+ ptr_size -= ((void*)ptr - (void*)buffer);
+
+ (*crt_size)++;
+ }
+ fprintf(stderr, "Loaded %d certificates.\n", *crt_size);
return crt;
}
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 67176fe6ff..5418c66f8c 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -19,6 +19,8 @@ option (s, generate-self-signed) { $action=0; } "Generate a self-signed certific
option (c, generate-certificate) { $action=4; } "Generate a signed certificate."
+option (generate-crl) { $action=13; } "Generate a CRL."
+
option (u, update-certificate) { $action=7; } "Update a signed certificate."
option (p, generate-privkey) { $action=1; } "Generate a private key."