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 /lib | |
parent | 90e5b542084f0af2b7242824e82fe32635dddc45 (diff) | |
download | gnutls-afa9584ac75c439ce8c2722de48b0fb2ad943adb.tar.gz |
added gnutls_x509_extract_certificate_pk_algorithm()
Diffstat (limited to 'lib')
-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 |
6 files changed, 176 insertions, 30 deletions
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; +} + |