|  | @@ -487,7 +487,7 @@ static int x509_parse_validity ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 487 | 487 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 488 | 488 |   */
 | 
		
	
		
			
			| 489 | 489 |  static int x509_parse_common_name ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 490 |  | -				    struct x509_name *name,
 | 
		
	
		
			
			|  | 490 | +				    struct x509_string *name,
 | 
		
	
		
			
			| 491 | 491 |  				    const struct asn1_cursor *raw ) {
 | 
		
	
		
			
			| 492 | 492 |  	struct asn1_cursor cursor;
 | 
		
	
		
			
			| 493 | 493 |  	struct asn1_cursor oid_cursor;
 | 
		
	
	
		
			
			|  | @@ -533,7 +533,7 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 533 | 533 |  static int x509_parse_subject ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 534 | 534 |  				const struct asn1_cursor *raw ) {
 | 
		
	
		
			
			| 535 | 535 |  	struct x509_subject *subject = &cert->subject;
 | 
		
	
		
			
			| 536 |  | -	struct x509_name *name = &subject->name;
 | 
		
	
		
			
			|  | 536 | +	struct x509_string *name = &subject->name;
 | 
		
	
		
			
			| 537 | 537 |  	int rc;
 | 
		
	
		
			
			| 538 | 538 |  
 | 
		
	
		
			
			| 539 | 539 |  	/* Record raw subject */
 | 
		
	
	
		
			
			|  | @@ -750,7 +750,7 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 750 | 750 |  	memcpy ( &cursor, raw, sizeof ( cursor ) );
 | 
		
	
		
			
			| 751 | 751 |  	asn1_enter ( &cursor, ASN1_SEQUENCE );
 | 
		
	
		
			
			| 752 | 752 |  
 | 
		
	
		
			
			| 753 |  | -	/* Parse each extension in turn */
 | 
		
	
		
			
			|  | 753 | +	/* Parse each extended key usage in turn */
 | 
		
	
		
			
			| 754 | 754 |  	while ( cursor.len ) {
 | 
		
	
		
			
			| 755 | 755 |  		if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
 | 
		
	
		
			
			| 756 | 756 |  			return rc;
 | 
		
	
	
		
			
			|  | @@ -760,14 +760,145 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
 | 
		
	
		
			
			| 760 | 760 |  	return 0;
 | 
		
	
		
			
			| 761 | 761 |  }
 | 
		
	
		
			
			| 762 | 762 |  
 | 
		
	
		
			
			|  | 763 | +/**
 | 
		
	
		
			
			|  | 764 | + * Parse X.509 certificate OCSP access method
 | 
		
	
		
			
			|  | 765 | + *
 | 
		
	
		
			
			|  | 766 | + * @v cert		X.509 certificate
 | 
		
	
		
			
			|  | 767 | + * @v raw		ASN.1 cursor
 | 
		
	
		
			
			|  | 768 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 769 | + */
 | 
		
	
		
			
			|  | 770 | +static int x509_parse_ocsp ( struct x509_certificate *cert,
 | 
		
	
		
			
			|  | 771 | +			     const struct asn1_cursor *raw ) {
 | 
		
	
		
			
			|  | 772 | +	struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
 | 
		
	
		
			
			|  | 773 | +	struct asn1_cursor cursor;
 | 
		
	
		
			
			|  | 774 | +	int rc;
 | 
		
	
		
			
			|  | 775 | +
 | 
		
	
		
			
			|  | 776 | +	/* Enter accessLocation */
 | 
		
	
		
			
			|  | 777 | +	memcpy ( &cursor, raw, sizeof ( cursor ) );
 | 
		
	
		
			
			|  | 778 | +	if ( ( rc = asn1_enter ( &cursor, ASN1_IMPLICIT_TAG ( 6 ) ) ) != 0 ) {
 | 
		
	
		
			
			|  | 779 | +		DBGC ( cert, "X509 %p OCSP does not contain "
 | 
		
	
		
			
			|  | 780 | +		       "uniformResourceIdentifier:\n", cert );
 | 
		
	
		
			
			|  | 781 | +		DBGC_HDA ( cert, 0, raw->data, raw->len );
 | 
		
	
		
			
			|  | 782 | +		return rc;
 | 
		
	
		
			
			|  | 783 | +	}
 | 
		
	
		
			
			|  | 784 | +
 | 
		
	
		
			
			|  | 785 | +	/* Record URI */
 | 
		
	
		
			
			|  | 786 | +	ocsp->uri.data = cursor.data;
 | 
		
	
		
			
			|  | 787 | +	ocsp->uri.len = cursor.len;
 | 
		
	
		
			
			|  | 788 | +	DBGC ( cert, "X509 %p OCSP URI is:\n", cert );
 | 
		
	
		
			
			|  | 789 | +	DBGC_HDA ( cert, 0, ocsp->uri.data, ocsp->uri.len );
 | 
		
	
		
			
			|  | 790 | +
 | 
		
	
		
			
			|  | 791 | +	return 0;
 | 
		
	
		
			
			|  | 792 | +}
 | 
		
	
		
			
			|  | 793 | +
 | 
		
	
		
			
			|  | 794 | +/** "id-ad-ocsp" object identifier */
 | 
		
	
		
			
			|  | 795 | +static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
 | 
		
	
		
			
			|  | 796 | +
 | 
		
	
		
			
			|  | 797 | +/** Supported access methods */
 | 
		
	
		
			
			|  | 798 | +static struct x509_access_method x509_access_methods[] = {
 | 
		
	
		
			
			|  | 799 | +	{
 | 
		
	
		
			
			|  | 800 | +		.name = "OCSP",
 | 
		
	
		
			
			|  | 801 | +		.oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
 | 
		
	
		
			
			|  | 802 | +		.parse = x509_parse_ocsp,
 | 
		
	
		
			
			|  | 803 | +	},
 | 
		
	
		
			
			|  | 804 | +};
 | 
		
	
		
			
			|  | 805 | +
 | 
		
	
		
			
			|  | 806 | +/**
 | 
		
	
		
			
			|  | 807 | + * Identify X.509 access method by OID
 | 
		
	
		
			
			|  | 808 | + *
 | 
		
	
		
			
			|  | 809 | + * @v oid		OID
 | 
		
	
		
			
			|  | 810 | + * @ret method		Access method, or NULL
 | 
		
	
		
			
			|  | 811 | + */
 | 
		
	
		
			
			|  | 812 | +static struct x509_access_method *
 | 
		
	
		
			
			|  | 813 | +x509_find_access_method ( const struct asn1_cursor *oid ) {
 | 
		
	
		
			
			|  | 814 | +	struct x509_access_method *method;
 | 
		
	
		
			
			|  | 815 | +	unsigned int i;
 | 
		
	
		
			
			|  | 816 | +
 | 
		
	
		
			
			|  | 817 | +	for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
 | 
		
	
		
			
			|  | 818 | +			    sizeof ( x509_access_methods[0] ) ) ; i++ ) {
 | 
		
	
		
			
			|  | 819 | +		method = &x509_access_methods[i];
 | 
		
	
		
			
			|  | 820 | +		if ( asn1_compare ( &method->oid, oid ) == 0 )
 | 
		
	
		
			
			|  | 821 | +			return method;
 | 
		
	
		
			
			|  | 822 | +	}
 | 
		
	
		
			
			|  | 823 | +
 | 
		
	
		
			
			|  | 824 | +	return NULL;
 | 
		
	
		
			
			|  | 825 | +}
 | 
		
	
		
			
			|  | 826 | +
 | 
		
	
		
			
			|  | 827 | +/**
 | 
		
	
		
			
			|  | 828 | + * Parse X.509 certificate access description
 | 
		
	
		
			
			|  | 829 | + *
 | 
		
	
		
			
			|  | 830 | + * @v cert		X.509 certificate
 | 
		
	
		
			
			|  | 831 | + * @v raw		ASN.1 cursor
 | 
		
	
		
			
			|  | 832 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 833 | + */
 | 
		
	
		
			
			|  | 834 | +static int x509_parse_access_description ( struct x509_certificate *cert,
 | 
		
	
		
			
			|  | 835 | +					   const struct asn1_cursor *raw ) {
 | 
		
	
		
			
			|  | 836 | +	struct asn1_cursor cursor;
 | 
		
	
		
			
			|  | 837 | +	struct asn1_cursor subcursor;
 | 
		
	
		
			
			|  | 838 | +	struct x509_access_method *method;
 | 
		
	
		
			
			|  | 839 | +	int rc;
 | 
		
	
		
			
			|  | 840 | +
 | 
		
	
		
			
			|  | 841 | +	/* Enter keyPurposeId */
 | 
		
	
		
			
			|  | 842 | +	memcpy ( &cursor, raw, sizeof ( cursor ) );
 | 
		
	
		
			
			|  | 843 | +	asn1_enter ( &cursor, ASN1_SEQUENCE );
 | 
		
	
		
			
			|  | 844 | +
 | 
		
	
		
			
			|  | 845 | +	/* Try to identify access method */
 | 
		
	
		
			
			|  | 846 | +	memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
 | 
		
	
		
			
			|  | 847 | +	asn1_enter ( &subcursor, ASN1_OID );
 | 
		
	
		
			
			|  | 848 | +	method = x509_find_access_method ( &subcursor );
 | 
		
	
		
			
			|  | 849 | +	asn1_skip_any ( &cursor );
 | 
		
	
		
			
			|  | 850 | +	DBGC ( cert, "X509 %p found access method %s\n",
 | 
		
	
		
			
			|  | 851 | +	       cert, ( method ? method->name : "<unknown>" ) );
 | 
		
	
		
			
			|  | 852 | +
 | 
		
	
		
			
			|  | 853 | +	/* Parse access location, if applicable */
 | 
		
	
		
			
			|  | 854 | +	if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
 | 
		
	
		
			
			|  | 855 | +		return rc;
 | 
		
	
		
			
			|  | 856 | +
 | 
		
	
		
			
			|  | 857 | +	return 0;
 | 
		
	
		
			
			|  | 858 | +}
 | 
		
	
		
			
			|  | 859 | +
 | 
		
	
		
			
			|  | 860 | +/**
 | 
		
	
		
			
			|  | 861 | + * Parse X.509 certificate authority information access
 | 
		
	
		
			
			|  | 862 | + *
 | 
		
	
		
			
			|  | 863 | + * @v cert		X.509 certificate
 | 
		
	
		
			
			|  | 864 | + * @v raw		ASN.1 cursor
 | 
		
	
		
			
			|  | 865 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 866 | + */
 | 
		
	
		
			
			|  | 867 | +static int x509_parse_authority_info_access ( struct x509_certificate *cert,
 | 
		
	
		
			
			|  | 868 | +					      const struct asn1_cursor *raw ) {
 | 
		
	
		
			
			|  | 869 | +	struct asn1_cursor cursor;
 | 
		
	
		
			
			|  | 870 | +	int rc;
 | 
		
	
		
			
			|  | 871 | +
 | 
		
	
		
			
			|  | 872 | +	/* Enter authorityInfoAccess */
 | 
		
	
		
			
			|  | 873 | +	memcpy ( &cursor, raw, sizeof ( cursor ) );
 | 
		
	
		
			
			|  | 874 | +	asn1_enter ( &cursor, ASN1_SEQUENCE );
 | 
		
	
		
			
			|  | 875 | +
 | 
		
	
		
			
			|  | 876 | +	/* Parse each access description in turn */
 | 
		
	
		
			
			|  | 877 | +	while ( cursor.len ) {
 | 
		
	
		
			
			|  | 878 | +		if ( ( rc = x509_parse_access_description ( cert,
 | 
		
	
		
			
			|  | 879 | +							    &cursor ) ) != 0 )
 | 
		
	
		
			
			|  | 880 | +			return rc;
 | 
		
	
		
			
			|  | 881 | +		asn1_skip_any ( &cursor );
 | 
		
	
		
			
			|  | 882 | +	}
 | 
		
	
		
			
			|  | 883 | +
 | 
		
	
		
			
			|  | 884 | +	return 0;
 | 
		
	
		
			
			|  | 885 | +}
 | 
		
	
		
			
			|  | 886 | +
 | 
		
	
		
			
			| 763 | 887 |  /** "id-ce-basicConstraints" object identifier */
 | 
		
	
		
			
			| 764 |  | -static uint8_t oid_ce_basic_constraints[] = { ASN1_OID_BASICCONSTRAINTS };
 | 
		
	
		
			
			|  | 888 | +static uint8_t oid_ce_basic_constraints[] =
 | 
		
	
		
			
			|  | 889 | +	{ ASN1_OID_BASICCONSTRAINTS };
 | 
		
	
		
			
			| 765 | 890 |  
 | 
		
	
		
			
			| 766 | 891 |  /** "id-ce-keyUsage" object identifier */
 | 
		
	
		
			
			| 767 |  | -static uint8_t oid_ce_key_usage[] = { ASN1_OID_KEYUSAGE };
 | 
		
	
		
			
			|  | 892 | +static uint8_t oid_ce_key_usage[] =
 | 
		
	
		
			
			|  | 893 | +	{ ASN1_OID_KEYUSAGE };
 | 
		
	
		
			
			| 768 | 894 |  
 | 
		
	
		
			
			| 769 | 895 |  /** "id-ce-extKeyUsage" object identifier */
 | 
		
	
		
			
			| 770 |  | -static uint8_t oid_ce_ext_key_usage[] = { ASN1_OID_EXTKEYUSAGE };
 | 
		
	
		
			
			|  | 896 | +static uint8_t oid_ce_ext_key_usage[] =
 | 
		
	
		
			
			|  | 897 | +	{ ASN1_OID_EXTKEYUSAGE };
 | 
		
	
		
			
			|  | 898 | +
 | 
		
	
		
			
			|  | 899 | +/** "id-pe-authorityInfoAccess" object identifier */
 | 
		
	
		
			
			|  | 900 | +static uint8_t oid_pe_authority_info_access[] =
 | 
		
	
		
			
			|  | 901 | +	{ ASN1_OID_AUTHORITYINFOACCESS };
 | 
		
	
		
			
			| 771 | 902 |  
 | 
		
	
		
			
			| 772 | 903 |  /** Supported certificate extensions */
 | 
		
	
		
			
			| 773 | 904 |  static struct x509_extension x509_extensions[] = {
 | 
		
	
	
		
			
			|  | @@ -786,6 +917,11 @@ static struct x509_extension x509_extensions[] = {
 | 
		
	
		
			
			| 786 | 917 |  		.oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
 | 
		
	
		
			
			| 787 | 918 |  		.parse = x509_parse_extended_key_usage,
 | 
		
	
		
			
			| 788 | 919 |  	},
 | 
		
	
		
			
			|  | 920 | +	{
 | 
		
	
		
			
			|  | 921 | +		.name = "authorityInfoAccess",
 | 
		
	
		
			
			|  | 922 | +		.oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
 | 
		
	
		
			
			|  | 923 | +		.parse = x509_parse_authority_info_access,
 | 
		
	
		
			
			|  | 924 | +	},
 | 
		
	
		
			
			| 789 | 925 |  };
 | 
		
	
		
			
			| 790 | 926 |  
 | 
		
	
		
			
			| 791 | 927 |  /**
 |