Example #1
0
File: ocsp.c Project: eworm-de/ipxe
/**
 * Parse OCSP certificate ID
 *
 * @v ocsp		OCSP check
 * @v raw		ASN.1 cursor
 * @ret rc		Return status code
 */
static int ocsp_parse_cert_id ( struct ocsp_check *ocsp,
				const struct asn1_cursor *raw ) {
	struct asn1_cursor cursor;
	struct asn1_algorithm *algorithm;
	int rc;

	/* Check certID algorithm */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	asn1_enter ( &cursor, ASN1_SEQUENCE );
	if ( ( rc = asn1_digest_algorithm ( &cursor, &algorithm ) ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" certID unknown algorithm: %s\n",
		       ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
		return rc;
	}
	if ( algorithm->digest != &ocsp_digest_algorithm ) {
		DBGC ( ocsp, "OCSP %p \"%s\" certID wrong algorithm %s\n",
		       ocsp, x509_name ( ocsp->cert ),
		       algorithm->digest->name );
		return -EACCES_CERT_MISMATCH;
	}

	/* Check remaining certID fields */
	asn1_skip ( &cursor, ASN1_SEQUENCE );
	if ( asn1_compare ( &cursor, &ocsp->request.cert_id_tail ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
		       ocsp, x509_name ( ocsp->cert ) );
		DBGC_HDA ( ocsp, 0, ocsp->request.cert_id_tail.data,
			   ocsp->request.cert_id_tail.len );
		DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
		return -EACCES_CERT_MISMATCH;
	}

	return 0;
}
Example #2
0
File: ocsp.c Project: eworm-de/ipxe
/**
 * Build OCSP request
 *
 * @v ocsp		OCSP check
 * @ret rc		Return status code
 */
static int ocsp_request ( struct ocsp_check *ocsp ) {
	struct digest_algorithm *digest = &ocsp_digest_algorithm;
	struct asn1_builder *builder = &ocsp->request.builder;
	struct asn1_cursor *cert_id_tail = &ocsp->request.cert_id_tail;
	uint8_t digest_ctx[digest->ctxsize];
	uint8_t name_digest[digest->digestsize];
	uint8_t pubkey_digest[digest->digestsize];
	int rc;

	/* Generate digests */
	digest_init ( digest, digest_ctx );
	digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data,
			ocsp->cert->issuer.raw.len );
	digest_final ( digest, digest_ctx, name_digest );
	digest_init ( digest, digest_ctx );
	digest_update ( digest, digest_ctx,
			ocsp->issuer->subject.public_key.raw_bits.data,
			ocsp->issuer->subject.public_key.raw_bits.len );
	digest_final ( digest, digest_ctx, pubkey_digest );

	/* Construct request */
	if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data,
					 ocsp->cert->serial.raw.len ),
		      asn1_prepend ( builder, ASN1_OCTET_STRING,
				     pubkey_digest, sizeof ( pubkey_digest ) ),
		      asn1_prepend ( builder, ASN1_OCTET_STRING,
				     name_digest, sizeof ( name_digest ) ),
		      asn1_prepend ( builder, ASN1_SEQUENCE,
				     ocsp_algorithm_id,
				     sizeof ( ocsp_algorithm_id ) ),
		      asn1_wrap ( builder, ASN1_SEQUENCE ),
		      asn1_wrap ( builder, ASN1_SEQUENCE ),
		      asn1_wrap ( builder, ASN1_SEQUENCE ),
		      asn1_wrap ( builder, ASN1_SEQUENCE ),
		      asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n",
		       ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
		return rc;
	}
	DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n",
		ocsp, x509_name ( ocsp->cert ) );
	DBGC2_HDA ( ocsp, 0, builder->data, builder->len );

	/* Parse certificate ID for comparison with response */
	cert_id_tail->data = builder->data;
	cert_id_tail->len = builder->len;
	if ( ( rc = ( asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
		      asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
		      asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
		      asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
		      asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
		      asn1_skip ( cert_id_tail, ASN1_SEQUENCE ) ) ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n",
		       ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
		return rc;
	}

	return 0;
}
Example #3
0
/**
 * Identify X.509 certificate public key
 *
 * @v certificate	Certificate
 * @v algorithm		Public key algorithm to fill in
 * @v pubkey		Public key value to fill in
 * @ret rc		Return status code
 */
