Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Feb 2015 00:56:15 +0900
From:      "Daisuke Aoyama" <aoyama@peach.ne.jp>
To:        "Brenden Bartelt" <brenden.bartelt@gmail.com>, "George Rosamond" <george@ceetonetechnology.com>
Cc:        freebsd-arm@freebsd.org, Pawel Jakub Dawidek <pjd@freebsd.org>
Subject:   Re: "geli: Wrong key" unable to attach in RPi/ARM environment
Message-ID:  <640B1015D2984FE0A5FB69DBA9ECD23E@ad.peach.ne.jp>
In-Reply-To: <CANUxo4ooMHMeEBPBFH89nsHvrkt-nNmSt2xf-1TTSN6M4htxVg@mail.gmail.com>
References:  <CANUxo4omL1m0EkSnmad8qyZqRWbuZ5zJ29nzCA0%2BgSyCAyU9dw@mail.gmail.com> <54DB7B07.4080704@ceetonetechnology.com> <CANUxo4ooMHMeEBPBFH89nsHvrkt-nNmSt2xf-1TTSN6M4htxVg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_0571_01D04F03.866B0080
Content-Type: text/plain;
	format=flowed;
	charset="iso-8859-1";
	reply-type=original
Content-Transfer-Encoding: 7bit

Hi all,

It seems openssl(/usr/src/crypto/openssl/crypto/evp) doesn't like unaligned buffer.
We use it from g_eli_key.c. decrypt() is called with tmpmkey located stack but encrypt() is 
called with the value passed to the function.
According to definition in g_eli.h, md_mkeys is located odd address due to "uint8_t md_keys".
So encrypt() is called with odd address! In armv6, it's a bad thing of course. armv6 can't 
handle unaligned data by some op.
Fixing is very simple, don't pass mkey directly to openssl.

Please try the patch attached this mail. (usage is bottom of this mail)
I've only checked "geli init". If it does not work in other place, please follow up this mail.

--------------------------------------------------
From: "Brenden Bartelt" <brenden.bartelt@gmail.com>
Sent: Thursday, February 12, 2015 1:08 AM
To: "George Rosamond" <george@ceetonetechnology.com>
Cc: <freebsd-arm@freebsd.org>; "Pawel Jakub Dawidek" <pjd@freebsd.org>
Subject: Re: "geli: Wrong key" unable to attach in RPi/ARM environment

