コード例 #1
0
ファイル: intelxlvf.c プロジェクト: eworm-de/ipxe
/**
 * Handle virtual function event
 *
 * @v netdev		Network device
 * @v evt		Admin queue event descriptor
 * @v buf		Admin queue event data buffer
 */
void intelxlvf_admin_event ( struct net_device *netdev,
			     struct intelxl_admin_descriptor *evt,
			     union intelxl_admin_buffer *buf ) {
	struct intelxl_nic *intelxl = netdev->priv;
	unsigned int vopcode = le32_to_cpu ( evt->vopcode );

	/* Record command response if applicable */
	if ( vopcode == intelxl->vopcode ) {
		memcpy ( &intelxl->vbuf, buf, sizeof ( intelxl->vbuf ) );
		intelxl->vopcode = 0;
		intelxl->vret = le32_to_cpu ( evt->vret );
		if ( intelxl->vret != 0 ) {
			DBGC ( intelxl, "INTELXL %p admin VF command %#x "
			       "error %d\n", intelxl, vopcode, intelxl->vret );
			DBGC_HDA ( intelxl, virt_to_bus ( evt ), evt,
				   sizeof ( *evt ) );
			DBGC_HDA ( intelxl, virt_to_bus ( buf ), buf,
				   le16_to_cpu ( evt->len ) );
		}
		return;
	}

	/* Handle unsolicited events */
	switch ( vopcode ) {
	case INTELXL_ADMIN_VF_STATUS:
		intelxlvf_admin_status ( netdev, &buf->stat );
		break;
	default:
		DBGC ( intelxl, "INTELXL %p unrecognised VF event %#x:\n",
		       intelxl, vopcode );
		DBGC_HDA ( intelxl, 0, evt, sizeof ( *evt ) );
		DBGC_HDA ( intelxl, 0, buf, le16_to_cpu ( evt->len ) );
		break;
	}
}
コード例 #2
0
ファイル: ocsp.c プロジェクト: 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;
}
コード例 #3
0
ファイル: ntlm_test.c プロジェクト: antoinemiquel/ipxe
/**
 * Report NTLM variable-length data test result
 *
 * @v msg		Message header
 * @v msg_len		Length of message
 * @v data		Variable-length data descriptor
 * @v expected		Expected message header
 * @v expected_data	Expected variable-length data descriptor
 * @v field		Field name
 * @v file		Test code file
 * @v line		Test code line
 */
static void ntlm_data_okx ( struct ntlm_header *msg, size_t msg_len,
			    struct ntlm_data *data,
			    struct ntlm_header *expected,
			    struct ntlm_data *expected_data,
			    const char *field, const char *file,
			    unsigned int line ) {
	size_t offset;
	size_t len;
	void *raw;
	void *expected_raw;

	/* Verify data lies within message */
	okx ( data->len == data->max_len, file, line );
	offset = le32_to_cpu ( data->offset );
	len = le16_to_cpu ( data->len );
	okx ( offset <= msg_len, file, line );
	okx ( len <= ( msg_len - offset ), file, line );

	/* Verify content matches expected content */
	raw = ( ( ( void * ) msg ) + offset );
	expected_raw = ( ( ( void * ) expected ) +
			 le32_to_cpu ( expected_data->offset ) );
	DBGC ( msg, "NTLM %s expected:\n", field );
	DBGC_HDA ( msg, 0, expected_raw, le16_to_cpu ( expected_data->len ) );
	DBGC ( msg, "NTLM %s actual:\n", field );
	DBGC_HDA ( msg, 0, raw, len );
	okx ( data->len == expected_data->len, file, line );
	okx ( memcmp ( raw, expected_raw, len ) == 0, file, line );
}
コード例 #4
0
/**
 * Update the HMAC_DRBG key
 *
 * @v hash		Underlying hash algorithm
 * @v state		HMAC_DRBG internal state
 * @v data		Provided data
 * @v len		Length of provided data
 * @v single		Single byte used in concatenation
 *
 * This function carries out the operation
 *
 *     K = HMAC ( K, V || single || provided_data )
 *
 * as used by hmac_drbg_update()
 */
