summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/TODO2
-rw-r--r--lib/gnutls.h.in.in3
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_pk.h4
-rw-r--r--lib/gnutls_ui.h1
-rw-r--r--lib/gnutls_x509.c196
-rw-r--r--src/common.c18
-rwxr-xr-xsrc/gnutls-http-serv2
-rw-r--r--src/serv.c4
11 files changed, 201 insertions, 34 deletions
diff --git a/NEWS b/NEWS
index 93f3eae24c..e7b55c5de6 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/doc/TODO b/doc/TODO
index 8c48f22d27..82f59622d2 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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( &params[0]);
+ _gnutls_mpi_release( &params[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( &params[0]);
+ _gnutls_mpi_release( &params[1]);
+ _gnutls_mpi_release( &params[2]);
+ _gnutls_mpi_release( &params[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);