summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-25 21:11:14 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-10-25 21:11:14 +0000
commit343dd84d42732342e0eb961e82ec2c900d08fbee (patch)
tree6b73864ac154e960241b0e2cc5a3ef077bc396da
parent219136f6e6317bb955ecf50ee4c6a10c691e0693 (diff)
downloadgnutls-343dd84d42732342e0eb961e82ec2c900d08fbee.tar.gz
Several improvments in the certtool.
-rw-r--r--NEWS3
-rw-r--r--lib/pkix.asn2
-rw-r--r--lib/pkix_asn1_tab.c2
-rw-r--r--lib/x509/common.c9
-rw-r--r--lib/x509/crq.c29
-rw-r--r--lib/x509/privkey_pkcs8.c1
-rw-r--r--src/Makefile.am5
-rw-r--r--src/certtool-gaa.c117
-rw-r--r--src/certtool-gaa.h10
-rw-r--r--src/certtool.c320
-rw-r--r--src/certtool.gaa16
11 files changed, 477 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 38810e67f9..55826a7a45 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
-Version 0.9.92
+Version 0.9.92 (25/10/2003)
- The RFC2818 hostname verification is now case insensitive.
- Added support for generating X.509 certificates.
+- Added the certtool, a tool for generating X.509 certificates
Version 0.9.91 (17/10/2003)
- Fixed a compilation issue in the openpgp authentication part.
diff --git a/lib/pkix.asn b/lib/pkix.asn
index aa9ac0ec1e..01b1e7e940 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -1022,7 +1022,7 @@ pkcs-9-ub-challengePassword INTEGER ::= 255
pkcs-9-certTypes OBJECT IDENTIFIER ::= {pkcs-9 22}
pkcs-9-crlTypes OBJECT IDENTIFIER ::= {pkcs-9 23}
-pkcs-9-challengePassword AttributeType ::= {pkcs-9 7}
+pkcs-9-at-challengePassword OBJECT IDENTIFIER ::= {pkcs-9 7}
pkcs-9-challengePassword ::= CHOICE {
printableString PrintableString (SIZE (1..pkcs-9-ub-challengePassword)),
diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c
index 9922313d05..26d8ef9942 100644
--- a/lib/pkix_asn1_tab.c
+++ b/lib/pkix_asn1_tab.c
@@ -920,7 +920,7 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[]={
{"pkcs-9-crlTypes",1879048204,0},
{0,1073741825,"pkcs-9"},
{0,1,"23"},
- {"pkcs-9-challengePassword",1880096780,"AttributeType"},
+ {"pkcs-9-at-challengePassword",1879048204,0},
{0,1073741825,"pkcs-9"},
{0,1,"7"},
{"pkcs-9-challengePassword",1610612754,0},
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 01d3048187..35978e574c 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -591,9 +591,10 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
if (tmp_buf_size == 0) tmp_buf_size = 16*1024;
if (format == GNUTLS_X509_FMT_DER) {
- len = *output_data_size;
if (output_data == NULL) *output_data_size = 0;
+
+ len = *output_data_size;
if ((result=asn1_der_coding( asn1_data, "", output_data, &len, NULL)) != ASN1_SUCCESS)
{
@@ -618,8 +619,10 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
return GNUTLS_E_MEMORY_ERROR;
}
- if ((result=asn1_der_coding( asn1_data, "", tmp, &len, NULL)) != ASN1_SUCCESS) {
+{char err[1024];
+ if ((result=asn1_der_coding( asn1_data, "", tmp, &len, err)) != ASN1_SUCCESS) {
gnutls_assert();
+fprintf(stderr, "re: %s\n", err);
if (result == ASN1_MEM_ERROR) {
_gnutls_x509_log("Length required for der coding: %d\n", len);
*output_data_size = B64FSIZE(strlen(pem_header),len);
@@ -627,7 +630,7 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
gnutls_afree(tmp);
return _gnutls_asn2err(result);
}
-
+}
result = _gnutls_fbase64_encode( pem_header,
tmp, len, &out);
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index d1d805101d..80c20b02a1 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -500,13 +500,14 @@ int gnutls_x509_crq_sign(gnutls_x509_crq crq, gnutls_x509_privkey key)
{
int result;
gnutls_datum signature;
+const char* pk;
if (key->pk_algorithm != GNUTLS_PK_RSA) {
gnutls_assert();
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
- /* Step 3. Self sign the request.
+ /* Step 1. Self sign the request.
*/
result = _gnutls_x509_sign_tbs( crq->crq, "certificationRequestInfo", GNUTLS_MAC_SHA,
key, &signature);
@@ -516,7 +517,7 @@ gnutls_datum signature;
return result;
}
- /* write the signature (bits)
+ /* Step 2. write the signature (bits)
*/
result = asn1_write_value( crq->crq, "signature", signature.data, signature.size*8);
@@ -527,6 +528,30 @@ gnutls_datum signature;
return _gnutls_asn2err(result);
}
+ /* Step 3. Write the signatureAlgorithm field.
+ */
+ pk = _gnutls_x509_sign2oid( key->pk_algorithm, GNUTLS_MAC_SHA);
+ if (pk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* write the RSA OID
+ */
+ result = asn1_write_value( crq->crq, "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( crq->crq, "signatureAlgorithm.parameters", NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
return 0;
}
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 0d373cc1f8..d4e1c5ca76 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -179,6 +179,7 @@ static int encode_to_private_key_info(gnutls_x509_privkey pkey,
/* Write the raw private key
*/
+ size = 0;
result =
gnutls_x509_privkey_export(pkey, GNUTLS_X509_FMT_DER, NULL,
&size);
diff --git a/src/Makefile.am b/src/Makefile.am
index 7be501984f..466de9b4ad 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,8 +14,6 @@ gnutls_cli_SOURCES = cli-gaa.c cli.c common.c
gnutls_cli_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS)
gnutls_cli_debug_SOURCES = tls_test-gaa.c tls_test.c tests.c common.c
gnutls_cli_debug_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS)
-certtool_SOURCES = certtool-gaa.c certtool.c
-certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS)
noinst_PROGRAMS = prime retcodes
@@ -24,6 +22,9 @@ prime_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS)
retcodes_SOURCES = retcodes.c
retcodes_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS)
+certtool_SOURCES = certtool-gaa.c certtool.c
+certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS)
+
crypt-gaa.c: crypt.gaa
-gaa crypt.gaa -o crypt-gaa.c -i crypt-gaa.h
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index c08a70accb..4a1e8e64ad 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -118,7 +118,12 @@ 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('p', "generate-privkey", "", "Generate a private key.");
+ __gaa_helpsingle('q', "generate-request", "", "Generate a PKCS #10 certificate request.");
+ __gaa_helpsingle(0, "load-privkey", "FILE ", "Private key file to use.");
+ __gaa_helpsingle(0, "load-ca-privkey", "FILE ", "Certificate authority's private key file to use.");
+ __gaa_helpsingle(0, "load-ca-cert", "FILE ", "Certificate authority's certificate file to use.");
__gaa_helpsingle('i', "cert-info", "", "Print information on a certificate.");
__gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys.");
__gaa_helpsingle(0, "bits", "BITS ", "specify the number of bits for key generation.");
@@ -138,10 +143,16 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 13 "certtool.gaa"
+#line 27 "certtool.gaa"
int bits;
-#line 10 "certtool.gaa"
+#line 24 "certtool.gaa"
int pkcs8;
+#line 18 "certtool.gaa"
+ char *ca;
+#line 15 "certtool.gaa"
+ char *ca_privkey;
+#line 12 "certtool.gaa"
+ char *privkey;
#line 3 "certtool.gaa"
int action;
@@ -198,14 +209,19 @@ int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 7
+#define GAA_NB_OPTION 12
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_bits 3
#define GAAOPTID_pkcs8 4
#define GAAOPTID_cert_info 5
-#define GAAOPTID_generate_privkey 6
-#define GAAOPTID_generate_self_signed 7
+#define GAAOPTID_load_ca_cert 6
+#define GAAOPTID_load_ca_privkey 7
+#define GAAOPTID_load_privkey 8
+#define GAAOPTID_generate_request 9
+#define GAAOPTID_generate_privkey 10
+#define GAAOPTID_generate_certificate 11
+#define GAAOPTID_generate_self_signed 12
#line 168 "gaa.skel"
@@ -397,6 +413,24 @@ struct GAAOPTION_bits
int arg1;
int size1;
};
+
+struct GAAOPTION_load_ca_cert
+{
+ char* arg1;
+ int size1;
+};
+
+struct GAAOPTION_load_ca_privkey
+{
+ char* arg1;
+ int size1;
+};
+
+struct GAAOPTION_load_privkey
+{
+ char* arg1;
+ int size1;
+};
#line 349 "gaa.skel"
int gaa_is_an_argument(char *str)
@@ -428,13 +462,18 @@ int gaa_get_option_num(char *str, int status)
{
case GAA_LETTER_OPTION:
GAA_CHECK1STR("", GAAOPTID_bits);
+ GAA_CHECK1STR("", GAAOPTID_load_ca_cert);
+ GAA_CHECK1STR("", GAAOPTID_load_ca_privkey);
+ GAA_CHECK1STR("", GAAOPTID_load_privkey);
case GAA_MULTIPLE_OPTION:
#line 375 "gaa.skel"
GAA_CHECK1STR("v", GAAOPTID_version);
GAA_CHECK1STR("h", GAAOPTID_help);
GAA_CHECK1STR("8", GAAOPTID_pkcs8);
GAA_CHECK1STR("i", GAAOPTID_cert_info);
+ GAA_CHECK1STR("q", GAAOPTID_generate_request);
GAA_CHECK1STR("p", GAAOPTID_generate_privkey);
+ GAA_CHECK1STR("c", GAAOPTID_generate_certificate);
GAA_CHECK1STR("s", GAAOPTID_generate_self_signed);
#line 277 "gaa.skel"
@@ -445,7 +484,12 @@ int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("bits", GAAOPTID_bits);
GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8);
GAA_CHECKSTR("cert-info", GAAOPTID_cert_info);
+ GAA_CHECKSTR("load-ca-cert", GAAOPTID_load_ca_cert);
+ GAA_CHECKSTR("load-ca-privkey", GAAOPTID_load_ca_privkey);
+ GAA_CHECKSTR("load-privkey", GAAOPTID_load_privkey);
+ GAA_CHECKSTR("generate-request", GAAOPTID_generate_request);
GAA_CHECKSTR("generate-privkey", GAAOPTID_generate_privkey);
+ GAA_CHECKSTR("generate-certificate", GAAOPTID_generate_certificate);
GAA_CHECKSTR("generate-self-signed", GAAOPTID_generate_self_signed);
#line 281 "gaa.skel"
@@ -460,6 +504,9 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
int OK = 0;
int gaa_last_non_option;
struct GAAOPTION_bits GAATMP_bits;
+ struct GAAOPTION_load_ca_cert GAATMP_load_ca_cert;
+ struct GAAOPTION_load_ca_privkey GAATMP_load_ca_privkey;
+ struct GAAOPTION_load_privkey GAATMP_load_privkey;
#line 393 "gaa.skel"
#ifdef GAA_REST_EXISTS
@@ -482,14 +529,14 @@ int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_version:
OK = 0;
-#line 18 "certtool.gaa"
+#line 32 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 16 "certtool.gaa"
+#line 30 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
@@ -499,32 +546,76 @@ 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 14 "certtool.gaa"
+#line 28 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 11 "certtool.gaa"
+#line 25 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
return GAA_OK;
break;
case GAAOPTID_cert_info:
OK = 0;
-#line 8 "certtool.gaa"
+#line 21 "certtool.gaa"
{ gaaval->action = 2; ;};
return GAA_OK;
break;
+ case GAAOPTID_load_ca_cert:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_load_ca_cert.arg1, gaa_getstr, GAATMP_load_ca_cert.size1);
+ gaa_index++;
+#line 19 "certtool.gaa"
+{ gaaval->ca = GAATMP_load_ca_cert.arg1 ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_load_ca_privkey:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, GAATMP_load_ca_privkey.size1);
+ gaa_index++;
+#line 16 "certtool.gaa"
+{ gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_load_privkey:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, GAATMP_load_privkey.size1);
+ gaa_index++;
+#line 13 "certtool.gaa"
+{ gaaval->privkey = GAATMP_load_privkey.arg1 ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_generate_request:
+ OK = 0;
+#line 10 "certtool.gaa"
+{ gaaval->action=3; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_generate_privkey:
OK = 0;
-#line 6 "certtool.gaa"
+#line 8 "certtool.gaa"
{ gaaval->action=1; ;};
return GAA_OK;
break;
+ case GAAOPTID_generate_certificate:
+ OK = 0;
+#line 6 "certtool.gaa"
+{ gaaval->action=4; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_generate_self_signed:
OK = 0;
#line 4 "certtool.gaa"
@@ -556,8 +647,8 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 20 "certtool.gaa"
-{ gaaval->bits = 1024; gaaval->pkcs8 = 0;;};
+#line 34 "certtool.gaa"
+{ gaaval->bits = 1024; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL; ;};
}
inited = 1;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index e4aba13d70..c086d6aea7 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,10 +8,16 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 13 "certtool.gaa"
+#line 27 "certtool.gaa"
int bits;
-#line 10 "certtool.gaa"
+#line 24 "certtool.gaa"
int pkcs8;
+#line 18 "certtool.gaa"
+ char *ca;
+#line 15 "certtool.gaa"
+ char *ca_privkey;
+#line 12 "certtool.gaa"
+ char *privkey;
#line 3 "certtool.gaa"
int action;
diff --git a/src/certtool.c b/src/certtool.c
index b38b3063af..fe6b7e8e1c 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -6,9 +6,14 @@
#include <time.h>
#include "certtool-gaa.h"
+gnutls_x509_privkey load_private_key(void);
+gnutls_x509_privkey load_ca_private_key(void);
+gnutls_x509_crt load_ca_cert(void);
void certificate_info( void);
static void gaa_parser(int argc, char **argv);
void generate_self_signed( void);
+void generate_request(void);
+
static gaainfo info;
static unsigned char buffer[10*1024];
@@ -32,7 +37,7 @@ int main(int argc, char** argv)
-static void read_set( gnutls_x509_crt crt, const char* input_str, const char* oid)
+static void read_crt_set( gnutls_x509_crt crt, const char* input_str, const char* oid)
{
char input[128];
int ret;
@@ -49,6 +54,23 @@ int ret;
}
}
+static void read_crq_set( gnutls_x509_crq crq, const char* input_str, const char* oid)
+{
+char input[128];
+int ret;
+
+ fputs( input_str, stderr);
+ fgets( input, sizeof(input), stdin);
+
+ if (strlen(input)==1) /* only newline */ return;
+
+ ret = gnutls_x509_crq_set_dn_by_oid(crq, oid, input, strlen(input)-1);
+ if (ret < 0) {
+ fprintf(stderr, "set_dn: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+}
+
static int read_int( const char* input_str)
{
char input[128];
@@ -94,6 +116,9 @@ static gnutls_x509_privkey generate_private_key_int( void)
gnutls_x509_privkey key;
int ret;
+ if (info.privkey)
+ return load_private_key();
+
ret = gnutls_x509_privkey_init(&key);
if (ret < 0) {
fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
@@ -138,6 +163,8 @@ void generate_private_key( void)
{
gnutls_x509_privkey key;
+ fprintf(stderr, "Generating a private key...\n");
+
key = generate_private_key_int();
print_private_key( key);
@@ -146,7 +173,7 @@ gnutls_x509_privkey key;
}
-void generate_self_signed( void)
+gnutls_x509_crt generate_certificate( gnutls_x509_privkey *ret_key)
{
gnutls_x509_crt crt;
gnutls_x509_privkey key;
@@ -165,15 +192,15 @@ void generate_self_signed( void)
fprintf(stderr, "Please enter the details of the certificate's distinguished name. "
"Just press enter to ignore a field.\n");
- read_set( crt, "Country name (2 chars): ", GNUTLS_OID_X520_COUNTRY_NAME);
- read_set( crt, "Organization name: ", GNUTLS_OID_X520_ORGANIZATION_NAME);
- read_set( crt, "Organizational unit name: ", GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME);
- read_set( crt, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME);
- read_set( crt, "State or province name: ", GNUTLS_OID_X520_LOCALITY_NAME);
- read_set( crt, "Common name: ", GNUTLS_OID_X520_COMMON_NAME);
+ read_crt_set( crt, "Country name (2 chars): ", GNUTLS_OID_X520_COUNTRY_NAME);
+ read_crt_set( crt, "Organization name: ", GNUTLS_OID_X520_ORGANIZATION_NAME);
+ read_crt_set( crt, "Organizational unit name: ", GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME);
+ read_crt_set( crt, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME);
+ read_crt_set( crt, "State or province name: ", GNUTLS_OID_X520_LOCALITY_NAME);
+ read_crt_set( crt, "Common name: ", GNUTLS_OID_X520_COMMON_NAME);
fprintf(stderr, "This field should not be used in new certificates.\n");
- read_set( crt, "E-mail: ", GNUTLS_OID_PKCS9_EMAIL);
+ read_crt_set( crt, "E-mail: ", GNUTLS_OID_PKCS9_EMAIL);
size = gnutls_x509_crt_set_version( crt, 2);
if (size < 0) {
@@ -192,7 +219,6 @@ void generate_self_signed( void)
exit(1);
}
-
size = gnutls_x509_crt_set_key( crt, key);
if (size < 0) {
fprintf(stderr, "set_key: %s\n", gnutls_strerror(size));
@@ -246,6 +272,22 @@ void generate_self_signed( void)
}
}
+ *ret_key = key;
+ return crt;
+
+}
+
+void generate_self_signed( void)
+{
+ gnutls_x509_crt crt;
+ gnutls_x509_privkey key;
+ int size;
+ int result;
+
+ fprintf(stderr, "Generating a self signed certificate...\n");
+
+ crt = generate_certificate( &key);
+
fprintf(stderr, "\n\nSigning certificate...\n");
result = gnutls_x509_crt_sign( crt, crt, key);
@@ -256,7 +298,6 @@ void generate_self_signed( void)
print_private_key( key);
-
size = sizeof(buffer);
result = gnutls_x509_crt_export( crt, GNUTLS_X509_FMT_PEM, buffer, &size);
if (result < 0) {
@@ -272,6 +313,45 @@ void generate_self_signed( void)
}
+void generate_signed_certificate( void)
+{
+ gnutls_x509_crt crt;
+ gnutls_x509_privkey key;
+ int size, result;
+ gnutls_x509_privkey ca_key;
+ gnutls_x509_crt ca_crt;
+
+ fprintf(stderr, "Generating a signed certificate...\n");
+
+ ca_key = load_ca_private_key();
+ ca_crt = load_ca_cert();
+
+ crt = generate_certificate( &key);
+
+ fprintf(stderr, "\n\nSigning certificate...\n");
+
+ result = gnutls_x509_crt_sign( crt, ca_crt, ca_key);
+ if (result < 0) {
+ fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ print_private_key( key);
+
+ size = sizeof(buffer);
+ result = gnutls_x509_crt_export( crt, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (result < 0) {
+ fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result));
+ exit(1);
+ }
+
+ printf("Certificate: \n%s", buffer);
+
+ gnutls_x509_crt_deinit(crt);
+ gnutls_x509_privkey_deinit(key);
+
+}
+
void gaa_parser(int argc, char **argv)
{
if (gaa(argc, argv, &info) != -1) {
@@ -290,6 +370,12 @@ void gaa_parser(int argc, char **argv)
case 2:
certificate_info();
return;
+ case 3:
+ generate_request();
+ return;
+ case 4:
+ generate_signed_certificate();
+ return;
}
}
@@ -398,3 +484,215 @@ void certificate_info( void)
}
}
+
+gnutls_x509_privkey load_private_key()
+{
+FILE* fd;
+gnutls_x509_privkey key;
+int ret;
+gnutls_datum dat;
+size_t size;
+
+ fd = fopen(info.privkey, "r");
+ if (fd == NULL) {
+ fprintf(stderr, "File %s does not exist.\n", info.privkey);
+ exit(1);
+ }
+
+ size = fread(buffer, 1, sizeof(buffer)-1, fd);
+ buffer[size] = 0;
+
+ fclose(fd);
+
+ ret = gnutls_x509_privkey_init(&key);
+ if (ret < 0) {
+ fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ dat.data = buffer;
+ dat.size = size;
+
+ if (!info.pkcs8)
+ ret = gnutls_x509_privkey_import( key, &dat, GNUTLS_X509_FMT_PEM);
+ else
+ ret = gnutls_x509_privkey_import_pkcs8( key, &dat, GNUTLS_X509_FMT_PEM,
+ NULL, 0);
+
+ if (ret < 0) {
+ fprintf(stderr, "privkey_import: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ return key;
+}
+
+gnutls_x509_privkey load_ca_private_key()
+{
+FILE* fd;
+gnutls_x509_privkey key;
+int ret;
+gnutls_datum dat;
+size_t size;
+
+ fprintf(stderr, "Loading CA's private key...\n");
+
+ if (info.ca_privkey==NULL) {
+ fprintf(stderr, "You must specify a private key of the CA.\n");
+ exit(1);
+ }
+
+ fd = fopen(info.ca_privkey, "r");
+ if (fd == NULL) {
+ fprintf(stderr, "File %s does not exist.\n", info.ca_privkey);
+ exit(1);
+ }
+
+ size = fread(buffer, 1, sizeof(buffer)-1, fd);
+ buffer[size] = 0;
+
+ fclose(fd);
+
+ ret = gnutls_x509_privkey_init(&key);
+ if (ret < 0) {
+ fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ dat.data = buffer;
+ dat.size = size;
+
+ if (!info.pkcs8)
+ ret = gnutls_x509_privkey_import( key, &dat, GNUTLS_X509_FMT_PEM);
+ else
+ ret = gnutls_x509_privkey_import_pkcs8( key, &dat, GNUTLS_X509_FMT_PEM,
+ NULL, 0);
+
+ if (ret < 0) {
+ fprintf(stderr, "privkey_import: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ return key;
+}
+
+/* Loads the CA's certificate
+ */
+gnutls_x509_crt load_ca_cert()
+{
+FILE* fd;
+gnutls_x509_crt crt;
+int ret;
+gnutls_datum dat;
+size_t size;
+
+ fprintf(stderr, "Loading CA's certificate...\n");
+
+ if (info.ca==NULL) {
+ fprintf(stderr, "You must specify a certificate of the CA.\n");
+ exit(1);
+ }
+
+ fd = fopen(info.ca, "r");
+ if (fd == NULL) {
+ fprintf(stderr, "File %s does not exist.\n", info.ca);
+ exit(1);
+ }
+
+ size = fread(buffer, 1, sizeof(buffer)-1, fd);
+ buffer[size] = 0;
+
+ fclose(fd);
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ dat.data = buffer;
+ dat.size = size;
+
+ ret = gnutls_x509_crt_import( crt, &dat, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "crt_import: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ return crt;
+}
+
+
+/* Generate a PKCS #10 certificate request.
+ */
+void generate_request(void)
+{
+ gnutls_x509_crq crq;
+ gnutls_x509_privkey key;
+ int ret;
+ const char* pass;
+ size_t size;
+
+ fprintf(stderr, "Generating a PKCS #10 certificate request...\n");
+
+ ret = gnutls_x509_crq_init(&crq);
+ if (ret < 0) {
+ fprintf(stderr, "crq_init: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* Load the private key.
+ */
+ key = generate_private_key_int();
+
+ read_crq_set( crq, "Country name (2 chars): ", GNUTLS_OID_X520_COUNTRY_NAME);
+ read_crq_set( crq, "Organization name: ", GNUTLS_OID_X520_ORGANIZATION_NAME);
+ read_crq_set( crq, "Organizational unit name: ", GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME);
+ read_crq_set( crq, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME);
+ read_crq_set( crq, "State or province name: ", GNUTLS_OID_X520_LOCALITY_NAME);
+ read_crq_set( crq, "Common name: ", GNUTLS_OID_X520_COMMON_NAME);
+
+ ret = gnutls_x509_crq_set_version( crq, 0);
+ if (ret < 0) {
+ fprintf(stderr, "set_version: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ pass = read_str("Enter a challenge password: ");
+
+ if (pass != NULL) {
+ ret = gnutls_x509_crq_set_challenge_password( crq, pass);
+ if (ret < 0) {
+ fprintf(stderr, "set_pass: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+
+ ret = gnutls_x509_crq_set_key( crq, key);
+ if (ret < 0) {
+ fprintf(stderr, "set_key: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crq_sign( crq, key);
+ if (ret < 0) {
+ fprintf(stderr, "sign: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+
+ print_private_key( key);
+
+ size = sizeof(buffer);
+ ret = gnutls_x509_crq_export( crq, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "export: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ printf("Request: \n%s", buffer);
+
+ gnutls_x509_crq_deinit(crq);
+ gnutls_x509_privkey_deinit(key);
+
+}
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 1e7ba7651f..e9fe21580e 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -3,10 +3,24 @@ helpnode "Certtool help\nUsage : certtool [options]"
#int action;
option (s, generate-self-signed) { $action=0; } "Generate a self-signed certificate."
+option (c, generate-certificate) { $action=4; } "Generate a signed certificate."
+
option (p, generate-privkey) { $action=1; } "Generate a private key."
+option (q, generate-request) { $action=3; } "Generate a PKCS #10 certificate request."
+
+#char *privkey;
+option (load-privkey) STR "FILE" { $privkey = $1 } "Private key file to use."
+
+#char *ca_privkey;
+option (load-ca-privkey) STR "FILE" { $ca_privkey = $1 } "Certificate authority's private key file to use."
+
+#char *ca;
+option (load-ca-cert) STR "FILE" { $ca = $1 } "Certificate authority's certificate file to use."
+
option (i, cert-info) { $action = 2; } "Print information on a certificate."
+
#int pkcs8;
option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys."
@@ -17,5 +31,5 @@ option (h, help) { gaa_help(); exit(0); } "shows this help text"
option (v, version) { certtool_version(); exit(0); } "shows the program version"
-init { $bits = 1024; $pkcs8 = 0;}
+init { $bits = 1024; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = NULL; }