diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 21:11:14 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 21:11:14 +0000 |
commit | 343dd84d42732342e0eb961e82ec2c900d08fbee (patch) | |
tree | 6b73864ac154e960241b0e2cc5a3ef077bc396da | |
parent | 219136f6e6317bb955ecf50ee4c6a10c691e0693 (diff) | |
download | gnutls-343dd84d42732342e0eb961e82ec2c900d08fbee.tar.gz |
Several improvments in the certtool.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | lib/pkix.asn | 2 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 2 | ||||
-rw-r--r-- | lib/x509/common.c | 9 | ||||
-rw-r--r-- | lib/x509/crq.c | 29 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 1 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/certtool-gaa.c | 117 | ||||
-rw-r--r-- | src/certtool-gaa.h | 10 | ||||
-rw-r--r-- | src/certtool.c | 320 | ||||
-rw-r--r-- | src/certtool.gaa | 16 |
11 files changed, 477 insertions, 37 deletions
@@ -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; } |