diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/auth_cert.c | 2 | ||||
-rw-r--r-- | lib/gnutls_global.c | 2 | ||||
-rw-r--r-- | lib/gnutls_hash_int.c | 3 | ||||
-rw-r--r-- | lib/gnutls_random.c | 42 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 1 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 425 | ||||
-rw-r--r-- | lib/pkix.asn | 40 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 51 | ||||
-rwxr-xr-x | lib/x509_asn1.c | 4 | ||||
-rw-r--r-- | lib/x509_extensions.c | 6 | ||||
-rw-r--r-- | lib/x509_sig_check.c | 2 | ||||
-rw-r--r-- | lib/x509_verify.c | 4 | ||||
-rwxr-xr-x | src/gnutls-http-serv | 2 | ||||
-rw-r--r-- | src/serv.c | 2 |
16 files changed, 432 insertions, 159 deletions
@@ -1,3 +1,6 @@ +Version 0.4.0 +- Added support for RFC2630 (PKCS7) X.509 certificate sets + Version 0.3.92 (23/03/2002) - Updated documentation - Combined error codes of ASN.1 parser and gnutls diff --git a/lib/Makefile.am b/lib/Makefile.am index f1e199a52c..074b211c11 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -39,7 +39,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \ x509_extensions.c auth_cert.c gnutls_ui.c gnutls_sig.c auth_dhe.c \ gnutls_dh_primes.c ext_max_record.c gnutls_alert.c gnutls_int_compat.c \ gnutls_str.c gnutls_state.c gnutls_x509.c gnutls_openpgp.c \ - ext_cert_type.c + ext_cert_type.c # Separate so we can create the documentation COBJECTS2 = x509_ASN.y x509_asn1.c x509_der.c diff --git a/lib/auth_cert.c b/lib/auth_cert.c index 4865362448..ac05a74b8b 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -105,7 +105,7 @@ int _gnutls_find_dn(gnutls_datum * odn, gnutls_cert * cert) int start, end; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &dn, + (_gnutls_get_pkix(), "PKIX1.Certificate", &dn, "dn")) != ASN_OK) { gnutls_assert(); return result; diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 5e0707ae08..8998268ede 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -113,7 +113,7 @@ int gnutls_global_init( void) asn1_delete_structure( PKIX1_ASN); return result; } - + result = _gnutls_dh_calc_mpis(); if (result < 0) { gnutls_assert(); diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c index 273bca4c99..fcbb0d7ad3 100644 --- a/lib/gnutls_hash_int.c +++ b/lib/gnutls_hash_int.c @@ -148,6 +148,9 @@ void gnutls_hash_deinit(GNUTLS_HASH_HANDLE handle, void* digest) free(ret); } #else + /* FIXME: replace this with something that does not + * allocate the hash + */ maclen = gcry_md_get_algo_dlen(gcry_md_get_algo(handle->handle)); gcry_md_final(handle->handle); mac = gcry_md_read(handle->handle, 0); diff --git a/lib/gnutls_random.c b/lib/gnutls_random.c index b2acb0cb72..609ca21760 100644 --- a/lib/gnutls_random.c +++ b/lib/gnutls_random.c @@ -28,56 +28,30 @@ # include <sys/types.h> # include <sys/stat.h> # include <fcntl.h> -# ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -# endif #endif -int _gnutls_get_random(opaque * res, int bytes, int dev) +/* fills the buffer 'res' with random bytes of 'bytes' long. + * level is WEAK, STRONG, or VERY_STRONG (libgcrypt) + */ +int _gnutls_get_random(opaque * res, int bytes, int level) { #ifndef USE_GCRYPT int fd; - struct timeval tv; - char prand[16]; char *device; -#error DONT USE THAT - - switch(dev) { - case 1: - device = "/dev/random"; - break; - default: - device = "dev/urandom"; - } + device = "dev/urandom"; fd = open(device, O_RDONLY); if (device == NULL || fd < 0) { - gettimeofday(&tv, (struct timezone *) 0); - memcpy(prand, &tv, sizeof(tv)); - fd = getpid(); - memcpy(&prand[8], &fd, sizeof(fd)); - fd = clock(); - memcpy(&prand[12], &fd, sizeof(fd)); - memset(res, 0, bytes); - if (bytes > 16) - bytes = 16; - memcpy(res, prand, bytes); + _gnutls_log( "Could not open random device\n"); + return GNUTLS_E_FILE_ERROR; } else { read(fd, res, bytes); close(fd); } return 0; #else /* using gcrypt */ - char* buf; - buf = gcry_random_bytes(bytes, dev); - if (buf==NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - - memcpy( res, buf, bytes); - gcry_free(buf); + gcry_randomize( res, bytes, level); return 0; #endif diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index 22b2e08af3..a20dc122ef 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -88,6 +88,7 @@ int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* resu 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_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 e6180ff16e..2a6b4e4ca1 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -48,6 +48,9 @@ * some x509 certificate parsing functions. */ +int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size); + + #define _READ(a, aa, b, c, d, e, res, f) \ result = _IREAD(a, aa, sizeof(aa), b, c, d, e, res, sizeof(res)-1, f); \ if (result<0) return result; \ @@ -64,7 +67,7 @@ static int _IREAD(node_asn * rasn, char *name3, int name3_size, char *rstr, char if (strcmp(rstr, OID) == 0) { - _gnutls_str_cpy(str, sizeof(str), "PKIX1Implicit88."); + _gnutls_str_cpy(str, sizeof(str), "PKIX1."); _gnutls_str_cat(str, sizeof(str), ANAME); _gnutls_str_cpy(name2, sizeof(name2), "temp-structure-"); _gnutls_str_cat(name2, sizeof(name2), TYPE); @@ -333,7 +336,7 @@ int gnutls_x509_extract_dn(const gnutls_datum * idn, gnutls_x509_dn * rdn) if ((result = asn1_create_structure(_gnutls_get_pkix(), - "PKIX1Implicit88.Name", &dn, + "PKIX1.Name", &dn, "dn")) != ASN_OK) { gnutls_assert(); return result; @@ -378,9 +381,9 @@ int gnutls_x509_extract_certificate_dn(const gnutls_datum * cert, memset(ret, 0, sizeof(gnutls_x509_dn)); - if (asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, - "certificate2") + if ((result=asn1_create_structure + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, + "certificate2")) != ASN_OK) { gnutls_assert(); return result; @@ -430,9 +433,9 @@ int gnutls_x509_extract_certificate_issuer_dn(const gnutls_datum * cert, memset(ret, 0, sizeof(gnutls_x509_dn)); - if (asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, - "certificate2") + if ((result=asn1_create_structure + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, + "certificate2")) != ASN_OK) { gnutls_assert(); return result; @@ -487,7 +490,8 @@ static GNUTLS_X509_SUBJECT_ALT_NAME _find_type( char* str_type) { * or the type of alternative name if everything was ok. The type is one of the * enumerated GNUTLS_X509_SUBJECT_ALT_NAME. * - * If the certificate does not have a Alternative name then returns GNUTLS_E_DATA_NOT_AVAILABLE; + * If the certificate does not have an Alternative name with the specified sequence number + * then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; * **/ int gnutls_x509_extract_subject_alt_name(const gnutls_datum * cert, int seq, char *ret, int *ret_size) @@ -515,7 +519,7 @@ int gnutls_x509_extract_subject_alt_name(const gnutls_datum * cert, int seq, cha } if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.SubjectAltName", &c2, "san")) + (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2, "san")) != ASN_OK) { gnutls_assert(); gnutls_free_datum( &dnsname); @@ -540,8 +544,15 @@ int gnutls_x509_extract_subject_alt_name(const gnutls_datum * cert, int seq, cha _gnutls_str_cat( nptr, sizeof(nptr), num); len = sizeof(ext_data); - if ((result = - asn1_read_value(c2, nptr, ext_data, &len)) != ASN_OK) { + result = + asn1_read_value(c2, nptr, ext_data, &len); + + if (result == ASN_VALUE_NOT_FOUND) { + asn1_delete_structure(c2); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (result != ASN_OK) { gnutls_assert(); asn1_delete_structure(c2); return result; @@ -588,7 +599,7 @@ time_t gnutls_x509_extract_certificate_activation_time(const time_t ret; if (asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2") != ASN_OK) { gnutls_assert(); @@ -630,7 +641,7 @@ time_t gnutls_x509_extract_certificate_expiration_time(const time_t ret; if (asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2") != ASN_OK) { gnutls_assert(); @@ -668,7 +679,7 @@ int gnutls_x509_extract_certificate_version(const gnutls_datum * cert) int result; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2")) != ASN_OK) { gnutls_assert(); @@ -897,7 +908,7 @@ int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* resu int ret; if ((ret=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2")) != ASN_OK) { gnutls_assert(); @@ -946,37 +957,106 @@ static int _gnutls_check_key_cert_match( GNUTLS_CERTIFICATE_CREDENTIALS res) { #define MAX_FILE_SIZE 100*1024 #define CERT_SEP "-----BEGIN" -/* Reads a base64 encoded certificate from memory +/* Reads a PKCS7 base64 encoded certificate list from memory and stores it to + * a gnutls_cert structure. */ -static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, int cert_size) +static int parse_pkcs7_cert_mem( gnutls_cert** cert_list, int* ncerts, + const char *input_cert, int input_cert_size) { - int siz, i, siz2; + int siz, i, j; opaque *b64; const char *ptr; - gnutls_datum tmp; + gnutls_datum tmp, tmp2; int ret; + opaque pcert[MAX_X509_CERT_SIZE]; + int pcert_size; - /* allocate space for the certificate to add - */ - res->cert_list = gnutls_realloc( res->cert_list, (1+res->ncerts)*sizeof(gnutls_cert*)); - if (res->cert_list==NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } + ptr = input_cert; + siz = input_cert_size; + i = *ncerts + 1; - res->cert_list_length = gnutls_realloc( res->cert_list_length, - (1+res->ncerts)*sizeof(int)); - if (res->cert_list_length==NULL) { + ret = _gnutls_fbase64_decode(ptr, siz, &b64); + + if (ret < 0) { gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; + return GNUTLS_E_PARSING_ERROR; } + + /* tmp now contains the decoded certificate list */ + tmp.data = b64; + tmp.size = ret; + j = 0; + do { + pcert_size = sizeof(pcert); + ret = gnutls_x509_pkcs7_extract_certificate( &tmp, j, pcert, &pcert_size); - ptr = cert; - siz = cert_size; - i = 1; + /* if the current certificate is too long, just ignore + * it. */ + if (ret==GNUTLS_E_MEMORY_ERROR) continue; + + if (ret >= 0) { + *cert_list = + (gnutls_cert *) gnutls_realloc( *cert_list, + i * sizeof(gnutls_cert)); + + if ( *cert_list == NULL) { + gnutls_assert(); + gnutls_free(b64); + return GNUTLS_E_MEMORY_ERROR; + } + + /* set defaults to zero + */ + memset( &cert_list[0][i - 1], 0, sizeof(gnutls_cert)); + + tmp2.data = pcert; + tmp2.size = pcert_size; + + if ((ret = + _gnutls_x509_cert2gnutls_cert( + &cert_list[0][i - 1], + tmp2)) < 0) { + gnutls_free(b64); + gnutls_assert(); + return ret; + } + + i++; + } + j++; + + } while (ret >= 0); + + gnutls_free(b64); + + *ncerts = i - 1; + + return 0; +} + + +/* Reads a base64 encoded certificate list from memory and stores it to + * a gnutls_cert structure. + */ +static int parse_cert_mem( gnutls_cert** cert_list, int* ncerts, + const char *input_cert, int input_cert_size) +{ + int siz, i, siz2; + opaque *b64; + const char *ptr; + gnutls_datum tmp; + int ret; - res->cert_list[res->ncerts] = NULL; + if (strstr( input_cert, "-----BEGIN PKCS7")!=NULL) { + return parse_pkcs7_cert_mem( cert_list, ncerts, input_cert, + input_cert_size); + } + + + ptr = input_cert; + siz = input_cert_size; + i = *ncerts + 1; do { siz2 = _gnutls_fbase64_decode(ptr, siz, &b64); @@ -989,28 +1069,27 @@ static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, i } - res->cert_list[res->ncerts] = - (gnutls_cert *) gnutls_realloc(res-> - cert_list[res->ncerts], + *cert_list = + (gnutls_cert *) gnutls_realloc( *cert_list, i * sizeof(gnutls_cert)); - if (res->cert_list[res->ncerts] == NULL) { + if ( *cert_list == NULL) { gnutls_assert(); gnutls_free(b64); return GNUTLS_E_MEMORY_ERROR; } /* set defaults to zero */ - memset(&res->cert_list[res->ncerts][i - 1], 0, + memset( &cert_list[0][i - 1], 0, sizeof(gnutls_cert)); tmp.data = b64; tmp.size = siz2; if ((ret = - _gnutls_x509_cert2gnutls_cert(&res-> - cert_list[res->ncerts][i - 1], + _gnutls_x509_cert2gnutls_cert( + &cert_list[0][i - 1], tmp)) < 0) { gnutls_free(b64); gnutls_assert(); @@ -1026,73 +1105,57 @@ static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, i i++; } while ((ptr = strstr(ptr, CERT_SEP)) != NULL); - res->cert_list_length[res->ncerts] = i - 1; - + *ncerts = i - 1; return 0; } -/* Reads a base64 encoded CA list from memory - * This is to be called once. + + +/* Reads a base64 encoded certificate from memory */ -static int read_ca_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *ca, int ca_size) +static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, int cert_size) { - int siz, siz2, i; - opaque *b64; - const char *ptr; int ret; - gnutls_datum tmp; - siz = ca_size; - - ptr = ca; - - i = res->x509_ncas + 1; - - do { - siz2 = _gnutls_fbase64_decode(ptr, siz, &b64); - siz -= siz2; /* FIXME: this is not enough - */ + /* allocate space for the certificate to add + */ + res->cert_list = gnutls_realloc( res->cert_list, (1+ res->ncerts)*sizeof(gnutls_cert*)); + if ( res->cert_list==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } - if (siz2 < 0) { - gnutls_assert(); - return GNUTLS_E_PARSING_ERROR; - } + res->cert_list_length = gnutls_realloc( res->cert_list_length, + (1+ res->ncerts)*sizeof(int)); + if (res->cert_list_length==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } - res->x509_ca_list = - (gnutls_cert *) gnutls_realloc(res->x509_ca_list, - i * - sizeof(gnutls_cert)); - if (res->x509_ca_list == NULL) { - gnutls_assert(); - gnutls_free(b64); - return GNUTLS_E_MEMORY_ERROR; - } - memset(&res->x509_ca_list[i - 1], 0, sizeof(gnutls_cert)); + res->cert_list[res->ncerts] = NULL; /* for realloc */ + res->cert_list_length[res->ncerts] = 0; - tmp.data = b64; - tmp.size = siz2; + ret = parse_cert_mem( &res->cert_list[res->ncerts], &res->cert_list_length[res->ncerts], + cert, cert_size); - if ((ret = - _gnutls_x509_cert2gnutls_cert(&res->x509_ca_list[i - 1], - tmp)) < 0) { - gnutls_assert(); - gnutls_free(b64); - return ret; - } - gnutls_free(b64); + if (ret < 0) { + gnutls_assert(); + return ret; + } - /* now we move ptr after the pem header */ - ptr = strstr(ptr, CERT_SEP); - if (ptr!=NULL) - ptr++; + return 0; +} - i++; - } while ((ptr = strstr(ptr, CERT_SEP)) != NULL); +/* Reads a base64 encoded CA list from memory + * This is to be called once. + */ +static int read_ca_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *ca, int ca_size) +{ - res->x509_ncas = i - 1; + return parse_cert_mem( &res->x509_ca_list, &res->x509_ncas, + ca, ca_size); - return 0; } @@ -1230,7 +1293,7 @@ static int read_key_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *keyfile) * gnutls_certificate_set_x509_key_file - Used to set keys in a GNUTLS_CERTIFICATE_CREDENTIALS structure * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure. * @CERTFILE: is a PEM encoded file containing the certificate list (path) for - * the specified private key + * the specified private key or a PEM encoded PKCS7 file * @KEYFILE: is a PEM encoded file containing a private key * * This function sets a certificate/private key pair in the @@ -1320,7 +1383,7 @@ opaque *pdata; /** * gnutls_certificate_set_x509_trust_mem - Used to add trusted CAs in a GNUTLS_CERTIFICATE_CREDENTIALS structure * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure. - * @CA: is a PEM encoded list of trusted CAs + * @CA: is a PEM encoded list of trusted CAs or a PKCS7 pem encoded list * @CRL: is a PEM encoded list of CRLs (ignored for now) * * This function adds the trusted CAs in order to verify client @@ -1459,7 +1522,7 @@ static int _read_dsa_params(opaque * der, int dersize, MPI * params) node_asn *spk; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Dss-Parms", &spk, + (_gnutls_get_pkix(), "PKIX1.Dss-Parms", &spk, "dsa_parms")) != ASN_OK) { gnutls_assert(); return result; @@ -1685,7 +1748,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert) } if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + (_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2")) != ASN_OK) { gnutls_assert(); @@ -1767,6 +1830,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert) if (gCert->version < 0) { gnutls_assert(); asn1_delete_structure(c2); + gnutls_free_datum( &gCert->raw); return GNUTLS_E_ASN1_GENERIC_ERROR; } @@ -1923,4 +1987,171 @@ int _gnutls_verify_x509_file( char *cafile) return _gnutls_verify_x509_mem( x, siz); } + + #endif + +/** + * gnutls_x509_pkcs7_extract_certificate - This function returns a certificate in a PKCS7 certificate set + * @pkcs7_struct: should contain a PKCS7 DER formatted structure + * @indx: contains the index of the certificate to extract + * @certificate: the contents of the certificate will be copied there + * @certificate_size: should hold the size of the certificate + * + * This function will return a certificate of the PKCS7 or RFC2630 certificate set. + * Returns 0 on success. + * + **/ +int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size) +{ + node_asn *c2, *c1; + int result, len; + char root1[128]; + char oid[128]; + char root2[128]; + char counter[MAX_INT_DIGITS]; + opaque* pkcs7_str = pkcs7_struct->data; + int pkcs7_str_size = pkcs7_struct->size; + + opaque* pcert; + int pcert_size; + + /* Step 1. Parse content and content info */ + + if (pkcs7_str_size == 0 || pkcs7_str == NULL) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + _gnutls_str_cpy( root1, sizeof(root1), "PKIX1.ContentInfo"); + if ((result=asn1_create_structure + (_gnutls_get_pkix(), root1, &c1, "c1")) != ASN_OK) { + gnutls_assert(); + return result; + } + + result = asn1_get_der(c1, pkcs7_str, pkcs7_str_size); + if (result != ASN_OK) { + /* couldn't decode DER */ + + _gnutls_log("X509_auth: Decoding error %d\n"); + + gnutls_assert(); + asn1_delete_structure(c1); + return result; + } + + len = sizeof(oid) - 1; + + /* root2 is used as a temp storage area + */ + _gnutls_str_cpy( root2, sizeof(root2), "c1.contentType"); + result = asn1_read_value(c1, root2, oid, &len); + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(c1); + return result; + } + + if ( strcmp( oid, "1 2 840 113549 1 7 2") != 0) { + gnutls_assert(); + asn1_delete_structure(c1); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + pcert_size = *certificate_size - 1; + pcert = certificate; + + _gnutls_str_cpy( root2, sizeof(root2), "c1.content"); + result = asn1_read_value(c1, root2, pcert, &pcert_size); + + asn1_delete_structure(c1); + + if (result != ASN_OK) { + gnutls_assert(); + return result; + } + + /* pcert, pcert_size hold the data and the size of the CertificateSet structure + * actually the ANY stuff. + */ + + + /* Step 1.5. In case of a signed structure extract certificate set. + */ + _gnutls_str_cpy( root2, sizeof(root2), "PKIX1.SignedData"); + if ((result=asn1_create_structure + (_gnutls_get_pkix(), root2, &c2, "c2")) != ASN_OK) { + gnutls_assert(); + return result; + } + + result = asn1_get_der(c2, pcert, pcert_size); + if (result != ASN_OK) { + /* couldn't decode DER */ + + _gnutls_log("X509_auth: Decoding error %d\n"); + + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + + /* Step 2. Parse CertificateSet */ + + + _gnutls_str_cpy( root2, sizeof(root2), "c2.certificates.?"); + _gnutls_int2str( indx+1, counter); + _gnutls_str_cat( root2, sizeof(root2), counter); + + len = sizeof(oid) - 1; + + result = asn1_read_value(c2, root2, oid, &len); + + if (result == ASN_VALUE_NOT_FOUND) { + asn1_delete_structure(c2); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + /* if 'Certificate' is the choice found: */ + if (strcmp( oid, "certificate") == 0) { + int start, end; + +/* _gnutls_str_cat( root2, sizeof(root2), ".certificate"); */ + + result = asn1_get_start_end_der(c2, pcert, pcert_size, + root2, &start, &end); + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(c2); + return result; + } + + end = end-start+1; + + if (certificate!=NULL && end <= *certificate_size) + memcpy( certificate, &pcert[start], end); + else { + *certificate_size = end; + return GNUTLS_E_MEMORY_ERROR; + } + + *certificate_size = end; + + } else { + asn1_delete_structure(c2); + return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + asn1_delete_structure(c2); + + return 0; +} diff --git a/lib/pkix.asn b/lib/pkix.asn index 9faab3a370..fb44650127 100644 --- a/lib/pkix.asn +++ b/lib/pkix.asn @@ -1,11 +1,11 @@ -PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1) - security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)} +PKIX1 { } DEFINITIONS IMPLICIT TAGS ::= BEGIN +-- This contains both PKIX1Implicit88 and RFC2630 ASN.1 modules. -- ISO arc for standard certificate and CRL extensions @@ -937,13 +937,47 @@ ub-x121-address-length INTEGER ::= 16 -END +-- END of PKIX1Implicit88 + + +-- BEGIN of RFC2630 + +-- Cryptographic Message Syntax + +ContentInfo ::= SEQUENCE { + contentType ContentType, + content [0] EXPLICIT ANY DEFINED BY contentType } +ContentType ::= OBJECT IDENTIFIER +SignedData ::= SEQUENCE { + version CMSVersion, + digestAlgorithms DigestAlgorithmIdentifiers, + encapContentInfo EncapsulatedContentInfo, + certificates [0] IMPLICIT CertificateSet OPTIONAL, + crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos +} + +CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) } +DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier +DigestAlgorithmIdentifier ::= AlgorithmIdentifier +EncapsulatedContentInfo ::= SEQUENCE { + eContentType ContentType, + eContent [0] EXPLICIT OCTET STRING OPTIONAL } +CertificateRevocationLists ::= SET OF CertificateList +CertificateChoices ::= CHOICE { + certificate Certificate +} +CertificateSet ::= SET OF CertificateChoices +SignerInfos ::= SET OF ANY -- this is not correct but we don't use it + -- anyway + +END diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c index 727a980f4c..6839f8e996 100644 --- a/lib/pkix_asn1_tab.c +++ b/lib/pkix_asn1_tab.c @@ -2,17 +2,8 @@ #include "x509_asn1.h" const static_asn pkix_asn1_tab[]={ - {"PKIX1Implicit88",536875024,0}, - {0,1610612748,0}, - {"iso",1073741825,"1"}, - {"identified-organization",1073741825,"3"}, - {"dod",1073741825,"6"}, - {"internet",1073741825,"1"}, - {"security",1073741825,"5"}, - {"mechanisms",1073741825,"5"}, - {"pkix",1073741825,"7"}, - {"id-mod",1073741825,"0"}, - {"id-pkix1-implicit-88",1,"2"}, + {"PKIX1",536875024,0}, + {0,1073741836,0}, {"id-ce",1879048204,0}, {"joint-iso-ccitt",1073741825,"2"}, {"ds",1073741825,"5"}, @@ -869,6 +860,42 @@ const static_asn pkix_asn1_tab[]={ {"ub-surname-length",1342177283,"40"}, {"ub-terminal-id-length",1342177283,"24"}, {"ub-unformatted-address-length",1342177283,"180"}, - {"ub-x121-address-length",268435459,"16"}, + {"ub-x121-address-length",1342177283,"16"}, + {"ContentInfo",1610612741,0}, + {"contentType",1073741826,"ContentType"}, + {"content",541073421,0}, + {0,1073743880,"0"}, + {"contentType",1,0}, + {"ContentType",1073741836,0}, + {"SignedData",1610612741,0}, + {"version",1073741826,"CMSVersion"}, + {"digestAlgorithms",1073741826,"DigestAlgorithmIdentifiers"}, + {"encapContentInfo",1073741826,"EncapsulatedContentInfo"}, + {"certificates",1610637314,"CertificateSet"}, + {0,4104,"0"}, + {"crls",1610637314,"CertificateRevocationLists"}, + {0,4104,"1"}, + {"signerInfos",2,"SignerInfos"}, + {"CMSVersion",1610874883,0}, + {"v0",1073741825,"0"}, + {"v1",1073741825,"1"}, + {"v2",1073741825,"2"}, + {"v3",1073741825,"3"}, + {"v4",1,"4"}, + {"DigestAlgorithmIdentifiers",1610612751,0}, + {0,2,"DigestAlgorithmIdentifier"}, + {"DigestAlgorithmIdentifier",1073741826,"AlgorithmIdentifier"}, + {"EncapsulatedContentInfo",1610612741,0}, + {"eContentType",1073741826,"ContentType"}, + {"eContent",536895495,0}, + {0,2056,"0"}, + {"CertificateRevocationLists",1610612751,0}, + {0,2,"CertificateList"}, + {"CertificateChoices",1610612754,0}, + {"certificate",2,"Certificate"}, + {"CertificateSet",1610612751,0}, + {0,2,"CertificateChoices"}, + {"SignerInfos",536870927,0}, + {0,13,0}, {0,0,0} }; diff --git a/lib/x509_asn1.c b/lib/x509_asn1.c index 6784b2b783..cec909eecb 100755 --- a/lib/x509_asn1.c +++ b/lib/x509_asn1.c @@ -26,10 +26,10 @@ #include <gnutls_int.h> +#include <gnutls_errors.h> #include "x509_asn1.h" #include "x509_der.h" #include <gnutls_str.h> -#include <gnutls_errors.h> /* define used for visiting trees */ #define UP 1 @@ -938,7 +938,7 @@ _asn1_copy_structure2(node_asn *root,char *source_name) * ASN_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known * * Example: using "pkix.asn" - * result=asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",&cert,"certificate1"); + * result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert,"certificate1"); **/ int asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer,char *dest_name) diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c index 87e619f8a5..37d43ab2c7 100644 --- a/lib/x509_extensions.c +++ b/lib/x509_extensions.c @@ -41,7 +41,7 @@ static int _extract_keyUsage(uint16 *keyUsage, opaque * extnValue, keyUsage[0] = 0; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.KeyUsage", &ext, + (_gnutls_get_pkix(), "PKIX1.KeyUsage", &ext, "ku")) != ASN_OK) { gnutls_assert(); return result; @@ -80,7 +80,7 @@ static int _extract_basicConstraints(int *CA, opaque * extnValue, *CA = 0; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.BasicConstraints", &ext, + (_gnutls_get_pkix(), "PKIX1.BasicConstraints", &ext, "bc")) != ASN_OK) { gnutls_assert(); return result; @@ -268,7 +268,7 @@ int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, ret->size = 0; if ((result=asn1_create_structure - (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &rasn, + (_gnutls_get_pkix(), "PKIX1.Certificate", &rasn, "certificate2")) != ASN_OK) { gnutls_assert(); diff --git a/lib/x509_sig_check.c b/lib/x509_sig_check.c index 82547a5e3e..d6368855b9 100644 --- a/lib/x509_sig_check.c +++ b/lib/x509_sig_check.c @@ -42,7 +42,7 @@ opaque *str; int result, len; int start, end; - if (asn1_create_structure( _gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, "certificate")!=ASN_OK) { + if (asn1_create_structure( _gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate")!=ASN_OK) { gnutls_assert(); return ret; } diff --git a/lib/x509_verify.c b/lib/x509_verify.c index 5942e11bdb..d501c75874 100644 --- a/lib/x509_verify.c +++ b/lib/x509_verify.c @@ -206,7 +206,7 @@ int compare_dn(gnutls_cert * cert, gnutls_cert * issuer_cert) /* get the issuer of 'cert' */ - if ((result=asn1_create_structure(_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, "certificate2")) != ASN_OK) { + if ((result=asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate", &c2, "certificate2")) != ASN_OK) { gnutls_assert(); return result; } @@ -223,7 +223,7 @@ int compare_dn(gnutls_cert * cert, gnutls_cert * issuer_cert) /* get the 'subject' info of 'issuer_cert' */ - if ((result=asn1_create_structure(_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c3, "certificate2")) != ASN_OK) { + if ((result=asn1_create_structure(_gnutls_get_pkix(), "PKIX1.Certificate", &c3, "certificate2")) != ASN_OK) { gnutls_assert(); asn1_delete_structure(c2); return result; diff --git a/src/gnutls-http-serv b/src/gnutls-http-serv index 82380eed99..2c002598d8 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 +./gnutls-serv --http --x509certfile x509/cert.pem --x509keyfile x509/key.pem --cafile x509/ca.pem diff --git a/src/serv.c b/src/serv.c index 07c98819e9..2a604fdb9f 100644 --- a/src/serv.c +++ b/src/serv.c @@ -611,7 +611,7 @@ void gaa_parser(int argc, char **argv) #else x509_certfile = info.x509_certfile; x509_keyfile = info.x509_keyfile; - x509_cafile = info.x509_certfile; + x509_cafile = info.x509_cafile; pgp_certfile = info.pgp_certfile; pgp_keyfile = info.pgp_keyfile; srp_passwd = info.srp_passwd; |