static void hmac_drbg_update_key ( struct digest_algorithm *hash,
				   struct hmac_drbg_state *state,
				   const void *data, size_t len,
				   const uint8_t single ) {
	uint8_t context[ hash->ctxsize ];
	size_t out_len = hash->digestsize;

	DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state );
	DBGC_HDA ( state, 0, data, len );

	/* Sanity checks */
	assert ( hash != NULL );
	assert ( state != NULL );
	assert ( ( data != NULL ) || ( len == 0 ) );
	assert ( ( single == 0x00 ) || ( single == 0x01 ) );

	/* K = HMAC ( K, V || single || provided_data ) */
	hmac_init ( hash, context, state->key, &out_len );
	assert ( out_len == hash->digestsize );
	hmac_update ( hash, context, state->value, out_len );
	hmac_update ( hash, context, &single, sizeof ( single ) );
	hmac_update ( hash, context, data, len );
	hmac_final ( hash, context, state->key, &out_len, state->key );
	assert ( out_len == hash->digestsize );

	DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || "
	       "provided_data ) :\n", hash->name, state, single );
	DBGC_HDA ( state, 0, state->key, out_len );
}
コード例 #5
0
ファイル: acm.c プロジェクト: dell-asm-ci/ipxe
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void acm_intr_complete ( struct usb_endpoint *ep,
				struct io_buffer *iobuf, int rc ) {
	struct acm_device *acm = container_of ( ep, struct acm_device,
						usbnet.intr );
	struct rndis_device *rndis = acm->rndis;
	struct usb_setup_packet *message;

	/* Profile completions */
	profile_start ( &acm_intr_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto ignore;

	/* Drop packets with errors */
	if ( rc != 0 ) {
		DBGC ( acm, "ACM %p interrupt failed: %s\n",
		       acm, strerror ( rc ) );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		goto error;
	}

	/* Extract message header */
	if ( iob_len ( iobuf ) < sizeof ( *message ) ) {
		DBGC ( acm, "ACM %p underlength interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto error;
	}
	message = iobuf->data;

	/* Parse message header */
	switch ( message->request ) {

	case cpu_to_le16 ( CDC_RESPONSE_AVAILABLE ) :
	case cpu_to_le16 ( 0x0001 ) : /* qemu seems to use this value */
		acm->responded = 1;
		break;

	default:
		DBGC ( acm, "ACM %p unrecognised interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -ENOTSUP;
		goto error;
	}

	/* Free I/O buffer */
	free_iob ( iobuf );
	profile_stop ( &acm_intr_profiler );

	return;

 error:
	rndis_rx_err ( rndis, iob_disown ( iobuf ), rc );
 ignore:
	free_iob ( iobuf );
	return;
}
コード例 #6
0
ファイル: smsc95xx.c プロジェクト: Heyvaert/ipxe-1
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_in_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.in );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_rx_header *header;

	/* Profile completions */
	profile_start ( &smsc95xx_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p bulk IN failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p underlength bulk IN\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check for errors */
	if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT |
					     SMSC95XX_RX_LATE |
					     SMSC95XX_RX_CRC ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p receive error (%08x):\n",
		       smsc95xx, le32_to_cpu ( header->command ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );

	profile_stop ( &smsc95xx_in_profiler );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
コード例 #7
0
ファイル: dm96xx.c プロジェクト: dell-asm-ci/ipxe
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_in_complete ( struct usb_endpoint *ep,
				 struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.in );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_rx_header *header;

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
		       dm96xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check status */
	if ( header->rsr & ~DM96XX_RSR_MF ) {
		DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
		       dm96xx, header->rsr );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
コード例 #8
0
/**
 * Reseed HMAC_DRBG
 *
 * @v hash		Underlying hash algorithm
 * @v state		HMAC_DRBG internal state
 * @v entropy		Entropy input
 * @v entropy_len	Length of entropy input
 * @v additional	Additional input
 * @v additional_len	Length of additional input
 *
 * This is the HMAC_DRBG_Reseed_algorithm function defined in ANS X9.82
 * Part 3-2007 Section 10.2.2.2.4 (NIST SP 800-90 Section 10.1.2.4).
 *
 * The key, value and reseed counter are updated in-place within the
 * HMAC_DRBG internal state.
 */
void hmac_drbg_reseed ( struct digest_algorithm *hash,
			struct hmac_drbg_state *state,
			const void *entropy, size_t entropy_len,
			const void *additional, size_t additional_len ) {
	uint8_t seed_material[ entropy_len + additional_len ];

	DBGC ( state, "HMAC_DRBG_%s %p (re)seed\n", hash->name, state );

	/* Sanity checks */
	assert ( hash != NULL );
	assert ( state != NULL );
	assert ( entropy != NULL );
	assert ( ( additional != NULL ) || ( additional_len == 0 ) );

	/* 1.  seed_material = entropy_input || additional_input */
	memcpy ( seed_material, entropy, entropy_len );
	memcpy ( ( seed_material + entropy_len ), additional, additional_len );
	DBGC ( state, "HMAC_DRBG_%s %p seed material :\n", hash->name, state );
	DBGC_HDA ( state, 0, seed_material, sizeof ( seed_material ) );

	/* 2.  ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) */
	hmac_drbg_update ( hash, state, seed_material,
			   sizeof ( seed_material ) );

	/* 3.  reseed_counter = 1 */
	state->reseed_counter = 1;

	/* 4.  Return V, Key and reseed_counter as the new_working_state */
}
コード例 #9
0
/**
 * Identify autoboot device
 *
 */
void efi_set_autoboot ( void ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	union {
		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
		void *interface;
	} snp;
	EFI_SIMPLE_NETWORK_MODE *mode;
	EFI_STATUS efirc;

	/* Look for an SNP instance on the image's device handle */
	if ( ( efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
					  &efi_simple_network_protocol_guid,
					  &snp.interface, efi_image_handle,
					  NULL,
					  EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
		DBGC ( efi_loaded_image, "EFI found no autoboot device\n" );
		return;
	}

	/* Record autoboot device */
	mode = snp.snp->Mode;
	set_autoboot_ll_addr ( &mode->CurrentAddress, mode->HwAddressSize );
	DBGC ( efi_loaded_image, "EFI found autoboot link-layer address:\n" );
	DBGC_HDA ( efi_loaded_image, 0, &mode->CurrentAddress,
		   mode->HwAddressSize );

	/* Close protocol */
	bs->CloseProtocol ( efi_loaded_image->DeviceHandle,
			    &efi_simple_network_protocol_guid,
			    efi_image_handle, NULL );
}
コード例 #10
0
ファイル: sbft.c プロジェクト: 1stMaster/syslinux
/**
 * Fill in all variable portions of sBFT
 *
 * @v srp		SRP device
 * @ret rc		Return status code
 */
int sbft_fill_data ( struct srp_device *srp ) {
	struct sbft_scsi_subtable *sbft_scsi = &sbftab.scsi;
	struct sbft_srp_subtable *sbft_srp = &sbftab.srp;
	struct sbft_ib_subtable *sbft_ib = &sbftab.ib;
	struct ib_srp_parameters *ib_params;
	struct segoff rm_sbftab = {
		.segment = rm_ds,
		.offset = __from_data16 ( &sbftab ),
	};

	/* Fill in the SCSI subtable */
	memcpy ( &sbft_scsi->lun, &srp->lun, sizeof ( sbft_scsi->lun ) );

	/* Fill in the SRP subtable */
	memcpy ( &sbft_srp->port_ids, &srp->port_ids,
		 sizeof ( sbft_srp->port_ids ) );

	/* Fill in the IB subtable */
	assert ( srp->transport == &ib_srp_transport );
	ib_params = ib_srp_params ( srp );
	memcpy ( &sbft_ib->sgid, &ib_params->sgid, sizeof ( sbft_ib->sgid ) );
	memcpy ( &sbft_ib->dgid, &ib_params->dgid, sizeof ( sbft_ib->dgid ) );
	memcpy ( &sbft_ib->service_id, &ib_params->service_id,
		 sizeof ( sbft_ib->service_id ) );
	sbft_ib->pkey = ib_params->pkey;

	/* Update checksum */
	acpi_fix_checksum ( &sbftab.table.acpi );

	DBGC ( &sbftab, "SRP Boot Firmware Table at %04x:%04x:\n",
	       rm_sbftab.segment, rm_sbftab.offset );
	DBGC_HDA ( &sbftab, rm_sbftab, &sbftab, sizeof ( sbftab ) );

	return 0;
}
コード例 #11
0
ファイル: intelxvf.c プロジェクト: antoinemiquel/ipxe
/**
 * Get queue configuration
 *
 * @v intel		Intel device
 * @v vlan_thing	VLAN hand-waving thing to fill in
 * @ret rc		Return status code
 */
static int intelxvf_mbox_queues ( struct intel_nic *intel, int *vlan_thing ) {
	union intelvf_msg msg;
	int rc;

	/* Send queue configuration message */
	memset ( &msg, 0, sizeof ( msg ) );
	msg.hdr = INTELVF_MSG_TYPE_GET_QUEUES;
	if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
		DBGC ( intel, "INTEL %p get queue configuration failed: %s\n",
		       intel, strerror ( rc ) );
		return rc;
	}

	/* Check response */
	if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) !=INTELVF_MSG_TYPE_GET_QUEUES){
		DBGC ( intel, "INTEL %p get queue configuration unexpected "
		       "response:\n", intel );
		DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
		return -EPROTO;
	}

	/* Check that we were allowed to get the queue configuration */
	if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
		DBGC ( intel, "INTEL %p get queue configuration refused\n",
		       intel );
		return -EPERM;
	}

	/* Extract VLAN hand-waving thing */
	*vlan_thing = msg.queues.vlan_thing;

	return 0;
}
コード例 #12
0
ファイル: intelxvf.c プロジェクト: antoinemiquel/ipxe
/**
 * Send negotiate API version message
 *
 * @v intel		Intel device
 * @v version		Requested version
 * @ret rc		Return status code
 */