static int x509_public_key ( const struct asn1_cursor *certificate,
			     struct asn1_cursor *algorithm,
			     struct asn1_cursor *pubkey ) {
	struct asn1_cursor cursor;
	int rc;

	/* Locate subjectPublicKeyInfo */
	memcpy ( &cursor, certificate, sizeof ( cursor ) );
	rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
	       asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
	       asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
	       asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */
	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */
	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */
	       asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/);
	if ( rc != 0 ) {
		DBG ( "Cannot locate subjectPublicKeyInfo in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return rc;
	}

	/* Locate algorithm */
	memcpy ( algorithm, &cursor, sizeof ( *algorithm ) );
	rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate algorithm in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return rc;
	}

	/* Locate subjectPublicKey */
	memcpy ( pubkey, &cursor, sizeof ( *pubkey ) );
	rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */
	       asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate subjectPublicKey in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return rc;
	}

	return 0;
}
Example #4
0
/**
 * Identify X.509 certificate RSA modulus and public exponent
 *
 * @v certificate	Certificate
 * @v rsa		RSA public key to fill in
 * @ret rc		Return status code
 *
 * The caller is responsible for eventually calling
 * x509_free_rsa_public_key() to free the storage allocated to hold
 * the RSA modulus and exponent.
 */
int x509_rsa_public_key ( const struct asn1_cursor *certificate,
			  struct x509_rsa_public_key *rsa_pubkey ) {
	struct asn1_cursor algorithm;
	struct asn1_cursor pubkey;
	struct asn1_cursor modulus;
	struct asn1_cursor exponent;
	int rc;

	/* First, extract the public key algorithm and key data */
	if ( ( rc = x509_public_key ( certificate, &algorithm,
				      &pubkey ) ) != 0 )
		return rc;

	/* Check that algorithm is RSA */
	rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate algorithm:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
	return rc;
	}
	if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) ||
	     ( memcmp ( algorithm.data, &oid_rsa_encryption,
			sizeof ( oid_rsa_encryption ) ) != 0 ) ) {
		DBG ( "algorithm is not rsaEncryption in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return -ENOTSUP;
	}

	/* Check that public key is a byte string, i.e. that the
	 * "unused bits" byte contains zero.
	 */
	if ( ( pubkey.len < 1 ) ||
	     ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) {
		DBG ( "subjectPublicKey is not a byte string in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return -ENOTSUP;
	}
	pubkey.data++;
	pubkey.len--;

	/* Pick out the modulus and exponent */
	rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate RSAPublicKey in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return -ENOTSUP;
	}
	memcpy ( &modulus, &pubkey, sizeof ( modulus ) );
	rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate modulus in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return -ENOTSUP;
	}
	if ( modulus.len && ( ! *( ( uint8_t * ) modulus.data ) ) ) {
		/* Skip positive sign byte */
		modulus.data++;
		modulus.len--;
	}
	memcpy ( &exponent, &pubkey, sizeof ( exponent ) );
	rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */
	       asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ );
	if ( rc != 0 ) {
		DBG ( "Cannot locate publicExponent in:\n" );
		DBG_HDA ( 0, certificate->data, certificate->len );
		return -ENOTSUP;
	}
	if ( exponent.len && ( ! *( ( uint8_t * ) exponent.data ) ) ) {
		/* Skip positive sign byte */
		exponent.data++;
		exponent.len--;
	}

	/* Allocate space and copy out modulus and exponent */
	rsa_pubkey->modulus = malloc ( modulus.len + exponent.len );
	if ( ! rsa_pubkey->modulus )
		return -ENOMEM;
	rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len );
	memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len );
	rsa_pubkey->modulus_len = modulus.len;
	memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len );
	rsa_pubkey->exponent_len = exponent.len;

	DBG2 ( "RSA modulus:\n" );
	DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len );
	DBG2 ( "RSA exponent:\n" );
	DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len );

	return 0;
}