> I have tried it both with and without a -K/-k keyfile specified and with
> and without a passphrase (-P/-p). Any combination results in the same
> "geli: Wrong key for mmcsd0s3."
> For the sake of thoroughness I have even tried it with no PKCS#5v2
> iterations and with a NULL ealgo.
> Each attempt writes a master key to the device metadata, but subsequent
> attempts to attach the device fail with a wrong key.
>
> On Wed, Feb 11, 2015 at 10:53 AM, George Rosamond <
> george@ceetonetechnology.com> wrote:
>
>> Brenden Bartelt:
>> > Hi all,
>> >
>> > This a follow up to a previous thread in freebsd-geom where it was
>> > determined that geli is functional in 11.0-CURRENT and it could be an ARM
>> > problem.
>> >
>> > I have been unable to geli attach in RPi, even with a very simple
>> > passphrase ("test"). Has anyone had success with this? I have tried on an
>> > external usb, da0 as well as a partition on the SD card itself, mmcsd0s3.
>> > The geli init appears to work, and a geli dump reveals that a master key
>> > was indeed written to the device. What is even more puzzling is that a
>> geli
>> > onetime will work for the device, so it would appear that geli is
>> > functional, but something has gone wrong with the master key
>> > generating/writing/reading operation.
>> >
>> > Can anyone shed some light on something I am missing? Is geli not fully
>> > supported on ARM?
>> >
>> > Thanks,
>> > Brenden
>>
>> I haven't tried this, but two things:
>>
>> 1.  did you try setting the key with -k when you attach?
>>
>> 2.  I don't know if he's on this list, but I'm adding pdj@ to the cc.
>>
>> g
>>
>> >
>> > Log:
>> >
>> > # uname -a
>> > FreeBSD raspberry-pi 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r278031: Mon
>> Feb
>> > 2 02:54:08 UTC 2015
>> > root@releng2.nyi.freebsd.org:/usr/obj/arm.armv6/usr/src/sys/RPI-B
>> > arm
>> >
>> > # kldstat
>> > Id Refs Address    Size     Name
>> >  8    1 0xc5657000 17000    geom_eli.ko
>> >  9    1 0xc572e000 2c000    crypto.ko
>> >
>> > # geli init mmcsd0s3
>> > Enter new passphrase:
>> > Reenter new passphrase:
>> >
>> > Metadata backup can be found in /var/backups/mmcsd0s3.eli and
>> > can be restored with the following command:
>> >
>> >         # geli restore /var/backups/mmcsd0s3.eli mmcsd0s3
>> >
>> > # geli attach mmcsd0s3
>> > Enter passphrase:
>> > geli: Wrong key for mmcsd0s3.
>> >
>> > # geli dump mmcsd0s3
>> > Metadata on mmcsd0s3:
>> >      magic: GEOM::ELI
>> >    version: 7
>> >      flags: 0x0
>> >      ealgo: AES-XTS
>> >     keylen: 128
>> >   provsize: 24796725248
>> > sectorsize: 512
>> >       keys: 0x01
>> > iterations: 21660
>> >       Salt:
>> >
>> d2678fa977889263b18cbbb2e5a3151ac8185d9d0bc5dafa548abc4510ca49ce134ef9410cc63a9b0881514d9e9fedb6a3d392ba4096775030d0646fbfb4cce5
>> > Master Key:
>> >
>> 4c26413b864d809b7e537e13ad442d22eada3a12ef61cd538f3a2bc9fd3a1dbbe80e19d6a009c51784461380ff150602c31c4910ad63aa52d105fc93b2005f18cd0b187e0e56b44eabc9784a6255e696a9c398653e4ec669cae64961bd7b43d9af01fa0897f84fef1608c632bbb881d418bdf81e637afff4191ceda6ec829f33c93a0cb5ead63ee63e4c4ccc3ee0b076e6f86b05d514c8b006bf8a11e3f78ac658e56bd824d6958747f09f3c8e80861d2f19eed3f334bbcc83aa28a227239c4bd9c4390a9e1acb5aefed4ef4602432359271217bfb9676eb753930f5c9c45899b0f44bdd230517d3238fc9ab9763b2def43658f44fc76094ccb4af54c7c492a790eca0b407adf66fccf2f3b049c874b66d4bbccd4e82fe8a2e79985ae5e1d64affed7ac66808a2bbd9d661b460c2b9acc1bac5a537bc7d862c711c9ca4892fcf3e607b6ee255555b742352483b7ffda80545bd3774f90ff0e74db58ef87c6c050501c0643c3921345df6e6d7a296c7c535ec81468a8a739824673303664a8874
>> >   MD5 hash: f97f3ca1cf95c25144c84a12b10d81ef
>> >
>> > # geli onetime mmcsd0s3
>> > # geli list
>> > Geom name: mmcsd0s3.eli
>> > State: ACTIVE
>> > EncryptionAlgorithm: AES-XTS
>> > KeyLength: 128
>> > Crypto: software
>> > Version: 7
>> > Flags: ONETIME
>> > KeysAllocated: 47
>> > KeysTotal: 47
>> > Providers:
>> > 1. Name: mmcsd0s3.eli
>> >    Mediasize: 24796725248 (23G)
>> >    Sectorsize: 512
>> >    Mode: r0w0e0
>> > Consumers:
>> > 1. Name: mmcsd0s3
>> >    Mediasize: 24796725248 (23G)
>> >    Sectorsize: 512
>> >    Stripesize: 4194304
>> >    Stripeoffset: 0
>> >    Mode: r1w1e1
>> > _______________________________________________
>> > freebsd-arm@freebsd.org mailing list
>> > http://lists.freebsd.org/mailman/listinfo/freebsd-arm
>> > To unsubscribe, send any mail to "freebsd-arm-unsubscribe@freebsd.org"
>> >
>>
>>
> _______________________________________________
> freebsd-arm@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arm
> To unsubscribe, send any mail to "freebsd-arm-unsubscribe@freebsd.org"

g_eli_mkey_decrypt() @ /usr/src/sys/geom/eli/g_eli_key.c:
----------------------------------------------------------------------
    108 int
    109 g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
    110     unsigned char *mkey, unsigned *nkeyp)
    111 {
    112         unsigned char tmpmkey[G_ELI_MKEYLEN];
    113         unsigned char enckey[SHA512_MDLEN];     /* Key for encryption. */
    114         const unsigned char *mmkey;

    125         mmkey = md->md_mkeys;
    126         for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
    127                 bit = (1 << nkey);
    128                 if (!(md->md_keys & bit))
    129                         continue;
    130                 bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
    131                 error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
    132                     G_ELI_MKEYLEN, enckey, md->md_keylen);
----------------------------------------------------------------------

g_eli_mkey_encrypt() @ /usr/src/sys/geom/eli/g_eli_key.c:
----------------------------------------------------------------------
    156 int
    157 g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
    158     unsigned char *mkey)

    176         error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen);
----------------------------------------------------------------------

/usr/src/sys/geom/eli/g_eli.h:
----------------------------------------------------------------------
    210 struct g_eli_metadata {
    211         char            md_magic[16];   /* Magic value. */
    212         uint32_t        md_version;     /* Version number. */
    213         uint32_t        md_flags;       /* Additional flags. */
    214         uint16_t        md_ealgo;       /* Encryption algorithm. */
    215         uint16_t        md_keylen;      /* Key length. */
    216         uint16_t        md_aalgo;       /* Authentication algorithm. */
    217         uint64_t        md_provsize;    /* Provider's size. */
    218         uint32_t        md_sectorsize;  /* Sector size. */
    219         uint8_t         md_keys;        /* Available keys. */
    220         int32_t         md_iterations;  /* Number of iterations for PKCS#5v2. */
    221         uint8_t         md_salt[G_ELI_SALTLEN]; /* Salt. */
    222                         /* Encrypted master key (IV-key, Data-key, HMAC). */
    223         uint8_t         md_mkeys[G_ELI_MAXMKEYS * G_ELI_MKEYLEN];
    224         u_char          md_hash[16];    /* MD5 hash. */
    225 } __packed;