static int intelxvf_mbox_version ( struct intel_nic *intel,
				   unsigned int version ) {
	union intelvf_msg msg;
	int rc;

	/* Send set MTU message */
	memset ( &msg, 0, sizeof ( msg ) );
	msg.hdr = INTELXVF_MSG_TYPE_VERSION;
	msg.version.version = version;
	if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
		DBGC ( intel, "INTEL %p negotiate API version failed: %s\n",
		       intel, strerror ( rc ) );
		return rc;
	}

	/* Check response */
	if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELXVF_MSG_TYPE_VERSION ){
		DBGC ( intel, "INTEL %p negotiate API version unexpected "
		       "response:\n", intel );
		DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
		return -EPROTO;
	}

	/* Check that this version is supported */
	if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
		DBGC ( intel, "INTEL %p negotiate API version failed\n",
		       intel );
		return -EPERM;
	}

	return 0;
}
コード例 #13
0
ファイル: ocsp.c プロジェクト: eworm-de/ipxe
/**
 * Parse OCSP response status
 *
 * @v ocsp		OCSP check
 * @v raw		ASN.1 cursor
 * @ret rc		Return status code
 */
static int ocsp_parse_response_status ( struct ocsp_check *ocsp,
					const struct asn1_cursor *raw ) {
	struct asn1_cursor cursor;
	uint8_t status;
	int rc;

	/* Enter responseStatus */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
		       "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
		return rc;
	}

	/* Extract response status */
	if ( cursor.len != sizeof ( status ) ) {
		DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
		       ocsp, x509_name ( ocsp->cert ) );
		DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
		return -EINVAL;
	}
	memcpy ( &status, cursor.data, sizeof ( status ) );

	/* Check response status */
	if ( status != OCSP_STATUS_SUCCESSFUL ) {
		DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
		       ocsp, x509_name ( ocsp->cert ), status );
		return EPROTO_STATUS ( status );
	}

	return 0;
}
コード例 #14
0
ファイル: ocsp.c プロジェクト: Heyvaert/ipxe-1
/**
 * 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;

	/* Check certID matches request */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	asn1_shrink_any ( &cursor );
	if ( asn1_compare ( &cursor, &ocsp->request.cert_id ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
		       ocsp, x509_name ( ocsp->cert ) );
		DBGC_HDA ( ocsp, 0, ocsp->request.cert_id.data,
			   ocsp->request.cert_id.len );
		DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
		return -EACCES_CERT_MISMATCH;
	}

	return 0;
}
コード例 #15
0
ファイル: smsc95xx.c プロジェクト: Heyvaert/ipxe-1
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_intr_complete ( struct usb_endpoint *ep,
				     struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.intr );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_interrupt *intr;

	/* Profile completions */
	profile_start ( &smsc95xx_intr_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto done;

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p interrupt failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}

	/* Extract interrupt data */
	if ( iob_len ( iobuf ) != sizeof ( *intr ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p malformed interrupt\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}
	intr = iobuf->data;

	/* Record interrupt status */
	smsc95xx->int_sts = le32_to_cpu ( intr->int_sts );
	profile_stop ( &smsc95xx_intr_profiler );

 done:
	/* Free I/O buffer */
	free_iob ( iobuf );
}
コード例 #16
0
ファイル: ocsp.c プロジェクト: eworm-de/ipxe
/**
 * Parse OCSP certificates
 *
 * @v ocsp		OCSP check
 * @v raw		ASN.1 cursor
 * @ret rc		Return status code
 */
