FreeBSD/sys/geom/eli/g_eli_integrity.c
/*
 * The function is called after we read and decrypt data.
 *
 * g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> G_ELI_AUTH_READ_DONE -> g_io_deliver
 */
The function is called after we read and decrypt data.
The function is called after we read and decrypt data .
static int
g_eli_auth_read_done(struct cryptop *crp)
{
	struct g_eli_softc *sc;
	struct bio *bp;
	if (crp->crp_etype == EAGAIN) {
		if (g_eli_crypto_rerun(crp) == 0)
			return (0);
	}
	bp = (struct bio *)crp->crp_opaque;
	bp->bio_inbed++;
	if (crp->crp_etype == 0) {
		bp->bio_completed += crp->crp_olen;
		G_ELI_DEBUG(3, "Crypto READ request done (%d/%d) (add=%jd completed=%jd).",
		    bp->bio_inbed, bp->bio_children, (intmax_t)crp->crp_olen, (intmax_t)bp->bio_completed);
	} else {
		G_ELI_DEBUG(1, "Crypto READ request failed (%d/%d) error=%d.",
		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
		if (bp->bio_error == 0)
			bp->bio_error = crp->crp_etype;
	}
	sc = bp->bio_to->geom->softc;
	g_eli_key_drop(sc, crp->crp_desc->crd_next->crd_key);
	if (bp->bio_inbed < bp->bio_children)
		return (0);
	if (bp->bio_error == 0) {
		u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
		u_char *srcdata, *dstdata, *auth;
		off_t coroff, corsize;
		decr_secsize = bp->bio_to->sectorsize;
		encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
		data_secsize = sc->sc_data_per_sector;
		nsec = bp->bio_length / decr_secsize;
		nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
		lsec = sc->sc_bytes_per_sector / encr_secsize;
		srcdata = bp->bio_driver2;
		dstdata = bp->bio_data;
		auth = srcdata + encr_secsize * nsec;
		coroff = -1;
		corsize = 0;
		for (i = 1; i <= nsec; i++) {
			data_secsize = sc->sc_data_per_sector;
			if ((i % lsec) == 0)
				data_secsize = decr_secsize % data_secsize;
			if (bcmp(srcdata, auth, sc->sc_alen) != 0) {
				if (bp->bio_error == 0)
					bp->bio_error = -1;
				if (coroff == -1) {
					coroff = bp->bio_offset +
					    (dstdata - (u_char *)bp->bio_data);
				}
				corsize += data_secsize;
			} else {
				if (coroff != -1) {
					G_ELI_DEBUG(0, "%s: Failed to authenticate %jd "
					    "bytes of data at offset %jd.",
					    sc->sc_name, (intmax_t)corsize,
					    (intmax_t)coroff);
					coroff = -1;
					corsize = 0;
				}
				bcopy(srcdata + sc->sc_alen, dstdata,
				    data_secsize);
			}
			srcdata += encr_secsize;
			dstdata += data_secsize;
			auth += sc->sc_alen;
		}
		if (coroff != -1) {
			G_ELI_DEBUG(0, "%s: Failed to authenticate %jd "
			    "bytes of data at offset %jd.",
			    sc->sc_name, (intmax_t)corsize, (intmax_t)coroff);
		}
	}
	free(bp->bio_driver2, M_ELI);
	bp->bio_driver2 = NULL;
	if (bp->bio_error != 0) {
		if (bp->bio_error == -1)
			bp->bio_error = EINVAL;
		else {
			G_ELI_LOGREQ(0, bp,
			    "Crypto READ request failed (error=%d).",
			    bp->bio_error);
		}
		bp->bio_completed = 0;
	}
	g_io_deliver(bp, bp->bio_error);
	atomic_subtract_int(&sc->sc_inflight, 1);
	return (0);
}
static int g_eli_auth_read_done ( struct cryptop * crp ) { struct g_eli_softc * sc ; struct bio * bp ; if ( crp -> crp_etype == EAGAIN ) { if ( g_eli_crypto_rerun ( crp ) == 0 ) return ( 0 ) ; } bp = ( struct bio * ) crp -> crp_opaque ; bp -> bio_inbed ++ ; if ( crp -> crp_etype == 0 ) { bp -> bio_completed += crp -> crp_olen ; G_ELI_DEBUG ( 3 , " " , bp -> bio_inbed , bp -> bio_children , ( intmax_t ) crp -> crp_olen , ( intmax_t ) bp -> bio_completed ) ; } else { G_ELI_DEBUG ( 1 , " " , bp -> bio_inbed , bp -> bio_children , crp -> crp_etype ) ; if ( bp -> bio_error == 0 ) bp -> bio_error = crp -> crp_etype ; } sc = bp -> bio_to -> geom -> softc ; g_eli_key_drop ( sc , crp -> crp_desc -> crd_next -> crd_key ) ; if ( bp -> bio_inbed < bp -> bio_children ) return ( 0 ) ; if ( bp -> bio_error == 0 ) { u_int i , lsec , nsec , data_secsize , decr_secsize , encr_secsize ; u_char * srcdata , * dstdata , * auth ; off_t coroff , corsize ; decr_secsize = bp -> bio_to -> sectorsize ; encr_secsize = LIST_FIRST ( & sc -> sc_geom -> consumer ) -> provider -> sectorsize ; data_secsize = sc -> sc_data_per_sector ; nsec = bp -> bio_length / decr_secsize ; nsec = ( nsec * sc -> sc_bytes_per_sector ) / encr_secsize ; lsec = sc -> sc_bytes_per_sector / encr_secsize ; srcdata = bp -> bio_driver2 ; dstdata = bp -> bio_data ; auth = srcdata + encr_secsize * nsec ; coroff = -1 ; corsize = 0 ; for ( i = 1 ; i <= nsec ; i ++ ) { data_secsize = sc -> sc_data_per_sector ; if ( ( i % lsec ) == 0 ) data_secsize = decr_secsize % data_secsize ; if ( bcmp ( srcdata , auth , sc -> sc_alen ) != 0 ) { if ( bp -> bio_error == 0 ) bp -> bio_error = -1 ; if ( coroff == -1 ) { coroff = bp -> bio_offset + ( dstdata - ( u_char * ) bp -> bio_data ) ; } corsize += data_secsize ; } else { if ( coroff != -1 ) { G_ELI_DEBUG ( 0 , " " " " , sc -> sc_name , ( intmax_t ) corsize , ( intmax_t ) coroff ) ; coroff = -1 ; corsize = 0 ; } bcopy ( srcdata + sc -> sc_alen , dstdata , data_secsize ) ; } srcdata += encr_secsize ; dstdata += data_secsize ; auth += sc -> sc_alen ; } if ( coroff != -1 ) { G_ELI_DEBUG ( 0 , " " " " , sc -> sc_name , ( intmax_t ) corsize , ( intmax_t ) coroff ) ; } } free ( bp -> bio_driver2 , M_ELI ) ; bp -> bio_driver2 = NULL ; if ( bp -> bio_error != 0 ) { if ( bp -> bio_error == -1 ) bp -> bio_error = EINVAL ; else { G_ELI_LOGREQ ( 0 , bp , " " , bp -> bio_error ) ; } bp -> bio_completed = 0 ; } g_io_deliver ( bp , bp -> bio_error ) ; atomic_subtract_int ( & sc -> sc_inflight , 1 ) ; return ( 0 ) ; }
The function is called after we read and decrypt data.
The function is called after we read and decrypt data .
/*
	 * Do we have all sectors already?
	 */ /*
		 * Verify data integrity based on calculated and read HMACs.
		 */ /* Sectorsize of decrypted provider eg. 4096. */ /* The real sectorsize of encrypted provider, eg. 512. */ /* Number of data bytes in one encrypted sector, eg. 480. */ /* Number of sectors from decrypted provider, eg. 2. */ /* Number of sectors from encrypted provider, eg. 18. */ /* Last sector number in every big sector, eg. 9. */ /*
				 * Curruption detected, remember the offset if
				 * this is the first corrupted sector and
				 * increase size.
				 */ /*
				 * No curruption, good.
				 * Report previous corruption if there was one.
				 */ /* Report previous corruption if there was one. */ /*
	 * Read is finished, send it up.
	 */