diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-03-26 09:16:41 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-03-26 09:16:41 +0000 |
commit | afa9584ac75c439ce8c2722de48b0fb2ad943adb (patch) | |
tree | 54e84a478344874c3455b1733281319da927b20a | |
parent | 90e5b542084f0af2b7242824e82fe32635dddc45 (diff) | |
download | gnutls-afa9584ac75c439ce8c2722de48b0fb2ad943adb.tar.gz |
added gnutls_x509_extract_certificate_pk_algorithm()
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/TODO | 2 | ||||
-rw-r--r-- | lib/gnutls.h.in.in | 3 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 1 | ||||
-rw-r--r-- | lib/gnutls_errors_int.h | 1 | ||||
-rw-r--r-- | lib/gnutls_pk.h | 4 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 1 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 196 | ||||
-rw-r--r-- | src/common.c | 18 | ||||
-rwxr-xr-x | src/gnutls-http-serv | 2 | ||||
-rw-r--r-- | src/serv.c | 4 |
11 files changed, 201 insertions, 34 deletions
@@ -1,5 +1,6 @@ -Version 0.4.0 +Version 0.3.93 - Added support for RFC2630 (PKCS7) X.509 certificate sets +- Added new function: gnutls_x509_extract_certificate_pk_algorithm() Version 0.3.92 (23/03/2002) - Updated documentation @@ -5,6 +5,8 @@ in order to avoid having people working on the same thing. Current list: + Audit the code * Precalculate signatures for DHE cipher suites +* Precalculate the cipher suites to use (should increase the handshake + speed about 8%) * Minimize footprint. * Improve support for compression - Add Kerberos support diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in index 0eb30fe1f2..9a7020fe87 100644 --- a/lib/gnutls.h.in.in +++ b/lib/gnutls.h.in.in @@ -79,6 +79,9 @@ typedef enum GNUTLS_CertificateType { GNUTLS_CRT_X509=1, GNUTLS_CRT_OPENPGP typedef enum GNUTLS_X509_CertificateFmt { GNUTLS_X509_FMT_DER, GNUTLS_X509_FMT_PEM } GNUTLS_X509_CertificateFmt; +typedef enum GNUTLS_PKAlgorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA +} GNUTLS_PKAlgorithm; + /* If you want to change this, then also change the * define in gnutls_int.h, and recompile. */ diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 0701bd9fe9..20c0ff4914 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -43,6 +43,7 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER_SUITE, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_CERTIFICATE_KEY_MISMATCH, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_PK_ALGORITHM, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_MAC_ALGORITHM, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_ERROR, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER_TYPE, 1), diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h index 35d904ae0e..1bbcbb3d6d 100644 --- a/lib/gnutls_errors_int.h +++ b/lib/gnutls_errors_int.h @@ -77,6 +77,7 @@ #define GNUTLS_E_ASN1_DER_OVERFLOW -77 #define GNUTLS_E_TOO_MANY_EMPTY_PACKETS -78 #define GNUTLS_E_OPENPGP_UID_REVOKED -79 +#define GNUTLS_E_UNKNOWN_PK_ALGORITHM -80 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -250 diff --git a/lib/gnutls_pk.h b/lib/gnutls_pk.h index 125e6dbb45..c53b461f2d 100644 --- a/lib/gnutls_pk.h +++ b/lib/gnutls_pk.h @@ -2,9 +2,11 @@ # define GNUTLS_PK_H typedef enum PKAlgorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA, /* sign only */ - GNUTLS_PK_DH, GNUTLS_PK_UNKNOWN + GNUTLS_PK_UNKNOWN } PKAlgorithm; +#define GNUTLS_PKAlgorithm PKAlgorithm + int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI * pkey); int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, MPI * params, int btype); diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index a20dc122ef..ab9ceae148 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -89,6 +89,7 @@ time_t gnutls_x509_extract_certificate_activation_time( const gnutls_datum*); time_t gnutls_x509_extract_certificate_expiration_time( const gnutls_datum*); int gnutls_x509_extract_subject_alt_name( const gnutls_datum*, int seq, char*, int*); int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size); +int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int* bits); int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list_length, const gnutls_datum * CA_list, int CA_list_length, const gnutls_datum* CRL_list, int CRL_list_length); diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 73f7e89709..80212d9344 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -1018,7 +1018,7 @@ static int parse_pkcs7_cert_mem( gnutls_cert** cert_list, int* ncerts, /* tmp now contains the decoded certificate list */ tmp.data = (void*)input_cert; tmp.size = input_cert_size; - +#warning FIX THIS. Make it read the certificate the reverse order j = 0; do { pcert_size = sizeof(pcert); @@ -1697,6 +1697,8 @@ static int _read_dsa_pubkey(opaque * der, int dersize, MPI * params) } +#define PKIX1_RSA_OID "1 2 840 113549 1 1 1" +#define DSA_OID "1 2 840 10040 4 1" /* Extracts DSA and RSA parameters from a certificate. */ @@ -1704,24 +1706,24 @@ static int _gnutls_extract_x509_cert_mpi_params( const char* ALGO_OID, gnutls_cert * gCert, node_asn* c2, char* tmpstr, int tmpstr_size) { int len, result; + + len = tmpstr_size - 1; + result = + asn1_read_value + (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", + tmpstr, &len); + + if (result != ASN_OK) { + gnutls_assert(); + return result; + } - if (strcmp( ALGO_OID, "1 2 840 113549 1 1 1") == 0) { /* pkix-1 1 - RSA */ + if (strcmp( ALGO_OID, PKIX1_RSA_OID) == 0) { /* pkix-1 1 - RSA */ /* params[0] is the modulus, * params[1] is the exponent */ gCert->subject_pk_algorithm = GNUTLS_PK_RSA; - len = tmpstr_size - 1; - result = - asn1_read_value - (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", - tmpstr, &len); - - if (result != ASN_OK) { - gnutls_assert(); - return result; - } - if ((sizeof(gCert->params) / sizeof(MPI)) < RSA_PARAMS) { gnutls_assert(); /* internal error. Increase the MPIs in params */ @@ -1738,7 +1740,7 @@ int len, result; return 0; } - if (strcmp( ALGO_OID, "1 2 840 10040 4 1") == 0) { /* pkix-1 1 - DSA */ + if (strcmp( ALGO_OID, DSA_OID) == 0) { /* params[0] is p, * params[1] is q, * params[2] is q, @@ -1746,17 +1748,6 @@ int len, result; */ gCert->subject_pk_algorithm = GNUTLS_PK_DSA; - len = tmpstr_size - 1; - result = - asn1_read_value - (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", - tmpstr, &len); - - if (result != ASN_OK) { - gnutls_assert(); - return result; - } - if ((sizeof(gCert->params) / sizeof(MPI)) < DSA_PUBLIC_PARAMS) { gnutls_assert(); /* internal error. Increase the MPIs in params */ @@ -1793,7 +1784,6 @@ int len, result; } - /* other types like DH * currently not supported */ @@ -1820,6 +1810,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert) int result; node_asn *c2; opaque str[MAX_X509_CERT_SIZE]; + char oid[128]; int len = sizeof(str); memset(gCert, 0, sizeof(gnutls_cert)); @@ -1853,12 +1844,12 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert) return result; } - len = sizeof(str) - 1; + len = sizeof(oid) - 1; result = asn1_read_value (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", - str, &len); + oid, &len); if (result != ASN_OK) { gnutls_assert(); @@ -1867,7 +1858,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert) return result; } - if ( (result=_gnutls_extract_x509_cert_mpi_params( str, gCert, c2, str, sizeof(str))) < 0) { + if ( (result=_gnutls_extract_x509_cert_mpi_params( oid, gCert, c2, str, sizeof(str))) < 0) { gnutls_assert(); asn1_delete_structure(c2); gnutls_free_datum( &gCert->raw); @@ -2240,3 +2231,150 @@ int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int return 0; } + + +/** + * gnutls_x509_extract_certificate_pk_algorithm - This function returns the certificate's PublicKey algorithm + * @cert: is a DER encoded X.509 certificate + * @bits: if bits is non-null it will have enough space to hold the + * parameters size in bits. + * + * This function will return the public key algorithm of an X.509 + * certificate. + * + * If bits is non null, it should have enough size to hold the parameters + * size in bits. For RSA the bits returned is the modulus and the public + * exponent (in this order). For DSA the bits returned are of p, q, g, + * and the public exponent in this order. + * + * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, + * or a negative value on error. + * + **/ +int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int* bits) +{ + int result; + node_asn *c2; + opaque str[MAX_X509_CERT_SIZE]; + int algo; + int len = sizeof(str); + MPI params[MAX_PARAMS_SIZE]; + + if ((result=asn1_create_structure + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, + "certificate2")) + != ASN_OK) { + gnutls_assert(); + return result; + } + + result = asn1_get_der(c2, cert->data, cert->size); + if (result != ASN_OK) { + /* couldn't decode DER */ + + _gnutls_log("CERT: Decoding error %d\n", result); + + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + len = sizeof(str) - 1; + result = + asn1_read_value + (c2, + "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", + str, &len); + + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; + + if ( strcmp( str, PKIX1_RSA_OID)==0) + algo = GNUTLS_PK_RSA; + + if ( strcmp( str, DSA_OID)==0) + algo = GNUTLS_PK_DSA; + + if ( bits==NULL) { + asn1_delete_structure(c2); + return algo; + } + + /* Now read the parameters' bits */ + + len = sizeof(str) - 1; + result = + asn1_read_value + (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", + str, &len); + + if (result != ASN_OK) { + gnutls_assert(); + return result; + } + + + if (algo==GNUTLS_PK_RSA) { + if ((result=_read_rsa_params( str, len/8, params)) < 0) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + bits[0] = gcry_mpi_get_nbits( params[0]); + bits[1] = gcry_mpi_get_nbits( params[1]); + + _gnutls_mpi_release( ¶ms[0]); + _gnutls_mpi_release( ¶ms[1]); + } + + if (algo==GNUTLS_PK_DSA) { + + if ((result = + _read_dsa_pubkey(str, len / 8, params)) < 0) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + /* Now read the parameters + */ + len = sizeof(str) - 1; + result = + asn1_read_value + (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters", + str, &len); + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + if ((result=_read_dsa_params( str, len, params)) < 0) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + bits[0] = gcry_mpi_get_nbits( params[0]); + bits[1] = gcry_mpi_get_nbits( params[1]); + bits[2] = gcry_mpi_get_nbits( params[2]); + bits[3] = gcry_mpi_get_nbits( params[3]); + + _gnutls_mpi_release( ¶ms[0]); + _gnutls_mpi_release( ¶ms[1]); + _gnutls_mpi_release( ¶ms[2]); + _gnutls_mpi_release( ¶ms[3]); + } + + asn1_delete_structure(c2); + return algo; +} + diff --git a/src/common.c b/src/common.c index 068683fcd5..e826f29c0a 100644 --- a/src/common.c +++ b/src/common.c @@ -24,6 +24,7 @@ void print_x509_info(GNUTLS_STATE state) int serial_size = sizeof(serial); char printable[120]; char *print; + int bits[5], algo; cert_list = gnutls_certificate_get_peers(state, &cert_list_size); @@ -64,6 +65,23 @@ void print_x509_info(GNUTLS_STATE state) printf(" # Certificate version: #%d\n", gnutls_x509_extract_certificate_version(&cert_list[0])); + algo = gnutls_x509_extract_certificate_pk_algorithm( &cert_list[0], bits); + printf(" # Certificate public key: "); + + if (algo==GNUTLS_PK_RSA) { + printf("RSA\n"); + printf(" # Modulus: %d bits\n", bits[0]); + printf(" # Exponent: %d bits\n", bits[1]); + } else if (algo==GNUTLS_PK_DSA) { + printf("DSA\n"); + printf(" # p: %d bits\n", bits[0]); + printf(" # q: %d bits\n", bits[1]); + printf(" # g: %d bits\n", bits[2]); + printf(" # Exponent: %d bits\n", bits[3]); + } else { + printf("UNKNOWN\n"); + } + gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); PRINT_DN(dn); diff --git a/src/gnutls-http-serv b/src/gnutls-http-serv index 2c002598d8..2c44491e4b 100755 --- a/src/gnutls-http-serv +++ b/src/gnutls-http-serv @@ -1,4 +1,4 @@ #! /bin/sh -./gnutls-serv --http --x509certfile x509/cert.pem --x509keyfile x509/key.pem --cafile x509/ca.pem +./gnutls-serv --http --x509certfile x509/cert.pem --x509keyfile x509/key.pem --x509cafile x509/ca.pem $* diff --git a/src/serv.c b/src/serv.c index 2e1ef86ee5..2270f8e21c 100644 --- a/src/serv.c +++ b/src/serv.c @@ -347,7 +347,7 @@ int main(int argc, char **argv) if (x509_cafile != NULL) if (gnutls_certificate_set_x509_trust_file - (cert_cred, x509_cafile, x509_crlfile, GNUTLS_X509_FMT_DER) < 0) { + (cert_cred, x509_cafile, x509_crlfile, GNUTLS_X509_FMT_PEM) < 0) { fprintf(stderr, "Error reading '%s'\n", x509_cafile); exit(1); } @@ -376,7 +376,7 @@ int main(int argc, char **argv) if (x509_certfile != NULL) if (gnutls_certificate_set_x509_key_file - (cert_cred, x509_certfile, x509_keyfile, GNUTLS_X509_FMT_DER) < 0) { + (cert_cred, x509_certfile, x509_keyfile, GNUTLS_X509_FMT_PEM) < 0) { fprintf(stderr, "Error reading '%s' or '%s'\n", x509_certfile, x509_keyfile); |