static int ocsp_parse_certs ( struct ocsp_check *ocsp,
			      const struct asn1_cursor *raw ) {
	struct ocsp_response *response = &ocsp->response;
	struct asn1_cursor cursor;
	struct x509_certificate *cert;
	int rc;

	/* Enter certs */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
	asn1_enter ( &cursor, ASN1_SEQUENCE );

	/* Parse certificate, if present.  The data structure permits
	 * multiple certificates, but the protocol requires that the
	 * OCSP signing certificate must either be the issuer itself,
	 * or must be directly issued by the issuer (see RFC2560
	 * section 4.2.2.2 "Authorized Responders").  We therefore
	 * need to identify only the single certificate matching the
	 * Responder ID.
	 */
	while ( cursor.len ) {

		/* Parse certificate */
		if ( ( rc = x509_certificate ( cursor.data, cursor.len,
					       &cert ) ) != 0 ) {
			DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
			       "certificate: %s\n", ocsp,
			       x509_name ( ocsp->cert ), strerror ( rc ) );
			DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
			return rc;
		}

		/* Use if this certificate matches the responder ID */
		if ( response->responder.compare ( ocsp, cert ) == 0 ) {
			response->signer = cert;
			DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by ",
				ocsp, x509_name ( ocsp->cert ) );
			DBGC2 ( ocsp, "\"%s\"\n",
				x509_name ( response->signer ) );
			return 0;
		}

		/* Otherwise, discard this certificate */
		x509_put ( cert );
		asn1_skip_any ( &cursor );
	}

	DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n",
	       ocsp, x509_name ( ocsp->cert ) );
	return -EACCES_NO_RESPONDER;
}
コード例 #17
0
ファイル: dm96xx.c プロジェクト: dell-asm-ci/ipxe
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_intr_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.intr );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_interrupt *intr;
	size_t len = iob_len ( iobuf );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto done;

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p interrupt failed: %s\n",
		       dm96xx, strerror ( rc ) );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}

	/* Extract message header */
	if ( len < sizeof ( *intr ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength interrupt:\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, -EINVAL );
		goto done;
	}
	intr = iobuf->data;

	/* Update link status */
	dm96xx_link_nsr ( dm96xx, intr->nsr );

 done:
	/* Free I/O buffer */
	free_iob ( iobuf );
}
コード例 #18
0
ファイル: srp.c プロジェクト: 1stMaster/syslinux
/**
 * Handle SRP SCSI response
 *
 * @v srp		SRP device
 * @v iobuf		I/O buffer
 * @ret rc		Returns status code
 */