----------------------------------------------------------------------

/usr/src/sys/geom/eli/g_eli_crypto.c:
----------------------------------------------------------------------
    119 static int
    120 g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
    121     const u_char *key, size_t keysize)

    176         EVP_CIPHER_CTX_init(&ctx);
    177
    178         EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc);
    179         EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8);
    180         EVP_CIPHER_CTX_set_padding(&ctx, 0);
    181         bzero(iv, sizeof(iv));
    182         EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
    183
    184         if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
    185                 EVP_CIPHER_CTX_cleanup(&ctx);
    186                 return (EINVAL);
    187         }
    188         assert(outsize == (int)datasize);
    189
    190         if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
    191                 EVP_CIPHER_CTX_cleanup(&ctx);
    192                 return (EINVAL);
    193         }
    194         assert(outsize == 0);
    195
    196         EVP_CIPHER_CTX_cleanup(&ctx);

    201 int
    202 g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
    203     const u_char *key, size_t keysize)
    204 {
    205
    206         /* We prefer AES-CBC for metadata protection. */
    207         if (algo == CRYPTO_AES_XTS)
    208                 algo = CRYPTO_AES_CBC;
    209
    210         return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
    211 }
----------------------------------------------------------------------

How to use this patch on running system:
----------------------------------------------------------------------
If you don't have source tree, check out with your kernel version specified by "-r".
# uname -v
FreeBSD 11.0-CURRENT #0 r277169M: Wed Jan 14 22:06:07 JST 2015 
aoyama@fbs11.local:/usr/local/src/crochet-freebsd/work/obj/arm.armv6/usr/src/sys/RPI-B-test22
# svnlite checkout -r 277169 svn://svn.FreeBSD.org/base/head /usr/src

Apply the patch
# cd /usr/src
# patch < /path/to/g_eli_key.c.patch

Build the patched shared library
# cd /usr/src/sbin/geom/class/eli
# make && make install

Now you have patched shared library in /lib/geom/geom_eli.so
geli command use this library.
----------------------------------------------------------------------

Thanks,
-- 
Daisuke Aoyama
 

------=_NextPart_000_0571_01D04F03.866B0080
Content-Type: application/octet-stream;
	name="g_eli_key.c.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="g_eli_key.c.patch"

Index: sys/geom/eli/g_eli_key.c=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
--- sys/geom/eli/g_eli_key.c	(revision 277169)=0A=
+++ sys/geom/eli/g_eli_key.c	(working copy)=0A=
@@ -158,6 +158,9 @@=0A=
     unsigned char *mkey)=0A=
 {=0A=
 	unsigned char enckey[SHA512_MDLEN];	/* Key for encryption. */=0A=
+#if !defined(__NO_STRICT_ALIGNMENT)=0A=
+	unsigned char tmpmkey[G_ELI_MKEYLEN];=0A=
+#endif=0A=
 	int error;=0A=
 =0A=
 	/*=0A=
@@ -164,7 +167,13 @@=0A=
 	 * To calculate HMAC, the whole key (G_ELI_USERKEYLEN bytes long) will=0A=
 	 * be used.=0A=
 	 */=0A=
+#if !defined(__NO_STRICT_ALIGNMENT)=0A=
+	/* copy mkey to tmpmkey (sp aligned) */=0A=
+	bcopy(mkey, tmpmkey, G_ELI_MKEYLEN);=0A=
+	g_eli_mkey_hmac(tmpmkey, key);=0A=
+#else=0A=
 	g_eli_mkey_hmac(mkey, key);=0A=
+#endif=0A=
 	/*=0A=
 	 * The key for encryption is: enckey =3D HMAC_SHA512(Derived-Key, 1)=0A=
 	 */=0A=
@@ -173,7 +182,14 @@=0A=
 	 * Encrypt the Master-Key and HMAC() result with the given key (this=0A=
 	 * time only 'keylen' bits from the key are used).=0A=
 	 */=0A=
+#if !defined(__NO_STRICT_ALIGNMENT)=0A=
+	/* encrypt and back to mkey */=0A=
+	error =3D g_eli_crypto_encrypt(algo, tmpmkey, G_ELI_MKEYLEN, enckey, =
keylen);=0A=
+	bcopy(tmpmkey, mkey, G_ELI_MKEYLEN);=0A=
+	bzero(tmpmkey, G_ELI_MKEYLEN);=0A=
+#else=0A=
 	error =3D g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, =
keylen);=0A=
+#endif=0A=
 =0A=
 	bzero(enckey, sizeof(enckey));=0A=
 =0A=

------=_NextPart_000_0571_01D04F03.866B0080--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?640B1015D2984FE0A5FB69DBA9ECD23E>