diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-12-26 14:18:26 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-12-26 14:18:26 +0000 |
commit | 95f9e0fd4a4acc9a7552e4efc0dc04627936305a (patch) | |
tree | d1ed8e1e4d785de66d9a4e0a9b145c60f9d4c1ed | |
parent | 647c0a87ec285f1426e512de977c7e1a94c189d6 (diff) | |
download | gnutls-95f9e0fd4a4acc9a7552e4efc0dc04627936305a.tar.gz |
Added support for generating CRLs in the library and the
certtool utility.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | doc/TODO | 3 | ||||
-rw-r--r-- | doc/tex/certificate.tex | 8 | ||||
-rw-r--r-- | includes/gnutls/x509.h | 13 | ||||
-rw-r--r-- | lib/Makefile.am | 3 | ||||
-rw-r--r-- | lib/x509/Makefile.am | 2 | ||||
-rw-r--r-- | lib/x509/crl.c | 2 | ||||
-rw-r--r-- | lib/x509/sign.c | 115 | ||||
-rw-r--r-- | lib/x509/sign.h | 2 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 89 | ||||
-rw-r--r-- | src/certtool-gaa.c | 107 | ||||
-rw-r--r-- | src/certtool-gaa.h | 30 | ||||
-rw-r--r-- | src/certtool.c | 246 | ||||
-rw-r--r-- | src/certtool.gaa | 2 |
14 files changed, 418 insertions, 206 deletions
@@ -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) @@ -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." |