static int srp_rsp ( struct srp_device *srp, struct io_buffer *iobuf ) {
	struct srp_rsp *rsp = iobuf->data;
	int rc;

	DBGC2 ( srp, "SRP %p RX SCSI response tag %08x%08x\n", srp,
		ntohl ( rsp->tag.dwords[0] ), ntohl ( rsp->tag.dwords[1] ) );

	/* Sanity check */
	if ( iob_len ( iobuf ) < sizeof ( *rsp ) ) {
		DBGC ( srp, "SRP %p RX SCSI response too short (%zd bytes)\n",
		       srp, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto out;
	}

	/* Report SCSI errors */
	if ( rsp->status != 0 ) {
		DBGC ( srp, "SRP %p response status %02x\n",
		       srp, rsp->status );
		if ( srp_rsp_sense_data ( rsp ) ) {
			DBGC ( srp, "SRP %p sense data:\n", srp );
			DBGC_HDA ( srp, 0, srp_rsp_sense_data ( rsp ),
				   srp_rsp_sense_data_len ( rsp ) );
		}
	}
	if ( rsp->valid & ( SRP_RSP_VALID_DOUNDER | SRP_RSP_VALID_DOOVER ) ) {
		DBGC ( srp, "SRP %p response data-out %srun by %#x bytes\n",
		       srp, ( ( rsp->valid & SRP_RSP_VALID_DOUNDER )
			      ? "under" : "over" ),
		       ntohl ( rsp->data_out_residual_count ) );
	}
	if ( rsp->valid & ( SRP_RSP_VALID_DIUNDER | SRP_RSP_VALID_DIOVER ) ) {
		DBGC ( srp, "SRP %p response data-in %srun by %#x bytes\n",
		       srp, ( ( rsp->valid & SRP_RSP_VALID_DIUNDER )
			      ? "under" : "over" ),
		       ntohl ( rsp->data_in_residual_count ) );
	}
	srp->command->status = rsp->status;

	/* Mark SCSI command as complete */
	srp_scsi_done ( srp, 0 );

	rc = 0;
 out:
	free_iob ( iobuf );
	return rc;
}
コード例 #19
0
ファイル: acm.c プロジェクト: dell-asm-ci/ipxe
/**
 * Receive control packet
 *
 * @v acm		USB RNDIS device
 * @ret rc		Return status code
 */
static int acm_control_receive ( struct acm_device *acm ) {
	struct rndis_device *rndis = acm->rndis;
	struct usb_device *usb = acm->usb;
	struct io_buffer *iobuf;
	struct rndis_header *header;
	size_t mtu = ACM_RESPONSE_MTU;
	size_t len;
	int rc;

	/* Allocate I/O buffer */
	iobuf = alloc_iob ( mtu );
	if ( ! iobuf ) {
		rc = -ENOMEM;
		goto err_alloc;
	}

	/* Get encapsulated response */
	if ( ( rc = cdc_get_encapsulated_response ( usb, acm->usbnet.comms,
						    iobuf->data, mtu ) ) != 0 ){
		DBGC ( acm, "ACM %p could not get encapsulated response: %s\n",
		       acm, strerror ( rc ) );
		goto err_get_response;
	}

	/* Fix up buffer length */
	header = iobuf->data;
	len = le32_to_cpu ( header->len );
	if ( len > mtu ) {
		DBGC ( acm, "ACM %p overlength encapsulated response\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, mtu );
		rc = -EPROTO;
		goto err_len;
	}
	iob_put ( iobuf, len );

	/* Hand off to RNDIS */
	rndis_rx ( rndis, iob_disown ( iobuf ) );

	return 0;

 err_len:
 err_get_response:
	free_iob ( iobuf );
 err_alloc:
	return rc;
}
コード例 #20
0
ファイル: intelxlvf.c プロジェクト: eworm-de/ipxe
/**
 * Handle status change event
 *
 * @v netdev		Network device
 * @v stat		Status change event
 */
static void
intelxlvf_admin_status ( struct net_device *netdev,
			 struct intelxl_admin_vf_status_buffer *stat ) {
	struct intelxl_nic *intelxl = netdev->priv;

	/* Handle event */
	switch ( stat->event ) {
	case cpu_to_le32 ( INTELXL_ADMIN_VF_STATUS_LINK ):
		intelxlvf_admin_link ( netdev, &stat->data.link );
		break;
	default:
		DBGC ( intelxl, "INTELXL %p unrecognised status change "
		       "event %#x:\n", intelxl, le32_to_cpu ( stat->event ) );
		DBGC_HDA ( intelxl, 0, stat, sizeof ( *stat ) );
		break;
	}
}
コード例 #21
0
ファイル: ocsp.c プロジェクト: eworm-de/ipxe
/**
 * Parse OCSP response type
 *
 * @v ocsp		OCSP check
 * @v raw		ASN.1 cursor
 * @ret rc		Return status code
 */
static int ocsp_parse_response_type ( struct ocsp_check *ocsp,
				      const struct asn1_cursor *raw ) {
	struct asn1_cursor cursor;

	/* Enter responseType */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	asn1_enter ( &cursor, ASN1_OID );

	/* Check responseType is "basic" */
	if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
		       ocsp, x509_name ( ocsp->cert ) );
		DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
		return -ENOTSUP_RESPONSE_TYPE;
	}

	return 0;
}
コード例 #22
0
/**
 * Update the HMAC_DRBG value
 *
 * @v hash		Underlying hash algorithm
 * @v state		HMAC_DRBG internal state
 * @v data		Provided data
 * @v len		Length of provided data
 * @v single		Single byte used in concatenation
 *
 * This function carries out the operation
 *
 *     V = HMAC ( K, V )
 *
 * as used by hmac_drbg_update() and hmac_drbg_generate()
 */
