From owner-freebsd-geom@FreeBSD.ORG Mon May 6 00:54:31 2013 Return-Path: Delivered-To: freebsd-geom@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id B0926A49; Mon, 6 May 2013 00:54:31 +0000 (UTC) (envelope-from linimon@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 89452664; Mon, 6 May 2013 00:54:31 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r460sV2G004811; Mon, 6 May 2013 00:54:31 GMT (envelope-from linimon@freefall.freebsd.org) Received: (from linimon@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r460sVBh004810; Mon, 6 May 2013 00:54:31 GMT (envelope-from linimon) Date: Mon, 6 May 2013 00:54:31 GMT Message-Id: <201305060054.r460sVBh004810@freefall.freebsd.org> To: linimon@FreeBSD.org, freebsd-bugs@FreeBSD.org, freebsd-geom@FreeBSD.org From: linimon@FreeBSD.org Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2013 00:54:31 -0000 Old Synopsis: geom_eli: support external metadata New Synopsis: [geom] [patch] geom_eli: support external metadata Responsible-Changed-From-To: freebsd-bugs->freebsd-geom Responsible-Changed-By: linimon Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 Responsible-Changed-Why: Over to maintainer(s). http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 From owner-freebsd-geom@FreeBSD.ORG Mon May 6 03:51:12 2013 Return-Path: Delivered-To: freebsd-geom@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 12FBF443; Mon, 6 May 2013 03:51:12 +0000 (UTC) (envelope-from swhetzel@gmail.com) Received: from mail-ia0-x22f.google.com (mail-ia0-x22f.google.com [IPv6:2607:f8b0:4001:c02::22f]) by mx1.freebsd.org (Postfix) with ESMTP id D18ABD9D; Mon, 6 May 2013 03:51:11 +0000 (UTC) Received: by mail-ia0-f175.google.com with SMTP id i38so2865307iae.34 for ; Sun, 05 May 2013 20:51:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type; bh=IbmbpLYUwZ1tFCTHRp+10R94jG8x8Vje9lc1VHPcE4k=; b=FrTlavvQ0ME8fNutSEpKq1a8if/hBHe7EdEjCH+fz8XT/HJDwqzuiU10+jytF+SaFA qe8ADedl/GELCvgJPozGu7+/M7dxeHhqGNM9TuuqTla+78agi+a1+VqeH+KLSqb8NPRV 0OmIJkA3ko8BQ5KK1ee8cIkoeIhGUIhiZCUuq+Zho9/l456s4T/blTyMhH2wlnvD79uK vgcLX3XxX/4ZB7rGe+64e4tv0rRJ5bv1COwGfKkIxd1cI3PYcgdzBVSMW/7quI4brpsU J9Lv+mKDhJ5fqVRO1Lzz3rIPqqp3WDP43JWZkyeKNgPEWma2Nf9wVCYSrfWzKv7XDqB2 PzkQ== MIME-Version: 1.0 X-Received: by 10.50.62.14 with SMTP id u14mr2012240igr.41.1367812271006; Sun, 05 May 2013 20:51:11 -0700 (PDT) Received: by 10.50.66.162 with HTTP; Sun, 5 May 2013 20:51:10 -0700 (PDT) In-Reply-To: <201305060054.r460sVBh004810@freefall.freebsd.org> References: <201305060054.r460sVBh004810@freefall.freebsd.org> Date: Sun, 5 May 2013 22:51:10 -0500 Message-ID: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata From: Scot Hetzel To: freebsd-bugs@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 Cc: Andrew Romanenko , freebsd-geom@freebsd.org X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2013 03:51:12 -0000 On Sun, May 5, 2013 at 7:54 PM, wrote: > Old Synopsis: geom_eli: support external metadata > New Synopsis: [geom] [patch] geom_eli: support external metadata > > Responsible-Changed-From-To: freebsd-bugs->freebsd-geom > Responsible-Changed-By: linimon > Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 > Responsible-Changed-Why: > Over to maintainer(s). > > http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 I had a quick look at the patch and noticed that it is using -H for init method, but -h for the attach, configure, setkey, delkey, resume, resize, and dump methods. The patch also shows that it removes the -h option from the init method. I looked at the -Current and release/9.1.0 sources for geom_eli.8 and they don't have the -h option. I suspect it was a local modification that was made before this patch was created. It would be best that init, attach, configure, setkey, delkey, resume, resize, and dump methods use the same option (-h or -H) to specify the headerfile. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. From owner-freebsd-geom@FreeBSD.ORG Mon May 6 04:32:14 2013 Return-Path: Delivered-To: freebsd-geom@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 14D93789; Mon, 6 May 2013 04:32:14 +0000 (UTC) (envelope-from swhetzel@gmail.com) Received: from mail-ie0-x235.google.com (mail-ie0-x235.google.com [IPv6:2607:f8b0:4001:c03::235]) by mx1.freebsd.org (Postfix) with ESMTP id D7FDFE81; Mon, 6 May 2013 04:32:13 +0000 (UTC) Received: by mail-ie0-f181.google.com with SMTP id x12so3555208ief.26 for ; Sun, 05 May 2013 21:32:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type; bh=NE+/qQioateCzBePmNVOOCp2Fd+szspq8h4lymtDHbU=; b=lXsWAMSnW8BVnO0Pj9ebWoucKGHyd1bdS+/ELRMSA2XLyAdLiiDKglR/ZvzOjLF6qi EBgk9ONHDSVm2s3/rzZT5SVIw+dMRyg5CVY3snC6XmEe5pxz9K0YZRWaqkBVmXR/N+/P dDro18IuS2px50IB9ft6zK3BWISqFVDC3QRcmd19Dw6IulHoOZCGDTGk9wwJ/nib7+Ts 2pub4FkrJQDOWtfKyNKWWW4uQXDWH1cnwKD8MW3iPGV32GviAtFgqd32eBeHHMTxzp3J SHYqNMG1FE78qTTsU+IwRo7E1tXaPBYxzBLSu4iu8iPRPETa6MdGAEd1HcSnnls9hEYf iaWQ== MIME-Version: 1.0 X-Received: by 10.50.12.133 with SMTP id y5mr2067734igb.108.1367814733533; Sun, 05 May 2013 21:32:13 -0700 (PDT) Received: by 10.50.66.162 with HTTP; Sun, 5 May 2013 21:32:13 -0700 (PDT) In-Reply-To: References: <201305060054.r460sVBh004810@freefall.freebsd.org> Date: Sun, 5 May 2013 23:32:13 -0500 Message-ID: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata From: Scot Hetzel To: freebsd-bugs@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 Cc: Andrew Romanenko , freebsd-geom@freebsd.org X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2013 04:32:14 -0000 On Sun, May 5, 2013 at 10:51 PM, Scot Hetzel wrote: > On Sun, May 5, 2013 at 7:54 PM, wrote: >> Old Synopsis: geom_eli: support external metadata >> New Synopsis: [geom] [patch] geom_eli: support external metadata >> >> Responsible-Changed-From-To: freebsd-bugs->freebsd-geom >> Responsible-Changed-By: linimon >> Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 >> Responsible-Changed-Why: >> Over to maintainer(s). >> >> http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 > > I had a quick look at the patch and noticed that it is using -H for > init method, but -h for the attach, configure, setkey, delkey, resume, > resize, and dump methods. > > The patch also shows that it removes the -h option from the init > method. I looked at the -Current and release/9.1.0 sources for > geom_eli.8 and they don't have the -h option. I suspect it was a > local modification that was made before this patch was created. > My mistake, the -h option was in the geom_eli.c file, but only in the comment for the commands. According to the original commit: https://svnweb.freebsd.org/base?view=revision&revision=148456 The -h was never in the class_commands for the init method. Not sure what it was there for (maybe to display the usuage?). > It would be best that init, attach, configure, setkey, delkey, resume, > resize, and dump methods use the same option (-h or -H) to specify the > headerfile. > So for now it looks like using -H would be the better option for all these methods. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. From owner-freebsd-geom@FreeBSD.ORG Mon May 6 11:06:45 2013 Return-Path: Delivered-To: freebsd-geom@FreeBSD.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 5F512995 for ; Mon, 6 May 2013 11:06:45 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 424449FB for ; Mon, 6 May 2013 11:06:45 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r46B6j6a023777 for ; Mon, 6 May 2013 11:06:45 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r46B6idY023775 for freebsd-geom@FreeBSD.org; Mon, 6 May 2013 11:06:44 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 6 May 2013 11:06:44 GMT Message-Id: <201305061106.r46B6idY023775@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-geom@FreeBSD.org Subject: Current problem reports assigned to freebsd-geom@FreeBSD.org X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2013 11:06:45 -0000 Note: to view an individual PR, use: http://www.freebsd.org/cgi/query-pr.cgi?pr=(number). The following is a listing of current problems submitted by FreeBSD users. These represent problem reports covering all versions including experimental development code and obsolete releases. S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/178359 geom [geom] [patch] geom_eli: support external metadata o kern/176744 geom [geom] [patch] BIO_FLUSH not recorded by devstats o kern/170038 geom [geom] geom_mirror always starts degraded after reboot o kern/169539 geom [geom] [patch] fix ability to run gmirror on MSI MegaR a bin/169077 geom bsdinstall(8) does not use partition labels in /etc/fs f kern/165745 geom [geom] geom_multipath page fault on removed drive o kern/165428 geom [glabel][patch] Add xfs support to glabel o kern/164254 geom [geom] gjournal not stopping on GPT partitions o kern/164252 geom [geom] gjournal overflow o kern/164143 geom [geom] Partition table not recognized after upgrade R8 a kern/163020 geom [geli] [patch] enable the Camellia-XTS on GEOM ELI o kern/162690 geom [geom] gpart label changes only take effect after a re o kern/162010 geom [geli] panic: Provider's error should be set (error=0) o kern/161979 geom [geom] glabel doesn't update after newfs, and glabel s o kern/161752 geom [geom] glabel(8) doesn't get gpt label change o bin/161677 geom gpart(8) Probably bug in gptboot o kern/160409 geom [geli] failed to attach provider f kern/159595 geom [geom] [panic] panic on gmirror unload in vbox [regres f kern/159414 geom [isp] isp(4)+gmultipath(8) : removing active fiber pat p kern/158398 geom [headers] [patch] includes o kern/158197 geom [geom] geom_cache with size>1000 leads to panics o kern/157879 geom [libgeom] [regression] ABI change without version bump o kern/157863 geom [geli] kbdmux prevents geli passwords from being enter o kern/157739 geom [geom] GPT labels with geom_multipath o kern/157724 geom [geom] gpart(8) 'add' command must preserve gap for sc o kern/157723 geom [geom] GEOM should not process 'c' (raw) partitions fo o kern/157108 geom [gjournal] dumpon(8) fails on gjournal providers o kern/155994 geom [geom] Long "Suspend time" when reading large files fr o kern/154226 geom [geom] GEOM label does not change when you modify them o kern/150858 geom [geom] [geom_label] [patch] glabel(8) is not compatibl o kern/150626 geom [geom] [gjournal] gjournal(8) destroys label o kern/150555 geom [geom] gjournal unusable on GPT partitions o kern/150334 geom [geom] [udf] [patch] geom label does not support UDF o kern/149762 geom volume labels with rogue characters o bin/149215 geom [panic] [geom_part] gpart(8): Delete linux's slice via o kern/147667 geom [gmirror] Booting with one component of a gmirror, the o kern/145818 geom [geom] geom_stat_open showing cached information for n o kern/145042 geom [geom] System stops booting after printing message "GE o kern/143455 geom gstripe(8) in RELENG_8 (31st Jan 2010) broken o kern/142563 geom [geom] [hang] ioctl freeze in zpool o kern/141740 geom [geom] gjournal(8): g_journal_destroy concurrent error o kern/140352 geom [geom] gjournal + glabel not working o kern/135898 geom [geom] Severe filesystem corruption - large files or l o kern/134113 geom [geli] Problem setting secondary GELI key o kern/133931 geom [geli] [request] intentionally wrong password to destr o bin/132845 geom [geom] [patch] ggated(8) does not close files opened a o bin/131415 geom [geli] keystrokes are unregulary sent to Geli when typ o kern/131353 geom [geom] gjournal(8) kernel lock o kern/129674 geom [geom] gjournal root did not mount on boot o kern/129645 geom gjournal(8): GEOM_JOURNAL causes system to fail to boo o kern/129245 geom [geom] gcache is more suitable for suffix based provid o kern/127420 geom [geom] [gjournal] [panic] Journal overflow on gmirrore o kern/124973 geom [gjournal] [patch] boot order affects geom_journal con o kern/124969 geom gvinum(8): gvinum raid5 plex does not detect missing s o kern/123962 geom [panic] [gjournal] gjournal (455Gb data, 8Gb journal), o kern/123122 geom [geom] GEOM / gjournal kernel lock o kern/122738 geom [geom] gmirror list "losts consumers" after gmirror de o kern/122067 geom [geom] [panic] Geom crashed during boot o kern/121364 geom [gmirror] Removing all providers create a "zombie" mir o kern/120091 geom [geom] [geli] [gjournal] geli does not prompt for pass o kern/115856 geom [geli] ZFS thought it was degraded when it should have o kern/115547 geom [geom] [patch] [request] let GEOM Eli get password fro o kern/113837 geom [geom] unable to access 1024 sector size storage o kern/113419 geom [geom] geom fox multipathing not failing back o kern/107707 geom [geom] [patch] [request] add new class geom_xbox360 to o kern/94632 geom [geom] Kernel output resets input while GELI asks for o kern/90582 geom [geom] [panic] Restore cause panic string (ffs_blkfree o bin/90093 geom fdisk(8) incapable of altering in-core geometry o kern/87544 geom [gbde] mmaping large files on a gbde filesystem deadlo o bin/86388 geom [geom] [geom_part] periodic(8) daily should backup gpa o kern/84556 geom [geom] [panic] GBDE-encrypted swap causes panic at shu o kern/79251 geom [2TB] newfs fails on 2.6TB gbde device o kern/79035 geom [vinum] gvinum unable to create a striped set of mirro o bin/78131 geom gbde(8) "destroy" not working. 74 problems total. From owner-freebsd-geom@FreeBSD.ORG Mon May 6 11:29:19 2013 Return-Path: Delivered-To: freebsd-geom@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id C09FC92F; Mon, 6 May 2013 11:29:19 +0000 (UTC) (envelope-from melanhit@gmail.com) Received: from mail-wi0-x236.google.com (mail-wi0-x236.google.com [IPv6:2a00:1450:400c:c05::236]) by mx1.freebsd.org (Postfix) with ESMTP id 21817DC7; Mon, 6 May 2013 11:29:18 +0000 (UTC) Received: by mail-wi0-f182.google.com with SMTP id m6so2427373wiv.3 for ; Mon, 06 May 2013 04:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:message-id:date:from:user-agent:mime-version:to:cc :subject:references:in-reply-to:content-type; bh=7vJO0ex+E/Q9eebhqTsNqsvA8QCh/YgBCv0vDiQ2RyU=; b=Umz8HEo+8pUn5ZMcgmVZlY0Wl9q2q+w5utFqTqDg3EDFUov0oY49YZ0jofSty/WfGq 4I7a63oAvQGiIsUUafpqAz4tD2S19srYvUbjdhD3YF//UYLVVWcpYQlT3PDi0XH7Uzfu LRhewVCdrHzyhWfZ+0XloBWf3jp2bpxCaaBIOcNJEJGjZtzLyoTcPFLi0Kq2t1yhC/UZ yMNfSqY7Qv0NDsioegKxzepHR2attKdbypH5NlVWX1m0Vyt/m4Az6DnO+nU++YpEipId l9VGBnwC86Rg61GsZY5tB2C1NT9M399j5BV0lQZ+T0wTxC8J/FAl+HjNER3wvOGfetEX /9Ig== X-Received: by 10.180.185.114 with SMTP id fb18mr8167140wic.33.1367839758342; Mon, 06 May 2013 04:29:18 -0700 (PDT) Received: from localhost.localdomain (46-133-39-194.dialup.umc.net.ua. [46.133.39.194]) by mx.google.com with ESMTPSA id o3sm14602569wia.2.2013.05.06.04.29.08 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 06 May 2013 04:29:17 -0700 (PDT) Message-ID: <51879407.9050105@gmail.com> Date: Mon, 06 May 2013 14:29:11 +0300 From: Andrew Romanenko User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130407 Thunderbird/17.0.5 MIME-Version: 1.0 To: Scot Hetzel Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata References: <201305060054.r460sVBh004810@freefall.freebsd.org> In-Reply-To: Content-Type: multipart/mixed; boundary="------------070906000608010300010805" Cc: freebsd-bugs@freebsd.org, freebsd-geom@freebsd.org X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2013 11:29:19 -0000 This is a multi-part message in MIME format. --------------070906000608010300010805 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On 05/06/2013 07:32 AM, Scot Hetzel wrote: > On Sun, May 5, 2013 at 10:51 PM, Scot Hetzel wrote: >> On Sun, May 5, 2013 at 7:54 PM, wrote: >>> Old Synopsis: geom_eli: support external metadata >>> New Synopsis: [geom] [patch] geom_eli: support external metadata >>> >>> Responsible-Changed-From-To: freebsd-bugs->freebsd-geom >>> Responsible-Changed-By: linimon >>> Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 >>> Responsible-Changed-Why: >>> Over to maintainer(s). >>> >>> http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 >> I had a quick look at the patch and noticed that it is using -H for >> init method, but -h for the attach, configure, setkey, delkey, resume, >> resize, and dump methods. >> >> The patch also shows that it removes the -h option from the init >> method. I looked at the -Current and release/9.1.0 sources for >> geom_eli.8 and they don't have the -h option. I suspect it was a >> local modification that was made before this patch was created. >> > My mistake, the -h option was in the geom_eli.c file, but only in the > comment for the commands. According to the original commit: > > https://svnweb.freebsd.org/base?view=revision&revision=148456 > > The -h was never in the class_commands for the init method. Not sure > what it was there for (maybe to display the usuage?). > >> It would be best that init, attach, configure, setkey, delkey, resume, >> resize, and dump methods use the same option (-h or -H) to specify the >> headerfile. >> > So for now it looks like using -H would be the better option for all > these methods. > > Fixed, using '-H' for all methods (updated patch in the attachment) --------------070906000608010300010805 Content-Type: text/x-patch; name="geli.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="geli.patch" --- sbin/geom/class/eli/geom_eli.c.orig 2013-05-03 00:00:34.551720905 +0300 +++ sbin/geom/class/eli/geom_eli.c 2013-05-05 23:57:52.631347936 +0300 @@ -60,7 +60,6 @@ #define GELI_BACKUP_DIR "/var/backups/" #define GELI_ENC_ALGO "aes" - static void eli_main(struct gctl_req *req, unsigned flags); static void eli_init(struct gctl_req *req); static void eli_attach(struct gctl_req *req); @@ -81,23 +80,23 @@ /* * Available commands: * - * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov + * init [-bPv] [-a aalgo] [-B backupfile] [-H headerfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov * label - alias for 'init' - * attach [-dprv] [-j passfile] [-k keyfile] prov + * attach [-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... * stop - alias for 'detach' * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov - * configure [-bB] prov ... - * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov - * delkey [-afv] [-n keyno] prov + * configure [-bB] [-H headerfile] prov ... + * setkey [-pPv] [-H headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov + * delkey [-afv] [-H headerfile] [-n keyno] prov * suspend [-v] -a | prov ... - * resume [-pv] [-j passfile] [-k keyfile] prov + * resume [-pv] [-H headerfile] [-j passfile] [-k keyfile] prov * kill [-av] [prov ...] * backup [-v] prov file * restore [-fv] file prov - * resize [-v] -s oldsize prov + * resize [-v] [-H headerfile] -s oldsize prov * clear [-v] prov ... - * dump [-v] prov ... + * dump [-v] [-H headerfile] prov ... */ struct g_command class_commands[] = { { "init", G_FLAG_VERBOSE, eli_main, @@ -112,9 +111,10 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" + "[-bPv] [-H headerfile] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" }, { "label", G_FLAG_VERBOSE, eli_main, { @@ -128,6 +128,7 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, "- an alias for 'init'" @@ -139,9 +140,10 @@ { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-dprv] [-j passfile] [-k keyfile] prov" + "[-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "detach", 0, NULL, { @@ -174,9 +176,10 @@ { { 'b', "boot", NULL, G_TYPE_BOOL }, { 'B', "noboot", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bB] prov ..." + "[-bB] [-H headerfile] prov ..." }, { "setkey", G_FLAG_VERBOSE, eli_main, { @@ -188,18 +191,20 @@ { 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" + "[-pPv] [-H headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" }, { "delkey", G_FLAG_VERBOSE, eli_main, { { 'a', "all", NULL, G_TYPE_BOOL }, { 'f', "force", NULL, G_TYPE_BOOL }, { 'n', "keyno", "-1", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-afv] [-n keyno] prov" + "[-afv] [-H headerfile] [-n keyno] prov" }, { "suspend", G_FLAG_VERBOSE, NULL, { @@ -213,9 +218,10 @@ { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pv] [-j passfile] [-k keyfile] prov" + "[-pv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "kill", G_FLAG_VERBOSE, eli_main, { @@ -237,15 +243,20 @@ { "resize", G_FLAG_VERBOSE, eli_main, { { 's', "oldsize", NULL, G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-v] -s oldsize prov" + "[-v] [-H headerfile] -s oldsize prov" }, { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, "[-v] prov ..." }, - { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, - "[-v] prov ..." + { "dump", G_FLAG_VERBOSE, eli_main, + { + { 'H', "header", "", G_TYPE_STRING }, + G_OPT_SENTINEL + }, + "[-v] [-H headerfile] prov ..." }, G_CMD_SENTINEL }; @@ -653,7 +664,7 @@ unsigned char sector[sizeof(struct g_eli_metadata)]; unsigned char key[G_ELI_USERKEYLEN]; char backfile[MAXPATHLEN]; - const char *str, *prov; + const char *str, *prov, *header; unsigned secsize; off_t mediasize; intmax_t val; @@ -776,17 +787,39 @@ return; } + header = gctl_get_ascii(req, "header"); + + /* Store header if it present */ + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + return; + } + + str = gctl_get_ascii(req, "backupfile"); + if(str[0] != '\0') + if(strcmp(str, "none") != 0) + printf("Warning: options -B and -h are mutualy exlusive\n"); + + return; + } + eli_metadata_encode(&md, sector); bzero(&md, sizeof(md)); + error = g_metadata_store(prov, sector, sizeof(sector)); bzero(sector, sizeof(sector)); if (error != 0) { gctl_error(req, "Cannot store metadata on %s: %s.", prov, - strerror(error)); + strerror(error)); return; } if (verbose) printf("Metadata value stored on %s.\n", prov); + /* Backup metadata to a file. */ str = gctl_get_ascii(req, "backupfile"); if (str[0] != '\0') { @@ -820,10 +853,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -831,9 +868,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; + hdsize = g_get_sectorsize(prov); mediasize = g_get_mediasize(prov); if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); @@ -845,20 +889,43 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); if (gctl_issue(req) == NULL) { if (verbose) printf("Attached to %s.\n", prov); } bzero(key, sizeof(key)); + if(hd != NULL) + free(hd); } static void eli_configure_detached(struct gctl_req *req, const char *prov, bool boot) { struct g_eli_metadata md; + const char *str, *header; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) { @@ -872,7 +939,13 @@ md.md_flags |= G_ELI_FLAG_BOOT; else md.md_flags &= ~G_ELI_FLAG_BOOT; - eli_metadata_store(req, prov, &md); + + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, &md); } bzero(&md, sizeof(md)); } @@ -880,7 +953,7 @@ static void eli_configure(struct gctl_req *req) { - const char *prov; + const char *prov, *header; bool boot, noboot; int i, nargs; @@ -902,14 +975,29 @@ return; } + header = gctl_get_ascii(req, "header"); + /* First attached providers. */ - gctl_issue(req); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + prov = gctl_get_ascii(req, "arg0"); + eli_configure_detached(req, prov, boot); + return; + } else { + gctl_issue(req); + } + /* Now the rest. */ for (i = 0; i < nargs; i++) { prov = gctl_get_ascii(req, "arg%d", i); if (!eli_is_attached(prov)) eli_configure_detached(req, prov, boot); } + } static void @@ -950,6 +1038,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov, struct g_eli_metadata *md) { + const char *header, *str; unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; unsigned char *mkeydst; unsigned int nkey; @@ -1035,7 +1124,14 @@ } /* Store metadata with fresh key. */ - eli_metadata_store(req, prov, md); + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, md); + bzero(md, sizeof(*md)); } @@ -1043,7 +1139,7 @@ eli_setkey(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header, *str; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1053,10 +1149,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; - if (eli_is_attached(prov)) + if (eli_is_attached(prov) && header[0] == '\0') eli_setkey_attached(req, &md); else eli_setkey_detached(req, prov, &md); @@ -1079,12 +1181,19 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) { struct g_eli_metadata md; + const char *header, *str; unsigned char *mkeydst; unsigned int nkey; intmax_t val; bool all, force; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; all = gctl_get_int(req, "all"); @@ -1116,6 +1225,11 @@ arc4rand(mkeydst, G_ELI_MKEYLEN); } + if(header[0] != '\0') + str = header; + else + str = prov; + eli_metadata_store(req, prov, &md); bzero(&md, sizeof(md)); } @@ -1123,7 +1237,7 @@ static void eli_delkey(struct gctl_req *req) { - const char *prov; + const char *prov, *header; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1133,7 +1247,9 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_is_attached(prov)) + header = gctl_get_ascii(req, "header"); + + if (eli_is_attached(prov) && header[0] == '\0') eli_delkey_attached(req, prov); else eli_delkey_detached(req, prov); @@ -1144,10 +1260,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -1155,10 +1275,18 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; mediasize = g_get_mediasize(prov); + hdsize = g_get_sectorsize(prov); + if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); return; @@ -1169,12 +1297,30 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); + if (gctl_issue(req) == NULL) { if (verbose) printf("Resumed %s.\n", prov); } bzero(key, sizeof(key)); + + if(hd != NULL) + free(hd); } static int @@ -1469,11 +1615,11 @@ eli_resize(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header; unsigned char *sector; ssize_t secsize; off_t mediasize, oldsize; - int nargs, provfd; + int nargs, provfd, error; nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { @@ -1486,14 +1632,18 @@ sector = NULL; secsize = 0; - provfd = g_open(prov, 1); - if (provfd == -1) { - gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); - goto out; + header = gctl_get_ascii(req, "header"); + + if(header[0] == '\0') { + provfd = g_open(prov, 1); + if (provfd == -1) { + gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); + goto out; + } } - mediasize = g_mediasize(provfd); - secsize = g_sectorsize(provfd); + mediasize = g_get_mediasize(prov); + secsize = g_get_sectorsize(prov); if (mediasize == -1 || secsize == -1) { gctl_error(req, "Cannot get information about %s: %s.", prov, strerror(errno)); @@ -1517,16 +1667,24 @@ } /* Read metadata from the 'oldsize' offset. */ - if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { - gctl_error(req, "Cannot read old metadata: %s.", - strerror(errno)); - goto out; - } + if(header[0] != '\0') { + if (eli_metadata_read(req, header, &md) == -1) { + gctl_error(req, "Cannot read old metadata: %s.", + header); + goto out; + } + } else { + if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { + gctl_error(req, "Cannot read old metadata: %s.", + strerror(errno)); + goto out; + } - /* Check if this sector contains geli metadata. */ - if (eli_metadata_decode(sector, &md) != 0) { - gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); - goto out; + /* Check if this sector contains geli metadata. */ + if (eli_metadata_decode(sector, &md) != 0) { + gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); + goto out; + } } /* @@ -1544,15 +1702,25 @@ */ md.md_provsize = mediasize; eli_metadata_encode(&md, sector); - if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { - gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); - goto out; - } - (void)g_flush(provfd); - /* Now trash the old metadata. */ - if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) - goto out; + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + goto out; + } + } else { + if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { + gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); + goto out; + } + (void)g_flush(provfd); + + /* Now trash the old metadata. */ + if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) + goto out; + } out: if (provfd >= 0) (void)g_close(provfd); @@ -1592,7 +1760,7 @@ eli_dump(struct gctl_req *req) { struct g_eli_metadata md, tmpmd; - const char *name; + const char *name, *header; int error, i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -1601,15 +1769,40 @@ return; } - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(name, (unsigned char *)&tmpmd, - sizeof(tmpmd), G_ELI_MAGIC); - if (error != 0) { + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + if (eli_metadata_read(req, header, &tmpmd) == -1) + return; + + name = gctl_get_ascii(req, "arg0"); + + if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) { + error = EINVAL; fprintf(stderr, "Cannot read metadata from %s: %s.\n", - name, strerror(error)); + name, strerror(error)); gctl_error(req, "Not fully done."); - continue; + return; + } + + name = header; + } + + for (i = 0; i < nargs; i++) { + if(header[0] == '\0') { + name = gctl_get_ascii(req, "arg%d", i); + error = g_metadata_read(name, (unsigned char *)&tmpmd, + sizeof(tmpmd), G_ELI_MAGIC); + if (error != 0) { + fprintf(stderr, "Cannot read metadata from %s: %s.\n", + name, strerror(error)); + gctl_error(req, "Not fully done."); + continue; + } } if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", --- sbin/geom/class/eli/geli.8.orig 2013-04-29 01:45:56.000000000 +0300 +++ sbin/geom/class/eli/geli.8 2013-05-05 16:49:57.642188841 +0300 @@ -52,6 +52,7 @@ .Nm .Cm init .Op Fl bPv +.Op Fl H Ar headerfile .Op Fl a Ar aalgo .Op Fl B Ar backupfile .Op Fl e Ar ealgo @@ -67,6 +68,7 @@ .Nm .Cm attach .Op Fl dprv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov @@ -88,10 +90,12 @@ .Nm .Cm configure .Op Fl bB +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm setkey .Op Fl pPv +.Op Fl H Ar headerfile .Op Fl i Ar iterations .Op Fl j Ar passfile .Op Fl J Ar newpassfile @@ -102,6 +106,7 @@ .Nm .Cm delkey .Op Fl afv +.Op Fl H Ar headerfile .Op Fl n Ar keyno .Ar prov .Nm @@ -125,12 +130,14 @@ .Nm .Cm resume .Op Fl pv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov .Nm .Cm resize .Op Fl v +.Op Fl H Ar headerfile .Fl s Ar oldsize .Ar prov .Nm @@ -140,6 +147,7 @@ .Nm .Cm dump .Op Fl v +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm list @@ -240,6 +248,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Store GELI metadata (header) in the external file .It Fl a Ar aalgo Enable data integrity verification (authentication) using the given algorithm. This will reduce size of available storage and also reduce speed. @@ -341,6 +351,8 @@ option for the .Cm detach subcommand. +.It Fl H Ar headerfile +Read metadata from a file instead from a provider .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -415,7 +427,9 @@ Change configuration of the given providers. .Pp Additional options include: -.Bl -tag -width ".Fl b" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl b Set the BOOT flag on the given providers. For more information, see the description of the @@ -437,6 +451,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl i Ar iterations Number of iterations to use with PKCS#5v2. If 0 is given, PKCS#5v2 will not be used. @@ -472,7 +488,9 @@ subcommand. .Pp Additional options include: -.Bl -tag -width ".Fl a Ar keyno" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl a Destroy all keys (does not need .Fl f @@ -567,7 +585,9 @@ utility is stored is bad idea. .Pp Additional options include: -.Bl -tag -width ".Fl j Ar passfile" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -593,7 +613,9 @@ provider and the provider size is updated. .Pp Additional options include: -.Bl -tag -width ".Fl s Ar oldsize" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl s Ar oldsize The size of the provider before it was resized. .El @@ -764,6 +786,9 @@ # dd if=/dev/random of=/dev/da1s3a bs=1m # dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1 # geli init -b -P -K /boot/keys/da1s3a.key da1s3a +# dd if=/dev/random of=/dev/ada1 bs=1m +# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8 +# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1 .Ed .Pp The providers are initialized, now we have to add those lines to @@ -782,6 +807,13 @@ geli_da1s3a_keyfile0_load="YES" geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0" geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key" + +geli_ada1_header_load="YES" +geli_ada1_header_type="ada1:geli_header" +geli_ada1_header_name="/boot/hd/ada1.hd" +geli_ada1_keyfile0_load="YES" +geli_ada1_keyfile0_type="ada1:geli_keyfile0" +geli_ada1_keyfile0_name="/boot/keys/ada1.key" .Ed .Pp Not only configure encryption, but also data integrity verification using --- sys/geom/eli/g_eli_ctl.c.orig 2013-05-04 01:21:45.381136674 +0300 +++ sys/geom/eli/g_eli_ctl.c 2013-05-05 03:20:20.180243224 +0300 @@ -56,10 +56,11 @@ struct g_eli_metadata md; struct g_provider *pp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, *detach, *readonly; int keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -97,11 +98,18 @@ gctl_error(req, "Provider %s is invalid.", name); return; } - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); @@ -448,8 +456,8 @@ error = g_eli_read_metadata(mp, pp, &md); if (error != 0) { gctl_error(req, - "Cannot read metadata from %s (error=%d).", - prov, error); + "Cannot read metadata from %s (error=%d).", + prov, error); continue; } @@ -464,12 +472,13 @@ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); eli_metadata_encode(&md, sector); error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, - pp->sectorsize); + pp->sectorsize); if (error != 0) { gctl_error(req, - "Cannot store metadata on %s (error=%d).", - prov, error); + "Cannot store metadata on %s (error=%d).", + prov, error); } + bzero(&md, sizeof(md)); bzero(sector, sizeof(sector)); free(sector, M_ELI); @@ -815,9 +824,10 @@ struct g_provider *pp; struct g_consumer *cp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -843,12 +853,20 @@ } cp = LIST_FIRST(&sc->sc_geom->consumer); pp = cp->provider; - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } + if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); --------------070906000608010300010805-- From owner-freebsd-geom@FreeBSD.ORG Tue May 7 01:50:01 2013 Return-Path: Delivered-To: freebsd-geom@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 9C623662 for ; Tue, 7 May 2013 01:50:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 8DFCE68B for ; Tue, 7 May 2013 01:50:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r471o15D005424 for ; Tue, 7 May 2013 01:50:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r471o1K3005421; Tue, 7 May 2013 01:50:01 GMT (envelope-from gnats) Date: Tue, 7 May 2013 01:50:01 GMT Message-Id: <201305070150.r471o1K3005421@freefall.freebsd.org> To: freebsd-geom@FreeBSD.org Cc: From: Mark Linimon Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Mark Linimon List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 May 2013 01:50:01 -0000 The following reply was made to PR kern/178359; it has been noted by GNATS. From: Mark Linimon To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata Date: Mon, 6 May 2013 20:40:23 -0500 ----- Forwarded message from Scot Hetzel ----- Date: Sun, 5 May 2013 23:32:13 -0500 From: Scot Hetzel To: freebsd-bugs@freebsd.org Cc: Andrew Romanenko , freebsd-geom@freebsd.org Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata My mistake, the -h option was in the geom_eli.c file, but only in the comment for the commands. According to the original commit: https://svnweb.freebsd.org/base?view=revision&revision=148456 The -h was never in the class_commands for the init method. Not sure what it was there for (maybe to display the usuage?). > It would be best that init, attach, configure, setkey, delkey, resume, > resize, and dump methods use the same option (-h or -H) to specify the > headerfile. > So for now it looks like using -H would be the better option for all these methods. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. ----- End forwarded message ----- From owner-freebsd-geom@FreeBSD.ORG Tue May 7 01:50:02 2013 Return-Path: Delivered-To: freebsd-geom@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 8D326665 for ; Tue, 7 May 2013 01:50:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 8022F68C for ; Tue, 7 May 2013 01:50:02 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r471o2IE005431 for ; Tue, 7 May 2013 01:50:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r471o2Qf005430; Tue, 7 May 2013 01:50:02 GMT (envelope-from gnats) Date: Tue, 7 May 2013 01:50:02 GMT Message-Id: <201305070150.r471o2Qf005430@freefall.freebsd.org> To: freebsd-geom@FreeBSD.org Cc: From: Mark Linimon Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Mark Linimon List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 May 2013 01:50:02 -0000 The following reply was made to PR kern/178359; it has been noted by GNATS. From: Mark Linimon To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata Date: Mon, 6 May 2013 20:39:59 -0500 ----- Forwarded message from Scot Hetzel ----- Date: Sun, 5 May 2013 22:51:10 -0500 From: Scot Hetzel To: freebsd-bugs@freebsd.org Cc: Andrew Romanenko , freebsd-geom@freebsd.org Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata I had a quick look at the patch and noticed that it is using -H for init method, but -h for the attach, configure, setkey, delkey, resume, resize, and dump methods. The patch also shows that it removes the -h option from the init method. I looked at the -Current and release/9.1.0 sources for geom_eli.8 and they don't have the -h option. I suspect it was a local modification that was made before this patch was created. It would be best that init, attach, configure, setkey, delkey, resume, resize, and dump methods use the same option (-h or -H) to specify the headerfile. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. ----- End forwarded message ----- From owner-freebsd-geom@FreeBSD.ORG Tue May 7 01:50:03 2013 Return-Path: Delivered-To: freebsd-geom@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 96571666 for ; Tue, 7 May 2013 01:50:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 787FE68D for ; Tue, 7 May 2013 01:50:03 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r471o3JB005437 for ; Tue, 7 May 2013 01:50:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r471o36x005436; Tue, 7 May 2013 01:50:03 GMT (envelope-from gnats) Date: Tue, 7 May 2013 01:50:03 GMT Message-Id: <201305070150.r471o36x005436@freefall.freebsd.org> To: freebsd-geom@FreeBSD.org Cc: From: Mark Linimon Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Mark Linimon List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 May 2013 01:50:03 -0000 The following reply was made to PR kern/178359; it has been noted by GNATS. From: Mark Linimon To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata Date: Mon, 6 May 2013 20:40:48 -0500 ----- Forwarded message from Andrew Romanenko ----- Date: Mon, 06 May 2013 14:29:11 +0300 From: Andrew Romanenko To: Scot Hetzel Cc: freebsd-bugs@freebsd.org, freebsd-geom@freebsd.org Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130407 Thunderbird/17.0.5 Fixed, using '-H' for all methods (updated patch in the attachment) --- sbin/geom/class/eli/geom_eli.c.orig 2013-05-03 00:00:34.551720905 +0300 +++ sbin/geom/class/eli/geom_eli.c 2013-05-05 23:57:52.631347936 +0300 @@ -60,7 +60,6 @@ #define GELI_BACKUP_DIR "/var/backups/" #define GELI_ENC_ALGO "aes" - static void eli_main(struct gctl_req *req, unsigned flags); static void eli_init(struct gctl_req *req); static void eli_attach(struct gctl_req *req); @@ -81,23 +80,23 @@ /* * Available commands: * - * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov + * init [-bPv] [-a aalgo] [-B backupfile] [-H headerfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov * label - alias for 'init' - * attach [-dprv] [-j passfile] [-k keyfile] prov + * attach [-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... * stop - alias for 'detach' * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov - * configure [-bB] prov ... - * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov - * delkey [-afv] [-n keyno] prov + * configure [-bB] [-H headerfile] prov ... + * setkey [-pPv] [-H headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov + * delkey [-afv] [-H headerfile] [-n keyno] prov * suspend [-v] -a | prov ... - * resume [-pv] [-j passfile] [-k keyfile] prov + * resume [-pv] [-H headerfile] [-j passfile] [-k keyfile] prov * kill [-av] [prov ...] * backup [-v] prov file * restore [-fv] file prov - * resize [-v] -s oldsize prov + * resize [-v] [-H headerfile] -s oldsize prov * clear [-v] prov ... - * dump [-v] prov ... + * dump [-v] [-H headerfile] prov ... */ struct g_command class_commands[] = { { "init", G_FLAG_VERBOSE, eli_main, @@ -112,9 +111,10 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" + "[-bPv] [-H headerfile] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" }, { "label", G_FLAG_VERBOSE, eli_main, { @@ -128,6 +128,7 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, "- an alias for 'init'" @@ -139,9 +140,10 @@ { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-dprv] [-j passfile] [-k keyfile] prov" + "[-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "detach", 0, NULL, { @@ -174,9 +176,10 @@ { { 'b', "boot", NULL, G_TYPE_BOOL }, { 'B', "noboot", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bB] prov ..." + "[-bB] [-H headerfile] prov ..." }, { "setkey", G_FLAG_VERBOSE, eli_main, { @@ -188,18 +191,20 @@ { 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" + "[-pPv] [-H headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" }, { "delkey", G_FLAG_VERBOSE, eli_main, { { 'a', "all", NULL, G_TYPE_BOOL }, { 'f', "force", NULL, G_TYPE_BOOL }, { 'n', "keyno", "-1", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-afv] [-n keyno] prov" + "[-afv] [-H headerfile] [-n keyno] prov" }, { "suspend", G_FLAG_VERBOSE, NULL, { @@ -213,9 +218,10 @@ { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pv] [-j passfile] [-k keyfile] prov" + "[-pv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "kill", G_FLAG_VERBOSE, eli_main, { @@ -237,15 +243,20 @@ { "resize", G_FLAG_VERBOSE, eli_main, { { 's', "oldsize", NULL, G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-v] -s oldsize prov" + "[-v] [-H headerfile] -s oldsize prov" }, { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, "[-v] prov ..." }, - { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, - "[-v] prov ..." + { "dump", G_FLAG_VERBOSE, eli_main, + { + { 'H', "header", "", G_TYPE_STRING }, + G_OPT_SENTINEL + }, + "[-v] [-H headerfile] prov ..." }, G_CMD_SENTINEL }; @@ -653,7 +664,7 @@ unsigned char sector[sizeof(struct g_eli_metadata)]; unsigned char key[G_ELI_USERKEYLEN]; char backfile[MAXPATHLEN]; - const char *str, *prov; + const char *str, *prov, *header; unsigned secsize; off_t mediasize; intmax_t val; @@ -776,17 +787,39 @@ return; } + header = gctl_get_ascii(req, "header"); + + /* Store header if it present */ + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + return; + } + + str = gctl_get_ascii(req, "backupfile"); + if(str[0] != '\0') + if(strcmp(str, "none") != 0) + printf("Warning: options -B and -h are mutualy exlusive\n"); + + return; + } + eli_metadata_encode(&md, sector); bzero(&md, sizeof(md)); + error = g_metadata_store(prov, sector, sizeof(sector)); bzero(sector, sizeof(sector)); if (error != 0) { gctl_error(req, "Cannot store metadata on %s: %s.", prov, - strerror(error)); + strerror(error)); return; } if (verbose) printf("Metadata value stored on %s.\n", prov); + /* Backup metadata to a file. */ str = gctl_get_ascii(req, "backupfile"); if (str[0] != '\0') { @@ -820,10 +853,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -831,9 +868,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; + hdsize = g_get_sectorsize(prov); mediasize = g_get_mediasize(prov); if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); @@ -845,20 +889,43 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); if (gctl_issue(req) == NULL) { if (verbose) printf("Attached to %s.\n", prov); } bzero(key, sizeof(key)); + if(hd != NULL) + free(hd); } static void eli_configure_detached(struct gctl_req *req, const char *prov, bool boot) { struct g_eli_metadata md; + const char *str, *header; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) { @@ -872,7 +939,13 @@ md.md_flags |= G_ELI_FLAG_BOOT; else md.md_flags &= ~G_ELI_FLAG_BOOT; - eli_metadata_store(req, prov, &md); + + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, &md); } bzero(&md, sizeof(md)); } @@ -880,7 +953,7 @@ static void eli_configure(struct gctl_req *req) { - const char *prov; + const char *prov, *header; bool boot, noboot; int i, nargs; @@ -902,14 +975,29 @@ return; } + header = gctl_get_ascii(req, "header"); + /* First attached providers. */ - gctl_issue(req); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + prov = gctl_get_ascii(req, "arg0"); + eli_configure_detached(req, prov, boot); + return; + } else { + gctl_issue(req); + } + /* Now the rest. */ for (i = 0; i < nargs; i++) { prov = gctl_get_ascii(req, "arg%d", i); if (!eli_is_attached(prov)) eli_configure_detached(req, prov, boot); } + } static void @@ -950,6 +1038,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov, struct g_eli_metadata *md) { + const char *header, *str; unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; unsigned char *mkeydst; unsigned int nkey; @@ -1035,7 +1124,14 @@ } /* Store metadata with fresh key. */ - eli_metadata_store(req, prov, md); + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, md); + bzero(md, sizeof(*md)); } @@ -1043,7 +1139,7 @@ eli_setkey(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header, *str; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1053,10 +1149,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; - if (eli_is_attached(prov)) + if (eli_is_attached(prov) && header[0] == '\0') eli_setkey_attached(req, &md); else eli_setkey_detached(req, prov, &md); @@ -1079,12 +1181,19 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) { struct g_eli_metadata md; + const char *header, *str; unsigned char *mkeydst; unsigned int nkey; intmax_t val; bool all, force; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; all = gctl_get_int(req, "all"); @@ -1116,6 +1225,11 @@ arc4rand(mkeydst, G_ELI_MKEYLEN); } + if(header[0] != '\0') + str = header; + else + str = prov; + eli_metadata_store(req, prov, &md); bzero(&md, sizeof(md)); } @@ -1123,7 +1237,7 @@ static void eli_delkey(struct gctl_req *req) { - const char *prov; + const char *prov, *header; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1133,7 +1247,9 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_is_attached(prov)) + header = gctl_get_ascii(req, "header"); + + if (eli_is_attached(prov) && header[0] == '\0') eli_delkey_attached(req, prov); else eli_delkey_detached(req, prov); @@ -1144,10 +1260,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -1155,10 +1275,18 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; mediasize = g_get_mediasize(prov); + hdsize = g_get_sectorsize(prov); + if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); return; @@ -1169,12 +1297,30 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); + if (gctl_issue(req) == NULL) { if (verbose) printf("Resumed %s.\n", prov); } bzero(key, sizeof(key)); + + if(hd != NULL) + free(hd); } static int @@ -1469,11 +1615,11 @@ eli_resize(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header; unsigned char *sector; ssize_t secsize; off_t mediasize, oldsize; - int nargs, provfd; + int nargs, provfd, error; nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { @@ -1486,14 +1632,18 @@ sector = NULL; secsize = 0; - provfd = g_open(prov, 1); - if (provfd == -1) { - gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); - goto out; + header = gctl_get_ascii(req, "header"); + + if(header[0] == '\0') { + provfd = g_open(prov, 1); + if (provfd == -1) { + gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); + goto out; + } } - mediasize = g_mediasize(provfd); - secsize = g_sectorsize(provfd); + mediasize = g_get_mediasize(prov); + secsize = g_get_sectorsize(prov); if (mediasize == -1 || secsize == -1) { gctl_error(req, "Cannot get information about %s: %s.", prov, strerror(errno)); @@ -1517,16 +1667,24 @@ } /* Read metadata from the 'oldsize' offset. */ - if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { - gctl_error(req, "Cannot read old metadata: %s.", - strerror(errno)); - goto out; - } + if(header[0] != '\0') { + if (eli_metadata_read(req, header, &md) == -1) { + gctl_error(req, "Cannot read old metadata: %s.", + header); + goto out; + } + } else { + if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { + gctl_error(req, "Cannot read old metadata: %s.", + strerror(errno)); + goto out; + } - /* Check if this sector contains geli metadata. */ - if (eli_metadata_decode(sector, &md) != 0) { - gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); - goto out; + /* Check if this sector contains geli metadata. */ + if (eli_metadata_decode(sector, &md) != 0) { + gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); + goto out; + } } /* @@ -1544,15 +1702,25 @@ */ md.md_provsize = mediasize; eli_metadata_encode(&md, sector); - if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { - gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); - goto out; - } - (void)g_flush(provfd); - /* Now trash the old metadata. */ - if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) - goto out; + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + goto out; + } + } else { + if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { + gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); + goto out; + } + (void)g_flush(provfd); + + /* Now trash the old metadata. */ + if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) + goto out; + } out: if (provfd >= 0) (void)g_close(provfd); @@ -1592,7 +1760,7 @@ eli_dump(struct gctl_req *req) { struct g_eli_metadata md, tmpmd; - const char *name; + const char *name, *header; int error, i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -1601,15 +1769,40 @@ return; } - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(name, (unsigned char *)&tmpmd, - sizeof(tmpmd), G_ELI_MAGIC); - if (error != 0) { + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + if (eli_metadata_read(req, header, &tmpmd) == -1) + return; + + name = gctl_get_ascii(req, "arg0"); + + if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) { + error = EINVAL; fprintf(stderr, "Cannot read metadata from %s: %s.\n", - name, strerror(error)); + name, strerror(error)); gctl_error(req, "Not fully done."); - continue; + return; + } + + name = header; + } + + for (i = 0; i < nargs; i++) { + if(header[0] == '\0') { + name = gctl_get_ascii(req, "arg%d", i); + error = g_metadata_read(name, (unsigned char *)&tmpmd, + sizeof(tmpmd), G_ELI_MAGIC); + if (error != 0) { + fprintf(stderr, "Cannot read metadata from %s: %s.\n", + name, strerror(error)); + gctl_error(req, "Not fully done."); + continue; + } } if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", --- sbin/geom/class/eli/geli.8.orig 2013-04-29 01:45:56.000000000 +0300 +++ sbin/geom/class/eli/geli.8 2013-05-05 16:49:57.642188841 +0300 @@ -52,6 +52,7 @@ .Nm .Cm init .Op Fl bPv +.Op Fl H Ar headerfile .Op Fl a Ar aalgo .Op Fl B Ar backupfile .Op Fl e Ar ealgo @@ -67,6 +68,7 @@ .Nm .Cm attach .Op Fl dprv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov @@ -88,10 +90,12 @@ .Nm .Cm configure .Op Fl bB +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm setkey .Op Fl pPv +.Op Fl H Ar headerfile .Op Fl i Ar iterations .Op Fl j Ar passfile .Op Fl J Ar newpassfile @@ -102,6 +106,7 @@ .Nm .Cm delkey .Op Fl afv +.Op Fl H Ar headerfile .Op Fl n Ar keyno .Ar prov .Nm @@ -125,12 +130,14 @@ .Nm .Cm resume .Op Fl pv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov .Nm .Cm resize .Op Fl v +.Op Fl H Ar headerfile .Fl s Ar oldsize .Ar prov .Nm @@ -140,6 +147,7 @@ .Nm .Cm dump .Op Fl v +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm list @@ -240,6 +248,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Store GELI metadata (header) in the external file .It Fl a Ar aalgo Enable data integrity verification (authentication) using the given algorithm. This will reduce size of available storage and also reduce speed. @@ -341,6 +351,8 @@ option for the .Cm detach subcommand. +.It Fl H Ar headerfile +Read metadata from a file instead from a provider .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -415,7 +427,9 @@ Change configuration of the given providers. .Pp Additional options include: -.Bl -tag -width ".Fl b" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl b Set the BOOT flag on the given providers. For more information, see the description of the @@ -437,6 +451,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl i Ar iterations Number of iterations to use with PKCS#5v2. If 0 is given, PKCS#5v2 will not be used. @@ -472,7 +488,9 @@ subcommand. .Pp Additional options include: -.Bl -tag -width ".Fl a Ar keyno" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl a Destroy all keys (does not need .Fl f @@ -567,7 +585,9 @@ utility is stored is bad idea. .Pp Additional options include: -.Bl -tag -width ".Fl j Ar passfile" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -593,7 +613,9 @@ provider and the provider size is updated. .Pp Additional options include: -.Bl -tag -width ".Fl s Ar oldsize" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl s Ar oldsize The size of the provider before it was resized. .El @@ -764,6 +786,9 @@ # dd if=/dev/random of=/dev/da1s3a bs=1m # dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1 # geli init -b -P -K /boot/keys/da1s3a.key da1s3a +# dd if=/dev/random of=/dev/ada1 bs=1m +# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8 +# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1 .Ed .Pp The providers are initialized, now we have to add those lines to @@ -782,6 +807,13 @@ geli_da1s3a_keyfile0_load="YES" geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0" geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key" + +geli_ada1_header_load="YES" +geli_ada1_header_type="ada1:geli_header" +geli_ada1_header_name="/boot/hd/ada1.hd" +geli_ada1_keyfile0_load="YES" +geli_ada1_keyfile0_type="ada1:geli_keyfile0" +geli_ada1_keyfile0_name="/boot/keys/ada1.key" .Ed .Pp Not only configure encryption, but also data integrity verification using --- sys/geom/eli/g_eli_ctl.c.orig 2013-05-04 01:21:45.381136674 +0300 +++ sys/geom/eli/g_eli_ctl.c 2013-05-05 03:20:20.180243224 +0300 @@ -56,10 +56,11 @@ struct g_eli_metadata md; struct g_provider *pp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, *detach, *readonly; int keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -97,11 +98,18 @@ gctl_error(req, "Provider %s is invalid.", name); return; } - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); @@ -448,8 +456,8 @@ error = g_eli_read_metadata(mp, pp, &md); if (error != 0) { gctl_error(req, - "Cannot read metadata from %s (error=%d).", - prov, error); + "Cannot read metadata from %s (error=%d).", + prov, error); continue; } @@ -464,12 +472,13 @@ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); eli_metadata_encode(&md, sector); error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, - pp->sectorsize); + pp->sectorsize); if (error != 0) { gctl_error(req, - "Cannot store metadata on %s (error=%d).", - prov, error); + "Cannot store metadata on %s (error=%d).", + prov, error); } + bzero(&md, sizeof(md)); bzero(sector, sizeof(sector)); free(sector, M_ELI); @@ -815,9 +824,10 @@ struct g_provider *pp; struct g_consumer *cp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -843,12 +853,20 @@ } cp = LIST_FIRST(&sc->sc_geom->consumer); pp = cp->provider; - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } + if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); ----- End forwarded message ----- From owner-freebsd-geom@FreeBSD.ORG Tue May 7 07:26:18 2013 Return-Path: Delivered-To: freebsd-geom@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 28F82149; Tue, 7 May 2013 07:26:18 +0000 (UTC) (envelope-from melanhit@gmail.com) Received: from mail-la0-x229.google.com (mail-la0-x229.google.com [IPv6:2a00:1450:4010:c03::229]) by mx1.freebsd.org (Postfix) with ESMTP id 2EA7D3EA; Tue, 7 May 2013 07:26:16 +0000 (UTC) Received: by mail-la0-f41.google.com with SMTP id fn20so237942lab.0 for ; Tue, 07 May 2013 00:26:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:message-id:date:from:user-agent:mime-version:to:cc :subject:references:in-reply-to:content-type; bh=1PTsYRjA6LJf4cmxUQCY7ee4Hy+zgzOXV+JcyJyHvkg=; b=XVtxTKVUeR5kEc1VFJO6ttfy3criowJpSBaQiEsHW6thwCrSjFaeJoqLMUrKphJNst WEl7YkFkLLOvkyA+cG6MKGdAw4Gx8RiZDAFH1GOPV7nUQOzBjWKuCGitQ7TRtC7rgCM4 HXlSsGOrBKe8e2iH/u4IoQPNBe8vR2ZV6FglkWRrE1hrLRgHFdsdjjP8Xs6ewPdnFjYn 2SqXwh1MiYwvgI2CvNr5THUFpe+P32v6wag7m0f+o5pXLHf6rbKyK/ALPHtJ+CRPHzYM prKWMWmyUGHhU+V45Ejad2vdcDcS1WkAylAgtGZlntSdg8twXAOAE5thtWhkuXdLmjqI r1Cw== X-Received: by 10.112.171.7 with SMTP id aq7mr498462lbc.130.1367911576116; Tue, 07 May 2013 00:26:16 -0700 (PDT) Received: from localhost.localdomain (95-109-241-26.dialup.umc.net.ua. [95.109.241.26]) by mx.google.com with ESMTPSA id r9sm9787095lbr.3.2013.05.07.00.26.03 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 07 May 2013 00:26:15 -0700 (PDT) Message-ID: <5188AC8F.8070900@gmail.com> Date: Tue, 07 May 2013 10:26:07 +0300 From: Andrew Romanenko User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130407 Thunderbird/17.0.5 MIME-Version: 1.0 To: Scot Hetzel Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata References: <201305060054.r460sVBh004810@freefall.freebsd.org> In-Reply-To: Content-Type: multipart/mixed; boundary="------------070201020602040305050702" Cc: freebsd-bugs@freebsd.org, freebsd-geom@freebsd.org X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 May 2013 07:26:18 -0000 This is a multi-part message in MIME format. --------------070201020602040305050702 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit On 05/06/2013 07:32 AM, Scot Hetzel wrote: > On Sun, May 5, 2013 at 10:51 PM, Scot Hetzel wrote: >> On Sun, May 5, 2013 at 7:54 PM, wrote: >>> Old Synopsis: geom_eli: support external metadata >>> New Synopsis: [geom] [patch] geom_eli: support external metadata >>> >>> Responsible-Changed-From-To: freebsd-bugs->freebsd-geom >>> Responsible-Changed-By: linimon >>> Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 >>> Responsible-Changed-Why: >>> Over to maintainer(s). >>> >>> http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 >> I had a quick look at the patch and noticed that it is using -H for >> init method, but -h for the attach, configure, setkey, delkey, resume, >> resize, and dump methods. >> >> The patch also shows that it removes the -h option from the init >> method. I looked at the -Current and release/9.1.0 sources for >> geom_eli.8 and they don't have the -h option. I suspect it was a >> local modification that was made before this patch was created. >> > My mistake, the -h option was in the geom_eli.c file, but only in the > comment for the commands. According to the original commit: > > https://svnweb.freebsd.org/base?view=revision&revision=148456 > > The -h was never in the class_commands for the init method. Not sure > what it was there for (maybe to display the usuage?). > >> It would be best that init, attach, configure, setkey, delkey, resume, >> resize, and dump methods use the same option (-h or -H) to specify the >> headerfile. >> > So for now it looks like using -H would be the better option for all > these methods. > I forgot to include patch sys/geom/eli/g_eli.c (sorry, it's my mistake). Finished and full version of the patch in an attachment --------------070201020602040305050702 Content-Type: text/x-patch; name="geli.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="geli.patch" --- sbin/geom/class/eli/geom_eli.c.orig 2013-05-03 00:00:34.551720905 +0300 +++ sbin/geom/class/eli/geom_eli.c 2013-05-05 23:57:52.631347936 +0300 @@ -60,7 +60,6 @@ #define GELI_BACKUP_DIR "/var/backups/" #define GELI_ENC_ALGO "aes" - static void eli_main(struct gctl_req *req, unsigned flags); static void eli_init(struct gctl_req *req); static void eli_attach(struct gctl_req *req); @@ -81,23 +80,23 @@ /* * Available commands: * - * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov + * init [-bPv] [-a aalgo] [-B backupfile] [-H headerfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov * label - alias for 'init' - * attach [-dprv] [-j passfile] [-k keyfile] prov + * attach [-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... * stop - alias for 'detach' * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov - * configure [-bB] prov ... - * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov - * delkey [-afv] [-n keyno] prov + * configure [-bB] [-H headerfile] prov ... + * setkey [-pPv] [-H headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov + * delkey [-afv] [-H headerfile] [-n keyno] prov * suspend [-v] -a | prov ... - * resume [-pv] [-j passfile] [-k keyfile] prov + * resume [-pv] [-H headerfile] [-j passfile] [-k keyfile] prov * kill [-av] [prov ...] * backup [-v] prov file * restore [-fv] file prov - * resize [-v] -s oldsize prov + * resize [-v] [-H headerfile] -s oldsize prov * clear [-v] prov ... - * dump [-v] prov ... + * dump [-v] [-H headerfile] prov ... */ struct g_command class_commands[] = { { "init", G_FLAG_VERBOSE, eli_main, @@ -112,9 +111,10 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" + "[-bPv] [-H headerfile] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" }, { "label", G_FLAG_VERBOSE, eli_main, { @@ -128,6 +128,7 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, "- an alias for 'init'" @@ -139,9 +140,10 @@ { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-dprv] [-j passfile] [-k keyfile] prov" + "[-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "detach", 0, NULL, { @@ -174,9 +176,10 @@ { { 'b', "boot", NULL, G_TYPE_BOOL }, { 'B', "noboot", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bB] prov ..." + "[-bB] [-H headerfile] prov ..." }, { "setkey", G_FLAG_VERBOSE, eli_main, { @@ -188,18 +191,20 @@ { 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" + "[-pPv] [-H headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" }, { "delkey", G_FLAG_VERBOSE, eli_main, { { 'a', "all", NULL, G_TYPE_BOOL }, { 'f', "force", NULL, G_TYPE_BOOL }, { 'n', "keyno", "-1", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-afv] [-n keyno] prov" + "[-afv] [-H headerfile] [-n keyno] prov" }, { "suspend", G_FLAG_VERBOSE, NULL, { @@ -213,9 +218,10 @@ { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pv] [-j passfile] [-k keyfile] prov" + "[-pv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "kill", G_FLAG_VERBOSE, eli_main, { @@ -237,15 +243,20 @@ { "resize", G_FLAG_VERBOSE, eli_main, { { 's', "oldsize", NULL, G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-v] -s oldsize prov" + "[-v] [-H headerfile] -s oldsize prov" }, { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, "[-v] prov ..." }, - { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, - "[-v] prov ..." + { "dump", G_FLAG_VERBOSE, eli_main, + { + { 'H', "header", "", G_TYPE_STRING }, + G_OPT_SENTINEL + }, + "[-v] [-H headerfile] prov ..." }, G_CMD_SENTINEL }; @@ -653,7 +664,7 @@ unsigned char sector[sizeof(struct g_eli_metadata)]; unsigned char key[G_ELI_USERKEYLEN]; char backfile[MAXPATHLEN]; - const char *str, *prov; + const char *str, *prov, *header; unsigned secsize; off_t mediasize; intmax_t val; @@ -776,17 +787,39 @@ return; } + header = gctl_get_ascii(req, "header"); + + /* Store header if it present */ + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + return; + } + + str = gctl_get_ascii(req, "backupfile"); + if(str[0] != '\0') + if(strcmp(str, "none") != 0) + printf("Warning: options -B and -H are mutualy exlusive\n"); + + return; + } + eli_metadata_encode(&md, sector); bzero(&md, sizeof(md)); + error = g_metadata_store(prov, sector, sizeof(sector)); bzero(sector, sizeof(sector)); if (error != 0) { gctl_error(req, "Cannot store metadata on %s: %s.", prov, - strerror(error)); + strerror(error)); return; } if (verbose) printf("Metadata value stored on %s.\n", prov); + /* Backup metadata to a file. */ str = gctl_get_ascii(req, "backupfile"); if (str[0] != '\0') { @@ -820,10 +853,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -831,9 +868,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; + hdsize = g_get_sectorsize(prov); mediasize = g_get_mediasize(prov); if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); @@ -845,20 +889,43 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); if (gctl_issue(req) == NULL) { if (verbose) printf("Attached to %s.\n", prov); } bzero(key, sizeof(key)); + if(hd != NULL) + free(hd); } static void eli_configure_detached(struct gctl_req *req, const char *prov, bool boot) { struct g_eli_metadata md; + const char *str, *header; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) { @@ -872,7 +939,13 @@ md.md_flags |= G_ELI_FLAG_BOOT; else md.md_flags &= ~G_ELI_FLAG_BOOT; - eli_metadata_store(req, prov, &md); + + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, &md); } bzero(&md, sizeof(md)); } @@ -880,7 +953,7 @@ static void eli_configure(struct gctl_req *req) { - const char *prov; + const char *prov, *header; bool boot, noboot; int i, nargs; @@ -902,14 +975,29 @@ return; } + header = gctl_get_ascii(req, "header"); + /* First attached providers. */ - gctl_issue(req); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + prov = gctl_get_ascii(req, "arg0"); + eli_configure_detached(req, prov, boot); + return; + } else { + gctl_issue(req); + } + /* Now the rest. */ for (i = 0; i < nargs; i++) { prov = gctl_get_ascii(req, "arg%d", i); if (!eli_is_attached(prov)) eli_configure_detached(req, prov, boot); } + } static void @@ -950,6 +1038,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov, struct g_eli_metadata *md) { + const char *header, *str; unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; unsigned char *mkeydst; unsigned int nkey; @@ -1035,7 +1124,14 @@ } /* Store metadata with fresh key. */ - eli_metadata_store(req, prov, md); + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, md); + bzero(md, sizeof(*md)); } @@ -1043,7 +1139,7 @@ eli_setkey(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header, *str; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1053,10 +1149,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; - if (eli_is_attached(prov)) + if (eli_is_attached(prov) && header[0] == '\0') eli_setkey_attached(req, &md); else eli_setkey_detached(req, prov, &md); @@ -1079,12 +1181,19 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) { struct g_eli_metadata md; + const char *header, *str; unsigned char *mkeydst; unsigned int nkey; intmax_t val; bool all, force; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; all = gctl_get_int(req, "all"); @@ -1116,6 +1225,11 @@ arc4rand(mkeydst, G_ELI_MKEYLEN); } + if(header[0] != '\0') + str = header; + else + str = prov; + eli_metadata_store(req, prov, &md); bzero(&md, sizeof(md)); } @@ -1123,7 +1237,7 @@ static void eli_delkey(struct gctl_req *req) { - const char *prov; + const char *prov, *header; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1133,7 +1247,9 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_is_attached(prov)) + header = gctl_get_ascii(req, "header"); + + if (eli_is_attached(prov) && header[0] == '\0') eli_delkey_attached(req, prov); else eli_delkey_detached(req, prov); @@ -1144,10 +1260,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -1155,10 +1275,18 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; mediasize = g_get_mediasize(prov); + hdsize = g_get_sectorsize(prov); + if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); return; @@ -1169,12 +1297,30 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); + if (gctl_issue(req) == NULL) { if (verbose) printf("Resumed %s.\n", prov); } bzero(key, sizeof(key)); + + if(hd != NULL) + free(hd); } static int @@ -1469,11 +1615,11 @@ eli_resize(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header; unsigned char *sector; ssize_t secsize; off_t mediasize, oldsize; - int nargs, provfd; + int nargs, provfd, error; nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { @@ -1486,14 +1632,18 @@ sector = NULL; secsize = 0; - provfd = g_open(prov, 1); - if (provfd == -1) { - gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); - goto out; + header = gctl_get_ascii(req, "header"); + + if(header[0] == '\0') { + provfd = g_open(prov, 1); + if (provfd == -1) { + gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); + goto out; + } } - mediasize = g_mediasize(provfd); - secsize = g_sectorsize(provfd); + mediasize = g_get_mediasize(prov); + secsize = g_get_sectorsize(prov); if (mediasize == -1 || secsize == -1) { gctl_error(req, "Cannot get information about %s: %s.", prov, strerror(errno)); @@ -1517,16 +1667,24 @@ } /* Read metadata from the 'oldsize' offset. */ - if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { - gctl_error(req, "Cannot read old metadata: %s.", - strerror(errno)); - goto out; - } + if(header[0] != '\0') { + if (eli_metadata_read(req, header, &md) == -1) { + gctl_error(req, "Cannot read old metadata: %s.", + header); + goto out; + } + } else { + if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { + gctl_error(req, "Cannot read old metadata: %s.", + strerror(errno)); + goto out; + } - /* Check if this sector contains geli metadata. */ - if (eli_metadata_decode(sector, &md) != 0) { - gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); - goto out; + /* Check if this sector contains geli metadata. */ + if (eli_metadata_decode(sector, &md) != 0) { + gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); + goto out; + } } /* @@ -1544,15 +1702,25 @@ */ md.md_provsize = mediasize; eli_metadata_encode(&md, sector); - if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { - gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); - goto out; - } - (void)g_flush(provfd); - /* Now trash the old metadata. */ - if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) - goto out; + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + goto out; + } + } else { + if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { + gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); + goto out; + } + (void)g_flush(provfd); + + /* Now trash the old metadata. */ + if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) + goto out; + } out: if (provfd >= 0) (void)g_close(provfd); @@ -1592,7 +1760,7 @@ eli_dump(struct gctl_req *req) { struct g_eli_metadata md, tmpmd; - const char *name; + const char *name, *header; int error, i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -1601,15 +1769,40 @@ return; } - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(name, (unsigned char *)&tmpmd, - sizeof(tmpmd), G_ELI_MAGIC); - if (error != 0) { + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + if (eli_metadata_read(req, header, &tmpmd) == -1) + return; + + name = gctl_get_ascii(req, "arg0"); + + if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) { + error = EINVAL; fprintf(stderr, "Cannot read metadata from %s: %s.\n", - name, strerror(error)); + name, strerror(error)); gctl_error(req, "Not fully done."); - continue; + return; + } + + name = header; + } + + for (i = 0; i < nargs; i++) { + if(header[0] == '\0') { + name = gctl_get_ascii(req, "arg%d", i); + error = g_metadata_read(name, (unsigned char *)&tmpmd, + sizeof(tmpmd), G_ELI_MAGIC); + if (error != 0) { + fprintf(stderr, "Cannot read metadata from %s: %s.\n", + name, strerror(error)); + gctl_error(req, "Not fully done."); + continue; + } } if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", --- sbin/geom/class/eli/geli.8.orig 2013-04-29 01:45:56.000000000 +0300 +++ sbin/geom/class/eli/geli.8 2013-05-05 16:49:57.642188841 +0300 @@ -52,6 +52,7 @@ .Nm .Cm init .Op Fl bPv +.Op Fl H Ar headerfile .Op Fl a Ar aalgo .Op Fl B Ar backupfile .Op Fl e Ar ealgo @@ -67,6 +68,7 @@ .Nm .Cm attach .Op Fl dprv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov @@ -88,10 +90,12 @@ .Nm .Cm configure .Op Fl bB +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm setkey .Op Fl pPv +.Op Fl H Ar headerfile .Op Fl i Ar iterations .Op Fl j Ar passfile .Op Fl J Ar newpassfile @@ -102,6 +106,7 @@ .Nm .Cm delkey .Op Fl afv +.Op Fl H Ar headerfile .Op Fl n Ar keyno .Ar prov .Nm @@ -125,12 +130,14 @@ .Nm .Cm resume .Op Fl pv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov .Nm .Cm resize .Op Fl v +.Op Fl H Ar headerfile .Fl s Ar oldsize .Ar prov .Nm @@ -140,6 +147,7 @@ .Nm .Cm dump .Op Fl v +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm list @@ -240,6 +248,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Store GELI metadata (header) in the external file .It Fl a Ar aalgo Enable data integrity verification (authentication) using the given algorithm. This will reduce size of available storage and also reduce speed. @@ -341,6 +351,8 @@ option for the .Cm detach subcommand. +.It Fl H Ar headerfile +Read metadata from a file instead from a provider .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -415,7 +427,9 @@ Change configuration of the given providers. .Pp Additional options include: -.Bl -tag -width ".Fl b" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl b Set the BOOT flag on the given providers. For more information, see the description of the @@ -437,6 +451,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl i Ar iterations Number of iterations to use with PKCS#5v2. If 0 is given, PKCS#5v2 will not be used. @@ -472,7 +488,9 @@ subcommand. .Pp Additional options include: -.Bl -tag -width ".Fl a Ar keyno" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl a Destroy all keys (does not need .Fl f @@ -567,7 +585,9 @@ utility is stored is bad idea. .Pp Additional options include: -.Bl -tag -width ".Fl j Ar passfile" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -593,7 +613,9 @@ provider and the provider size is updated. .Pp Additional options include: -.Bl -tag -width ".Fl s Ar oldsize" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl s Ar oldsize The size of the provider before it was resized. .El @@ -764,6 +786,9 @@ # dd if=/dev/random of=/dev/da1s3a bs=1m # dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1 # geli init -b -P -K /boot/keys/da1s3a.key da1s3a +# dd if=/dev/random of=/dev/ada1 bs=1m +# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8 +# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1 .Ed .Pp The providers are initialized, now we have to add those lines to @@ -782,6 +807,13 @@ geli_da1s3a_keyfile0_load="YES" geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0" geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key" + +geli_ada1_header_load="YES" +geli_ada1_header_type="ada1:geli_header" +geli_ada1_header_name="/boot/hd/ada1.hd" +geli_ada1_keyfile0_load="YES" +geli_ada1_keyfile0_type="ada1:geli_keyfile0" +geli_ada1_keyfile0_name="/boot/keys/ada1.key" .Ed .Pp Not only configure encryption, but also data integrity verification using --- sys/geom/eli/g_eli_ctl.c.orig 2013-05-04 01:21:45.381136674 +0300 +++ sys/geom/eli/g_eli_ctl.c 2013-05-05 03:20:20.180243224 +0300 @@ -56,10 +56,11 @@ struct g_eli_metadata md; struct g_provider *pp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, *detach, *readonly; int keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -97,11 +98,18 @@ gctl_error(req, "Provider %s is invalid.", name); return; } - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); @@ -448,8 +456,8 @@ error = g_eli_read_metadata(mp, pp, &md); if (error != 0) { gctl_error(req, - "Cannot read metadata from %s (error=%d).", - prov, error); + "Cannot read metadata from %s (error=%d).", + prov, error); continue; } @@ -464,12 +472,13 @@ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); eli_metadata_encode(&md, sector); error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, - pp->sectorsize); + pp->sectorsize); if (error != 0) { gctl_error(req, - "Cannot store metadata on %s (error=%d).", - prov, error); + "Cannot store metadata on %s (error=%d).", + prov, error); } + bzero(&md, sizeof(md)); bzero(sector, sizeof(sector)); free(sector, M_ELI); @@ -815,9 +824,10 @@ struct g_provider *pp; struct g_consumer *cp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -843,12 +853,20 @@ } cp = LIST_FIRST(&sc->sc_geom->consumer); pp = cp->provider; - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } + if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); --- sys/geom/eli/g_eli.c.orig 2013-05-07 10:08:29.000000000 +0300 +++ sys/geom/eli/g_eli.c 2013-05-04 00:26:03.620416070 +0300 @@ -1013,6 +1013,47 @@ } } +static int +g_eli_header_load(struct g_eli_metadata *md, const char *provider) +{ + unsigned char *headfile, *data; + char *file, name[64]; + size_t size; + + snprintf(name, sizeof(name), "%s:geli_header", provider); + headfile = preload_search_by_type(name); + if (headfile == NULL) + return (1); + + data = preload_fetch_addr(headfile); + if (data == NULL) { + G_ELI_DEBUG(0, "Cannot find header file data for %s.", + name); + return (1); + } + + size = preload_fetch_size(headfile); + if (size == 0) { + G_ELI_DEBUG(0, "Cannot find header file size for %s.", + name); + return (1); + } + + file = preload_search_info(headfile, MODINFO_NAME); + if (file == NULL) { + G_ELI_DEBUG(0, "Cannot find header file name for %s.", + name); + return (1); + } + + G_ELI_DEBUG(1, "Loaded header %s for %s (type: %s).", file, + provider, name); + + eli_metadata_decode(data, md); + + return (0); +} + /* * Tasting is only made on boot. * We detect providers which should be attached before root is mounted. @@ -1036,9 +1077,11 @@ G_ELI_DEBUG(3, "Tasting %s.", pp->name); - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) - return (NULL); + if(g_eli_header_load(&md, pp->name) != 0) { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) + return (NULL); + } gp = NULL; if (strcmp(md.md_magic, G_ELI_MAGIC) != 0) --------------070201020602040305050702-- From owner-freebsd-geom@FreeBSD.ORG Wed May 8 21:40:01 2013 Return-Path: Delivered-To: freebsd-geom@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 80C9EBAC for ; Wed, 8 May 2013 21:40:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 6316DECB for ; Wed, 8 May 2013 21:40:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r48Le1sO093439 for ; Wed, 8 May 2013 21:40:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r48Le1O3093438; Wed, 8 May 2013 21:40:01 GMT (envelope-from gnats) Date: Wed, 8 May 2013 21:40:01 GMT Message-Id: <201305082140.r48Le1O3093438@freefall.freebsd.org> To: freebsd-geom@FreeBSD.org Cc: From: Mark Linimon Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata X-BeenThere: freebsd-geom@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Mark Linimon List-Id: GEOM-specific discussions and implementations List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 May 2013 21:40:01 -0000 The following reply was made to PR kern/178359; it has been noted by GNATS. From: Mark Linimon To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata Date: Wed, 8 May 2013 16:35:55 -0500 ----- Forwarded message from Andrew Romanenko ----- Date: Tue, 07 May 2013 10:26:07 +0300 From: Andrew Romanenko To: Scot Hetzel Cc: freebsd-bugs@freebsd.org, freebsd-geom@freebsd.org Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130407 Thunderbird/17.0.5 On 05/06/2013 07:32 AM, Scot Hetzel wrote: > On Sun, May 5, 2013 at 10:51 PM, Scot Hetzel wrote: >> On Sun, May 5, 2013 at 7:54 PM, wrote: >>> Old Synopsis: geom_eli: support external metadata >>> New Synopsis: [geom] [patch] geom_eli: support external metadata >>> >>> Responsible-Changed-From-To: freebsd-bugs->freebsd-geom >>> Responsible-Changed-By: linimon >>> Responsible-Changed-When: Mon May 6 00:54:16 UTC 2013 >>> Responsible-Changed-Why: >>> Over to maintainer(s). >>> >>> http://www.freebsd.org/cgi/query-pr.cgi?pr=178359 >> I had a quick look at the patch and noticed that it is using -H for >> init method, but -h for the attach, configure, setkey, delkey, resume, >> resize, and dump methods. >> >> The patch also shows that it removes the -h option from the init >> method. I looked at the -Current and release/9.1.0 sources for >> geom_eli.8 and they don't have the -h option. I suspect it was a >> local modification that was made before this patch was created. >> > My mistake, the -h option was in the geom_eli.c file, but only in the > comment for the commands. According to the original commit: > > https://svnweb.freebsd.org/base?view=revision&revision=148456 > > The -h was never in the class_commands for the init method. Not sure > what it was there for (maybe to display the usuage?). > >> It would be best that init, attach, configure, setkey, delkey, resume, >> resize, and dump methods use the same option (-h or -H) to specify the >> headerfile. >> > So for now it looks like using -H would be the better option for all > these methods. > I forgot to include patch sys/geom/eli/g_eli.c (sorry, it's my mistake). Finished and full version of the patch in an attachment --- sbin/geom/class/eli/geom_eli.c.orig 2013-05-03 00:00:34.551720905 +0300 +++ sbin/geom/class/eli/geom_eli.c 2013-05-05 23:57:52.631347936 +0300 @@ -60,7 +60,6 @@ #define GELI_BACKUP_DIR "/var/backups/" #define GELI_ENC_ALGO "aes" - static void eli_main(struct gctl_req *req, unsigned flags); static void eli_init(struct gctl_req *req); static void eli_attach(struct gctl_req *req); @@ -81,23 +80,23 @@ /* * Available commands: * - * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov + * init [-bPv] [-a aalgo] [-B backupfile] [-H headerfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov * label - alias for 'init' - * attach [-dprv] [-j passfile] [-k keyfile] prov + * attach [-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... * stop - alias for 'detach' * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov - * configure [-bB] prov ... - * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov - * delkey [-afv] [-n keyno] prov + * configure [-bB] [-H headerfile] prov ... + * setkey [-pPv] [-H headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov + * delkey [-afv] [-H headerfile] [-n keyno] prov * suspend [-v] -a | prov ... - * resume [-pv] [-j passfile] [-k keyfile] prov + * resume [-pv] [-H headerfile] [-j passfile] [-k keyfile] prov * kill [-av] [prov ...] * backup [-v] prov file * restore [-fv] file prov - * resize [-v] -s oldsize prov + * resize [-v] [-H headerfile] -s oldsize prov * clear [-v] prov ... - * dump [-v] prov ... + * dump [-v] [-H headerfile] prov ... */ struct g_command class_commands[] = { { "init", G_FLAG_VERBOSE, eli_main, @@ -112,9 +111,10 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" + "[-bPv] [-H headerfile] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov" }, { "label", G_FLAG_VERBOSE, eli_main, { @@ -128,6 +128,7 @@ { 'l', "keylen", "0", G_TYPE_NUMBER }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 's', "sectorsize", "0", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, "- an alias for 'init'" @@ -139,9 +140,10 @@ { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-dprv] [-j passfile] [-k keyfile] prov" + "[-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "detach", 0, NULL, { @@ -174,9 +176,10 @@ { { 'b', "boot", NULL, G_TYPE_BOOL }, { 'B', "noboot", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-bB] prov ..." + "[-bB] [-H headerfile] prov ..." }, { "setkey", G_FLAG_VERBOSE, eli_main, { @@ -188,18 +191,20 @@ { 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" + "[-pPv] [-H headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" }, { "delkey", G_FLAG_VERBOSE, eli_main, { { 'a', "all", NULL, G_TYPE_BOOL }, { 'f', "force", NULL, G_TYPE_BOOL }, { 'n', "keyno", "-1", G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-afv] [-n keyno] prov" + "[-afv] [-H headerfile] [-n keyno] prov" }, { "suspend", G_FLAG_VERBOSE, NULL, { @@ -213,9 +218,10 @@ { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-pv] [-j passfile] [-k keyfile] prov" + "[-pv] [-H headerfile] [-j passfile] [-k keyfile] prov" }, { "kill", G_FLAG_VERBOSE, eli_main, { @@ -237,15 +243,20 @@ { "resize", G_FLAG_VERBOSE, eli_main, { { 's', "oldsize", NULL, G_TYPE_NUMBER }, + { 'H', "header", "", G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-v] -s oldsize prov" + "[-v] [-H headerfile] -s oldsize prov" }, { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, "[-v] prov ..." }, - { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, - "[-v] prov ..." + { "dump", G_FLAG_VERBOSE, eli_main, + { + { 'H', "header", "", G_TYPE_STRING }, + G_OPT_SENTINEL + }, + "[-v] [-H headerfile] prov ..." }, G_CMD_SENTINEL }; @@ -653,7 +664,7 @@ unsigned char sector[sizeof(struct g_eli_metadata)]; unsigned char key[G_ELI_USERKEYLEN]; char backfile[MAXPATHLEN]; - const char *str, *prov; + const char *str, *prov, *header; unsigned secsize; off_t mediasize; intmax_t val; @@ -776,17 +787,39 @@ return; } + header = gctl_get_ascii(req, "header"); + + /* Store header if it present */ + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + return; + } + + str = gctl_get_ascii(req, "backupfile"); + if(str[0] != '\0') + if(strcmp(str, "none") != 0) + printf("Warning: options -B and -H are mutualy exlusive\n"); + + return; + } + eli_metadata_encode(&md, sector); bzero(&md, sizeof(md)); + error = g_metadata_store(prov, sector, sizeof(sector)); bzero(sector, sizeof(sector)); if (error != 0) { gctl_error(req, "Cannot store metadata on %s: %s.", prov, - strerror(error)); + strerror(error)); return; } if (verbose) printf("Metadata value stored on %s.\n", prov); + /* Backup metadata to a file. */ str = gctl_get_ascii(req, "backupfile"); if (str[0] != '\0') { @@ -820,10 +853,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -831,9 +868,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; + hdsize = g_get_sectorsize(prov); mediasize = g_get_mediasize(prov); if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); @@ -845,20 +889,43 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); if (gctl_issue(req) == NULL) { if (verbose) printf("Attached to %s.\n", prov); } bzero(key, sizeof(key)); + if(hd != NULL) + free(hd); } static void eli_configure_detached(struct gctl_req *req, const char *prov, bool boot) { struct g_eli_metadata md; + const char *str, *header; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) { @@ -872,7 +939,13 @@ md.md_flags |= G_ELI_FLAG_BOOT; else md.md_flags &= ~G_ELI_FLAG_BOOT; - eli_metadata_store(req, prov, &md); + + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, &md); } bzero(&md, sizeof(md)); } @@ -880,7 +953,7 @@ static void eli_configure(struct gctl_req *req) { - const char *prov; + const char *prov, *header; bool boot, noboot; int i, nargs; @@ -902,14 +975,29 @@ return; } + header = gctl_get_ascii(req, "header"); + /* First attached providers. */ - gctl_issue(req); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + prov = gctl_get_ascii(req, "arg0"); + eli_configure_detached(req, prov, boot); + return; + } else { + gctl_issue(req); + } + /* Now the rest. */ for (i = 0; i < nargs; i++) { prov = gctl_get_ascii(req, "arg%d", i); if (!eli_is_attached(prov)) eli_configure_detached(req, prov, boot); } + } static void @@ -950,6 +1038,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov, struct g_eli_metadata *md) { + const char *header, *str; unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; unsigned char *mkeydst; unsigned int nkey; @@ -1035,7 +1124,14 @@ } /* Store metadata with fresh key. */ - eli_metadata_store(req, prov, md); + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + eli_metadata_store(req, str, md); + bzero(md, sizeof(*md)); } @@ -1043,7 +1139,7 @@ eli_setkey(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header, *str; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1053,10 +1149,16 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; - if (eli_is_attached(prov)) + if (eli_is_attached(prov) && header[0] == '\0') eli_setkey_attached(req, &md); else eli_setkey_detached(req, prov, &md); @@ -1079,12 +1181,19 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) { struct g_eli_metadata md; + const char *header, *str; unsigned char *mkeydst; unsigned int nkey; intmax_t val; bool all, force; - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; all = gctl_get_int(req, "all"); @@ -1116,6 +1225,11 @@ arc4rand(mkeydst, G_ELI_MKEYLEN); } + if(header[0] != '\0') + str = header; + else + str = prov; + eli_metadata_store(req, prov, &md); bzero(&md, sizeof(md)); } @@ -1123,7 +1237,7 @@ static void eli_delkey(struct gctl_req *req) { - const char *prov; + const char *prov, *header; int nargs; nargs = gctl_get_int(req, "nargs"); @@ -1133,7 +1247,9 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_is_attached(prov)) + header = gctl_get_ascii(req, "header"); + + if (eli_is_attached(prov) && header[0] == '\0') eli_delkey_attached(req, prov); else eli_delkey_detached(req, prov); @@ -1144,10 +1260,14 @@ { struct g_eli_metadata md; unsigned char key[G_ELI_USERKEYLEN]; - const char *prov; + unsigned char *hd; + const char *prov, *str, *header; off_t mediasize; + ssize_t hdsize; int nargs; + hd = NULL; + nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { gctl_error(req, "Invalid number of arguments."); @@ -1155,10 +1275,18 @@ } prov = gctl_get_ascii(req, "arg0"); - if (eli_metadata_read(req, prov, &md) == -1) + header = gctl_get_ascii(req, "header"); + if (header[0] != '\0') + str = header; + else + str = prov; + + if (eli_metadata_read(req, str, &md) == -1) return; mediasize = g_get_mediasize(prov); + hdsize = g_get_sectorsize(prov); + if (md.md_provsize != (uint64_t)mediasize) { gctl_error(req, "Provider size mismatch."); return; @@ -1169,12 +1297,30 @@ return; } + if(header[0] != '\0') { + hd = malloc(hdsize); + if(hd == NULL) { + gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize); + return; + } + + bzero(hd, hdsize); + eli_metadata_encode(&md, hd); + } else { + hdsize = sizeof(hd); + } + + gctl_ro_param(req, "hd", hdsize, hd); gctl_ro_param(req, "key", sizeof(key), key); + if (gctl_issue(req) == NULL) { if (verbose) printf("Resumed %s.\n", prov); } bzero(key, sizeof(key)); + + if(hd != NULL) + free(hd); } static int @@ -1469,11 +1615,11 @@ eli_resize(struct gctl_req *req) { struct g_eli_metadata md; - const char *prov; + const char *prov, *header; unsigned char *sector; ssize_t secsize; off_t mediasize, oldsize; - int nargs, provfd; + int nargs, provfd, error; nargs = gctl_get_int(req, "nargs"); if (nargs != 1) { @@ -1486,14 +1632,18 @@ sector = NULL; secsize = 0; - provfd = g_open(prov, 1); - if (provfd == -1) { - gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); - goto out; + header = gctl_get_ascii(req, "header"); + + if(header[0] == '\0') { + provfd = g_open(prov, 1); + if (provfd == -1) { + gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); + goto out; + } } - mediasize = g_mediasize(provfd); - secsize = g_sectorsize(provfd); + mediasize = g_get_mediasize(prov); + secsize = g_get_sectorsize(prov); if (mediasize == -1 || secsize == -1) { gctl_error(req, "Cannot get information about %s: %s.", prov, strerror(errno)); @@ -1517,16 +1667,24 @@ } /* Read metadata from the 'oldsize' offset. */ - if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { - gctl_error(req, "Cannot read old metadata: %s.", - strerror(errno)); - goto out; - } + if(header[0] != '\0') { + if (eli_metadata_read(req, header, &md) == -1) { + gctl_error(req, "Cannot read old metadata: %s.", + header); + goto out; + } + } else { + if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { + gctl_error(req, "Cannot read old metadata: %s.", + strerror(errno)); + goto out; + } - /* Check if this sector contains geli metadata. */ - if (eli_metadata_decode(sector, &md) != 0) { - gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); - goto out; + /* Check if this sector contains geli metadata. */ + if (eli_metadata_decode(sector, &md) != 0) { + gctl_error(req, "MD5 hash mismatch: no metadata for oldsize."); + goto out; + } } /* @@ -1544,15 +1702,25 @@ */ md.md_provsize = mediasize; eli_metadata_encode(&md, sector); - if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { - gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); - goto out; - } - (void)g_flush(provfd); - /* Now trash the old metadata. */ - if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) - goto out; + if(header[0] != '\0') { + error = eli_metadata_store(req, header, &md); + if(error != 0) { + gctl_error(req, "Cannot store header %s: %s.", header, + strerror(error)); + goto out; + } + } else { + if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) { + gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); + goto out; + } + (void)g_flush(provfd); + + /* Now trash the old metadata. */ + if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1) + goto out; + } out: if (provfd >= 0) (void)g_close(provfd); @@ -1592,7 +1760,7 @@ eli_dump(struct gctl_req *req) { struct g_eli_metadata md, tmpmd; - const char *name; + const char *name, *header; int error, i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -1601,15 +1769,40 @@ return; } - for (i = 0; i < nargs; i++) { - name = gctl_get_ascii(req, "arg%d", i); - error = g_metadata_read(name, (unsigned char *)&tmpmd, - sizeof(tmpmd), G_ELI_MAGIC); - if (error != 0) { + header = gctl_get_ascii(req, "header"); + if(header[0] != '\0') { + if(nargs != 1) { + gctl_error(req, "Too many arguments."); + return; + } + + if (eli_metadata_read(req, header, &tmpmd) == -1) + return; + + name = gctl_get_ascii(req, "arg0"); + + if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) { + error = EINVAL; fprintf(stderr, "Cannot read metadata from %s: %s.\n", - name, strerror(error)); + name, strerror(error)); gctl_error(req, "Not fully done."); - continue; + return; + } + + name = header; + } + + for (i = 0; i < nargs; i++) { + if(header[0] == '\0') { + name = gctl_get_ascii(req, "arg%d", i); + error = g_metadata_read(name, (unsigned char *)&tmpmd, + sizeof(tmpmd), G_ELI_MAGIC); + if (error != 0) { + fprintf(stderr, "Cannot read metadata from %s: %s.\n", + name, strerror(error)); + gctl_error(req, "Not fully done."); + continue; + } } if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", --- sbin/geom/class/eli/geli.8.orig 2013-04-29 01:45:56.000000000 +0300 +++ sbin/geom/class/eli/geli.8 2013-05-05 16:49:57.642188841 +0300 @@ -52,6 +52,7 @@ .Nm .Cm init .Op Fl bPv +.Op Fl H Ar headerfile .Op Fl a Ar aalgo .Op Fl B Ar backupfile .Op Fl e Ar ealgo @@ -67,6 +68,7 @@ .Nm .Cm attach .Op Fl dprv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov @@ -88,10 +90,12 @@ .Nm .Cm configure .Op Fl bB +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm setkey .Op Fl pPv +.Op Fl H Ar headerfile .Op Fl i Ar iterations .Op Fl j Ar passfile .Op Fl J Ar newpassfile @@ -102,6 +106,7 @@ .Nm .Cm delkey .Op Fl afv +.Op Fl H Ar headerfile .Op Fl n Ar keyno .Ar prov .Nm @@ -125,12 +130,14 @@ .Nm .Cm resume .Op Fl pv +.Op Fl H Ar headerfile .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov .Nm .Cm resize .Op Fl v +.Op Fl H Ar headerfile .Fl s Ar oldsize .Ar prov .Nm @@ -140,6 +147,7 @@ .Nm .Cm dump .Op Fl v +.Op Fl H Ar headerfile .Ar prov ... .Nm .Cm list @@ -240,6 +248,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Store GELI metadata (header) in the external file .It Fl a Ar aalgo Enable data integrity verification (authentication) using the given algorithm. This will reduce size of available storage and also reduce speed. @@ -341,6 +351,8 @@ option for the .Cm detach subcommand. +.It Fl H Ar headerfile +Read metadata from a file instead from a provider .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -415,7 +427,9 @@ Change configuration of the given providers. .Pp Additional options include: -.Bl -tag -width ".Fl b" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl b Set the BOOT flag on the given providers. For more information, see the description of the @@ -437,6 +451,8 @@ .Pp Additional options include: .Bl -tag -width ".Fl J Ar newpassfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl i Ar iterations Number of iterations to use with PKCS#5v2. If 0 is given, PKCS#5v2 will not be used. @@ -472,7 +488,9 @@ subcommand. .Pp Additional options include: -.Bl -tag -width ".Fl a Ar keyno" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl a Destroy all keys (does not need .Fl f @@ -567,7 +585,9 @@ utility is stored is bad idea. .Pp Additional options include: -.Bl -tag -width ".Fl j Ar passfile" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl j Ar passfile Specifies a file which contains the passphrase or its part. For more information see the description of the @@ -593,7 +613,9 @@ provider and the provider size is updated. .Pp Additional options include: -.Bl -tag -width ".Fl s Ar oldsize" +.Bl -tag -width ".Fl H Ar headerfile" +.It Fl H Ar headerfile +Handle external metadata .It Fl s Ar oldsize The size of the provider before it was resized. .El @@ -764,6 +786,9 @@ # dd if=/dev/random of=/dev/da1s3a bs=1m # dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1 # geli init -b -P -K /boot/keys/da1s3a.key da1s3a +# dd if=/dev/random of=/dev/ada1 bs=1m +# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8 +# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1 .Ed .Pp The providers are initialized, now we have to add those lines to @@ -782,6 +807,13 @@ geli_da1s3a_keyfile0_load="YES" geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0" geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key" + +geli_ada1_header_load="YES" +geli_ada1_header_type="ada1:geli_header" +geli_ada1_header_name="/boot/hd/ada1.hd" +geli_ada1_keyfile0_load="YES" +geli_ada1_keyfile0_type="ada1:geli_keyfile0" +geli_ada1_keyfile0_name="/boot/keys/ada1.key" .Ed .Pp Not only configure encryption, but also data integrity verification using --- sys/geom/eli/g_eli_ctl.c.orig 2013-05-04 01:21:45.381136674 +0300 +++ sys/geom/eli/g_eli_ctl.c 2013-05-05 03:20:20.180243224 +0300 @@ -56,10 +56,11 @@ struct g_eli_metadata md; struct g_provider *pp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, *detach, *readonly; int keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -97,11 +98,18 @@ gctl_error(req, "Provider %s is invalid.", name); return; } - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); @@ -448,8 +456,8 @@ error = g_eli_read_metadata(mp, pp, &md); if (error != 0) { gctl_error(req, - "Cannot read metadata from %s (error=%d).", - prov, error); + "Cannot read metadata from %s (error=%d).", + prov, error); continue; } @@ -464,12 +472,13 @@ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); eli_metadata_encode(&md, sector); error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, - pp->sectorsize); + pp->sectorsize); if (error != 0) { gctl_error(req, - "Cannot store metadata on %s (error=%d).", - prov, error); + "Cannot store metadata on %s (error=%d).", + prov, error); } + bzero(&md, sizeof(md)); bzero(sector, sizeof(sector)); free(sector, M_ELI); @@ -815,9 +824,10 @@ struct g_provider *pp; struct g_consumer *cp; const char *name; - u_char *key, mkey[G_ELI_DATAIVKEYLEN]; + u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN]; int *nargs, keysize, error; u_int nkey; + ssize_t hdsize; g_topology_assert(); @@ -843,12 +853,20 @@ } cp = LIST_FIRST(&sc->sc_geom->consumer); pp = cp->provider; - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) { - gctl_error(req, "Cannot read metadata from %s (error=%d).", - name, error); - return; + + hd = gctl_get_param(req, "hd", &hdsize); + + if(hdsize == pp->sectorsize) { + eli_metadata_decode(hd, &md); + } else { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s (error=%d).", + name, error); + return; + } } + if (md.md_keys == 0x00) { bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); --- sys/geom/eli/g_eli.c.orig 2013-05-07 10:08:29.000000000 +0300 +++ sys/geom/eli/g_eli.c 2013-05-04 00:26:03.620416070 +0300 @@ -1013,6 +1013,47 @@ } } +static int +g_eli_header_load(struct g_eli_metadata *md, const char *provider) +{ + unsigned char *headfile, *data; + char *file, name[64]; + size_t size; + + snprintf(name, sizeof(name), "%s:geli_header", provider); + headfile = preload_search_by_type(name); + if (headfile == NULL) + return (1); + + data = preload_fetch_addr(headfile); + if (data == NULL) { + G_ELI_DEBUG(0, "Cannot find header file data for %s.", + name); + return (1); + } + + size = preload_fetch_size(headfile); + if (size == 0) { + G_ELI_DEBUG(0, "Cannot find header file size for %s.", + name); + return (1); + } + + file = preload_search_info(headfile, MODINFO_NAME); + if (file == NULL) { + G_ELI_DEBUG(0, "Cannot find header file name for %s.", + name); + return (1); + } + + G_ELI_DEBUG(1, "Loaded header %s for %s (type: %s).", file, + provider, name); + + eli_metadata_decode(data, md); + + return (0); +} + /* * Tasting is only made on boot. * We detect providers which should be attached before root is mounted. @@ -1036,9 +1077,11 @@ G_ELI_DEBUG(3, "Tasting %s.", pp->name); - error = g_eli_read_metadata(mp, pp, &md); - if (error != 0) - return (NULL); + if(g_eli_header_load(&md, pp->name) != 0) { + error = g_eli_read_metadata(mp, pp, &md); + if (error != 0) + return (NULL); + } gp = NULL; if (strcmp(md.md_magic, G_ELI_MAGIC) != 0) _______________________________________________ freebsd-bugs@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscribe@freebsd.org" ----- End forwarded message -----