/* Initialize GCM mode */ void GCM_init(gcm* g,char *key,int niv,char *iv) { /* iv size niv is usually 12 bytes (96 bits). AES key is 16 bytes */ int i; uchar H[16]; for (i=0;i<16;i++) {H[i]=0; g->stateX[i]=0;} AES_init(&(g->a),ECB,key,iv); AES_ecb_encrypt(&(g->a),H); /* E(K,0) */ precompute(g,H); g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0; if (niv==12) { for (i=0;i<12;i++) g->a.f[i]=iv[i]; unpack((unsign32)1,(uchar *)&(g->a.f[12])); /* initialise IV */ for (i=0;i<16;i++) g->Y_0[i]=g->a.f[i]; } else { g->status=GCM_ACCEPTING_CIPHER; GCM_ghash(g,iv,niv); /* GHASH(H,0,IV) */ GCM_wrap(g); for (i=0;i<16;i++) {g->a.f[i]=g->stateX[i];g->Y_0[i]=g->a.f[i];g->stateX[i]=0;} g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0; } g->status=GCM_ACCEPTING_HEADER; }
void g_bde_crypt_delete(struct g_bde_work *wp) { struct g_bde_softc *sc; u_char *d; off_t o; u_char skey[G_BDE_SKEYLEN]; keyInstance ki; cipherInstance ci; sc = wp->softc; d = wp->sp->data; AES_init(&ci); /* * Do not unroll this loop! * Our zone may be significantly wider than the amount of random * bytes arc4rand likes to give in one reseeding, whereas our * sectorsize is far more likely to be in the same range. */ for (o = 0; o < wp->length; o += sc->sectorsize) { arc4rand(d, sc->sectorsize, 0); arc4rand(&skey, sizeof skey, 0); AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey); AES_encrypt(&ci, &ki, d, d, sc->sectorsize); d += sc->sectorsize; } /* * Having written a long random sequence to disk here, we want to * force a reseed, to avoid weakening the next time we use random * data for something important. */ arc4rand(&o, sizeof o, 1); }
void g_bde_crypt_write(struct g_bde_work *wp) { u_char *s, *d; struct g_bde_softc *sc; u_int n; off_t o; u_char skey[G_BDE_SKEYLEN]; keyInstance ki; cipherInstance ci; sc = wp->softc; AES_init(&ci); o = 0; for (n = 0; o < wp->length; n++, o += sc->sectorsize) { s = (u_char *)wp->data + o; d = (u_char *)wp->sp->data + o; arc4rand(&skey, sizeof skey, 0); AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey); AES_encrypt(&ci, &ki, s, d, sc->sectorsize); d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN; g_bde_kkey(sc, &ki, DIR_ENCRYPT, wp->offset + o); AES_encrypt(&ci, &ki, skey, d, sizeof skey); bzero(skey, sizeof skey); } bzero(skey, sizeof skey); bzero(&ci, sizeof ci); bzero(&ki, sizeof ci); }
void g_bde_crypt_read(struct g_bde_work *wp) { struct g_bde_softc *sc; u_char *d; u_int n; off_t o; u_char skey[G_BDE_SKEYLEN]; keyInstance ki; cipherInstance ci; AES_init(&ci); sc = wp->softc; o = 0; for (n = 0; o < wp->length; n++, o += sc->sectorsize) { d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN; g_bde_kkey(sc, &ki, DIR_DECRYPT, wp->offset + o); AES_decrypt(&ci, &ki, d, skey, sizeof skey); d = (u_char *)wp->data + o; AES_makekey(&ki, DIR_DECRYPT, G_BDE_SKEYBITS, skey); AES_decrypt(&ci, &ki, d, d, sc->sectorsize); } bzero(skey, sizeof skey); bzero(&ci, sizeof ci); bzero(&ki, sizeof ci); }
int g_bde_keyloc_decrypt(u_char *sha2, void *input, uint64_t *output) { keyInstance ki; cipherInstance ci; u_char buf[16]; AES_init(&ci); AES_makekey(&ki, DIR_DECRYPT, G_BDE_KKEYBITS, sha2 + 0); AES_decrypt(&ci, &ki, input, buf, sizeof buf); *output = le64dec(buf); bzero(buf, sizeof buf); bzero(&ci, sizeof ci); bzero(&ki, sizeof ki); return(0); }
int g_bde_keyloc_encrypt(u_char *sha2, uint64_t v0, uint64_t v1, void *output) { u_char buf[16]; keyInstance ki; cipherInstance ci; le64enc(buf, v0); le64enc(buf + 8, v1); AES_init(&ci); AES_makekey(&ki, DIR_ENCRYPT, G_BDE_KKEYBITS, sha2 + 0); AES_encrypt(&ci, &ki, buf, output, sizeof buf); bzero(buf, sizeof buf); bzero(&ci, sizeof ci); bzero(&ki, sizeof ki); return (0); }
static int g_bde_decrypt_lockx(struct g_bde_softc *sc, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey) { u_char *buf, *q; struct g_bde_key *gl; uint64_t off, q1; int error, m, i; keyInstance ki; cipherInstance ci; gl = &sc->key; /* Try to decrypt the metadata */ error = g_bde_keyloc_decrypt(sc->sha2, meta, &off); if (error) return (error); /* If it points into thin blue air, forget it */ if (off + G_BDE_LOCKSIZE > (uint64_t)mediasize) { off = 0; return (EINVAL); } /* The lock data may span two physical sectors. */ m = 1; if (off % sectorsize > sectorsize - G_BDE_LOCKSIZE) m++; /* Read the suspected sector(s) */ buf = g_read_data(sc->consumer, off - (off % sectorsize), m * sectorsize, &error); if (buf == NULL) { off = 0; return(error); } /* Find the byte-offset of the stored byte sequence */ q = buf + off % sectorsize; /* If it is all zero, somebody nuked our lock sector */ q1 = 0; for (i = 0; i < G_BDE_LOCKSIZE; i++) q1 += q[i]; if (q1 == 0) { off = 0; g_free(buf); return (ESRCH); } /* Decrypt the byte-sequence in place */ AES_init(&ci); AES_makekey(&ki, DIR_DECRYPT, 256, sc->sha2 + 16); AES_decrypt(&ci, &ki, q, q, G_BDE_LOCKSIZE); /* Decode the byte-sequence */ i = g_bde_decode_lock(sc, gl, q); q = NULL; if (i < 0) { off = 0; return (EDOOFUS); /* Programming error */ } else if (i > 0) { off = 0; return (ENOTDIR); /* Hash didn't match */ } bzero(buf, sectorsize * m); g_free(buf); /* If the masterkey is all zeros, user destroyed it */ q1 = 0; for (i = 0; i < (int)sizeof(gl->mkey); i++) q1 += gl->mkey[i]; if (q1 == 0) return (ENOENT); /* If we have an unsorted lock-sequence, refuse */ for (i = 0; i < G_BDE_MAXKEYS - 1; i++) if (gl->lsector[i] >= gl->lsector[i + 1]) return (EINVAL); /* Finally, find out which key was used by matching the byte offset */ for (i = 0; i < G_BDE_MAXKEYS; i++) if (nkey != NULL && off == gl->lsector[i]) *nkey = i; off = 0; return (0); }