static void hmac_drbg_update_value ( struct digest_algorithm *hash,
				     struct hmac_drbg_state *state ) {
	uint8_t context[ hash->ctxsize ];
	size_t out_len = hash->digestsize;

	/* Sanity checks */
	assert ( hash != NULL );
	assert ( state != NULL );

	/* V = HMAC ( K, V ) */
	hmac_init ( hash, context, state->key, &out_len );
	assert ( out_len == hash->digestsize );
	hmac_update ( hash, context, state->value, out_len );
	hmac_final ( hash, context, state->key, &out_len, state->value );
	assert ( out_len == hash->digestsize );

	DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n",
	       hash->name, state );
	DBGC_HDA ( state, 0, state->value, out_len );
}
コード例 #23
0
ファイル: rootcert.c プロジェクト: Afterglow/ipxe
/**
 * Initialise root certificate
 *
 * The list of trusted root certificates can be specified at build
 * time using the TRUST= build parameter.  If no certificates are
 * specified, then the default iPXE root CA certificate is trusted.
 *
 * If no certificates were explicitly specified, then we allow the
 * list of trusted root certificate fingerprints to be overridden
 * using the "trust" setting, but only at the point of iPXE
 * initialisation.  This prevents untrusted sources of settings
 * (e.g. DHCP) from subverting the chain of trust, while allowing
 * trustworthy sources (e.g. VMware GuestInfo or non-volatile stored
 * options) to specify the trusted root certificate without requiring
 * a rebuild.
 */
static void rootcert_init ( void ) {
	void *external = NULL;
	int len;
	int rc;

	/* Allow trusted root certificates to be overridden only if
	 * not explicitly specified at build time.
	 */
	if ( ALLOW_TRUST_OVERRIDE ) {

		/* Fetch copy of "trust" setting, if it exists.  This
		 * memory will never be freed.
		 */
		len = fetch_setting_copy ( NULL, &trust_setting, &external );
		if ( len < 0 ) {
			rc = len;
			DBGC ( &root_certificates, "ROOTCERT cannot fetch "
			       "trusted root certificate fingerprints: %s\n",
			       strerror ( rc ) );
			/* No way to prevent startup; fail safe by
			 * trusting no certificates.
			 */
			root_certificates.count = 0;
			return;
		}

		/* Use certificates from "trust" setting, if present */
		if ( external ) {
			root_certificates.fingerprints = external;
			root_certificates.count = ( len / FINGERPRINT_LEN );
		}
	}

	DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n",
	       root_certificates.count, ( external ? "external" : "built-in" ));
	DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints,
		   ( root_certificates.count * FINGERPRINT_LEN ) );
}
コード例 #24
0
ファイル: acpi.c プロジェクト: sureshsundriyal/ipxe
/**
 * Locate ACPI table
 *
 * @v rsdt		ACPI root system description table
 * @v signature		Requested table signature
 * @v index		Requested index of table with this signature
 * @ret table		Table, or UNULL if not found
 */
userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
	struct acpi_header acpi;
	struct acpi_rsdt *rsdtab;
	typeof ( rsdtab->entry[0] ) entry;
	userptr_t table;
	size_t len;
	unsigned int count;
	unsigned int i;

	/* Read RSDT header */
	copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
	if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
		DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
		       user_to_phys ( rsdt, 0 ) );
		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
			   sizeof ( acpi ) );
		return UNULL;
	}
	len = le32_to_cpu ( acpi.length );
	if ( len < sizeof ( rsdtab->acpi ) ) {
		DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
		       user_to_phys ( rsdt, 0 ) );
		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
			   sizeof ( acpi ) );
		return UNULL;
	}

	/* Calculate number of entries */
	count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );

	/* Search through entries */
	for ( i = 0 ; i < count ; i++ ) {

		/* Get table address */
		copy_from_user ( &entry, rsdt,
				 offsetof ( typeof ( *rsdtab ), entry[i] ),
				 sizeof ( entry ) );

		/* Read table header */
		table = phys_to_user ( entry );
		copy_from_user ( &acpi.signature, table, 0,
				 sizeof ( acpi.signature ) );

		/* Check table signature */
		if ( acpi.signature != cpu_to_le32 ( signature ) )
			continue;

		/* Check index */
		if ( index-- )
			continue;

		DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
		       user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
		       user_to_phys ( table, 0 ) );
		return table;
	}

	DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
	return UNULL;
}
コード例 #25
0
ファイル: fcels.c プロジェクト: eatnumber1/ipxe
/**
 * Receive Fibre Channel ELS frame
 *
 * @v els		Fibre Channel ELS transaction
 * @v iobuf		I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
static int fc_els_rx ( struct fc_els *els,
                       struct io_buffer *iobuf,
                       struct xfer_metadata *meta ) {
    struct fc_els_frame_common *frame = iobuf->data;
    struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
    struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
    size_t len = iob_len ( iobuf );
    int rc;

    /* Sanity check */
    if ( len < sizeof ( *frame ) ) {
        DBGC ( els, FCELS_FMT " received underlength frame:\n",
               FCELS_ARGS ( els ) );
        DBGC_HDA ( els, 0, frame, len );
        rc = -EINVAL;
        goto done;
    }
    if ( ! src ) {
        DBGC ( els, FCELS_FMT " received frame missing source "
               "address:\n", FCELS_ARGS ( els ) );
        rc = -EINVAL;
        goto done;
    }
    if ( ! dest ) {
        DBGC ( els, FCELS_FMT " received frame missing destination "
               "address:\n", FCELS_ARGS ( els ) );
        rc = -EINVAL;
        goto done;
    }

    /* Check for rejection responses */
    if ( fc_els_is_request ( els ) &&
            ( frame->command != FC_ELS_LS_ACC ) ) {
        DBGC ( els, FCELS_FMT " rejected:\n", FCELS_ARGS ( els ) );
        DBGC_HDA ( els, 0, frame, len );
        rc = -EACCES;
        goto done;
    }

    /* Update port IDs */
    memcpy ( &els->port_id, &dest->sfc_port_id, sizeof ( els->port_id ) );
    memcpy ( &els->peer_port_id, &src->sfc_port_id,
             sizeof ( els->peer_port_id ) );

    /* Determine handler, if necessary */
    if ( ! els->handler )
        els->handler = fc_els_detect ( els, frame, len );
    if ( ! els->handler )
        els->handler = &fc_els_unknown_handler;

    DBGC2 ( els, FCELS_FMT " received:\n", FCELS_ARGS ( els ) );
    DBGC2_HDA ( els, 0, frame, len );

    /* Handle received frame */
    if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) {
        DBGC ( els, FCELS_FMT " could not handle received frame: "
               "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
        DBGC_HDA ( els, 0, frame, len );
        goto done;
    }

done:
    /* Free I/O buffer */
    free_iob ( iobuf );

    /* Close transaction */
    fc_els_close ( els, rc );

    return rc;
}
コード例 #26
0
ファイル: ocsp.c プロジェクト: eworm-de/ipxe
/**
 * Parse OCSP responses
 *
 * @v ocsp		OCSP check
 * @v raw		ASN.1 cursor
 * @ret rc		Return status code
 */
static int ocsp_parse_responses ( struct ocsp_check *ocsp,
				  const struct asn1_cursor *raw ) {
	struct ocsp_response *response = &ocsp->response;
	struct asn1_cursor cursor;
	int rc;

	/* Enter responses */
	memcpy ( &cursor, raw, sizeof ( cursor ) );
	asn1_enter ( &cursor, ASN1_SEQUENCE );

	/* Enter first singleResponse */
	asn1_enter ( &cursor, ASN1_SEQUENCE );

	/* Parse certID */
	if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 )
		return rc;
	asn1_skip_any ( &cursor );

	/* Check certStatus */
	if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) {
		DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n",
		       ocsp, x509_name ( ocsp->cert ) );
		DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
		return -EACCES_CERT_STATUS;
	}
	asn1_skip_any ( &cursor );

	/* Parse thisUpdate */
	if ( ( rc = asn1_generalized_time ( &cursor,
					    &response->this_update ) ) != 0 ) {
		DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n",
		       ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
		return rc;
	}
	DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n",
		ocsp, x509_name ( ocsp->cert ), response->this_update );
	asn1_skip_any ( &cursor );

	/* Parse nextUpdate, if present */
	if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
		asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
		if ( ( rc = asn1_generalized_time ( &cursor,
					     &response->next_update ) ) != 0 ) {
			DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
			       "nextUpdate: %s\n", ocsp,
			       x509_name ( ocsp->cert ), strerror ( rc ) );
			return rc;
		}
		DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n",
			ocsp, x509_name ( ocsp->cert ), response->next_update );
	} else {
		/* If no nextUpdate is present, this indicates that
		 * "newer revocation information is available all the
		 * time".  Actually, this indicates that there is no
		 * point to performing the OCSP check, since an
		 * attacker could replay the response at any future
		 * time and it would still be valid.
		 */
		DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n",
		       ocsp, x509_name ( ocsp->cert ) );
		response->next_update = time ( NULL );
	}

	return 0;
}
コード例 #27
0
/**
 * Generate pseudorandom bits using HMAC_DRBG
 *
 * @v hash		Underlying hash algorithm
 * @v state		HMAC_DRBG internal state
 * @v additional	Additional input
 * @v additional_len	Length of additional input
 * @v data		Output buffer
 * @v len		Length of output buffer
 * @ret rc		Return status code
 *
 * This is the HMAC_DRBG_Generate_algorithm function defined in ANS X9.82
 * Part 3-2007 Section 10.2.2.2.5 (NIST SP 800-90 Section 10.1.2.5).
 *
 * Requests must be for an integral number of bytes.
 *
 * The key, value and reseed counter are updated in-place within the
 * HMAC_DRBG internal state.
 *
 * Note that the only permitted error is "reseed required".
 */
int hmac_drbg_generate ( struct digest_algorithm *hash,
			 struct hmac_drbg_state *state,
			 const void *additional, size_t additional_len,
			 void *data, size_t len ) {
	size_t out_len = hash->digestsize;
	void *orig_data = data;
	size_t orig_len = len;
	size_t frag_len;

	DBGC ( state, "HMAC_DRBG_%s %p generate\n", hash->name, state );

	/* Sanity checks */
	assert ( hash != NULL );
	assert ( state != NULL );
	assert ( data != NULL );
	assert ( ( additional != NULL ) || ( additional_len == 0 ) );

	/* 1.  If reseed_counter > reseed_interval, then return an
	 *     indication that a reseed is required
	 */
	if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) {
		DBGC ( state, "HMAC_DRBG_%s %p reseed interval exceeded\n",
		       hash->name, state );
		return -ESTALE;
	}

	/* 2.  If additional_input != Null, then
	 *     ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V )
	 */
	if ( additional_len )
		hmac_drbg_update ( hash, state, additional, additional_len );

	/* 3.  temp = Null
	 * 4.  While ( len ( temp ) < requested_number_of_bits ) do:
	 */
	while ( len ) {

		/* 4.1  V = HMAC ( Key, V ) */
		hmac_drbg_update_value ( hash, state );

		/* 4.2.  temp = temp || V
		 * 5.    returned_bits = Leftmost requested_number_of_bits
		 *       of temp
		 */
		frag_len = len;
		if ( frag_len > out_len )
			frag_len = out_len;
		memcpy ( data, state->value, frag_len );
		data += frag_len;
		len -= frag_len;
	}

	/* 6.  ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */
	hmac_drbg_update ( hash, state, additional, additional_len );

	/* 7.  reseed_counter = reseed_counter + 1 */
	state->reseed_counter++;

	DBGC ( state, "HMAC_DRBG_%s %p generated :\n", hash->name, state );
	DBGC_HDA ( state, 0, orig_data, orig_len );

	/* 8.  Return SUCCESS, returned_bits, and the new values of
	 *     Key, V and reseed_counter as the new_working_state
	 */
	return 0;
}
コード例 #28
0
ファイル: hash_df.c プロジェクト: Heyvaert/ipxe-1
/**
 * Distribute entropy throughout a buffer
 *
 * @v hash		Underlying hash algorithm
 * @v input		Input data
 * @v input_len		Length of input data, in bytes
 * @v output		Output buffer
 * @v output_len	Length of output buffer, in bytes
 *
 * This is the Hash_df function defined in ANS X9.82 Part 3-2007
 * Section 10.5.2 (NIST SP 800-90 Section 10.4.1).
 *
 * The number of bits requested is implicit in the length of the
 * output buffer.  Requests must be for an integral number of bytes.
 *
 * The output buffer is filled incrementally with each iteration of
 * the central loop, rather than constructing an overall "temp" and
 * then taking the leftmost(no_of_bits_to_return) bits.
 *
 * There is no way for the Hash_df function to fail.  The returned
 * status SUCCESS is implicit.
 */
void hash_df ( struct digest_algorithm *hash, const void *input,
	       size_t input_len, void *output, size_t output_len ) {
	uint8_t context[hash->ctxsize];
	uint8_t digest[hash->digestsize];
	size_t frag_len;
	struct {
		uint8_t pad[3];
		uint8_t counter;
		uint32_t no_of_bits_to_return;
	} __attribute__ (( packed )) prefix;
	void *temp;
	size_t remaining;

	DBGC ( &hash_df, "HASH_DF input:\n" );
	DBGC_HDA ( &hash_df, 0, input, input_len );

	/* Sanity checks */
	assert ( input != NULL );
	assert ( output != NULL );

	/* 1.  temp = the Null string
	 * 2.  len = ceil ( no_of_bits_to_return / outlen )
	 *
	 * (Nothing to do.  We fill the output buffer incrementally,
	 * rather than constructing the complete "temp" in-memory.
	 * "len" is implicit in the number of iterations required to
	 * fill the output buffer, and so is not calculated
	 * explicitly.)
	 */

	/* 3.  counter = an 8-bit binary value representing the integer "1" */
	prefix.counter = 1;

	/* 4.  For i = 1 to len do */
	for ( temp = output, remaining = output_len ; remaining > 0 ; ) {

		/* Comment: in step 5.1 (sic), no_of_bits_to_return is
		 * used as a 32-bit string.
		 *
		 * 4.1  temp = temp || Hash ( counter || no_of_bits_to_return
		 *                            || input_string )
		 */
		prefix.no_of_bits_to_return = htonl ( output_len * 8 );
		digest_init ( hash, context );
		digest_update ( hash, context, &prefix.counter,
				( sizeof ( prefix ) -
				  offsetof ( typeof ( prefix ), counter ) ) );
		digest_update ( hash, context, input, input_len );
		digest_final ( hash, context, digest );

		/* 4.2  counter = counter + 1 */
		prefix.counter++;

		/* 5.    requested_bits = Leftmost ( no_of_bits_to_return )
		 *       of temp
		 *
		 * (We fill the output buffer incrementally.)
		 */
		frag_len = sizeof ( digest );
		if ( frag_len > remaining )
			frag_len = remaining;
		memcpy ( temp, digest, frag_len );
		temp += frag_len;
		remaining -= frag_len;
	}

	/* 6.  Return SUCCESS and requested_bits */
	DBGC ( &hash_df, "HASH_DF output:\n" );
	DBGC_HDA ( &hash_df, 0, output, output_len );
	return;
}