From: Karol Lewandowski Date: Fri, 24 Jul 2020 11:21:08 +0000 (+0200) Subject: Imported Upstream version 2.3.3 X-Git-Tag: upstream/2.3.3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Ftags%2Fupstream%2F2.3.3;p=platform%2Fupstream%2Fcryptsetup.git Imported Upstream version 2.3.3 Change-Id: I3af4bf459d2b73bed419873693a905a2606332b9 --- diff --git a/ABOUT-NLS b/ABOUT-NLS index 3575535..b1de1b6 100644 --- a/ABOUT-NLS +++ b/ABOUT-NLS @@ -18,35 +18,7 @@ explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. - When reporting bugs in the `intl/' directory or bugs which may be -related to internationalization, you should tell about the version of -`gettext' which is used. The information can be found in the -`intl/VERSION' file, in internationalized packages. - -1.1 Quick configuration advice -============================== - -If you want to exploit the full power of internationalization, you -should configure it using - - ./configure --with-included-gettext - -to force usage of internationalizing routines provided within this -package, despite the existence of internationalizing capabilities in the -operating system where this package is being installed. So far, only -the `gettext' implementation in the GNU C library version 2 provides as -many features (such as locale alias, message inheritance, automatic -charset conversion or plural form handling) as the implementation here. -It is also not possible to offer this additional functionality on top -of a `catgets' implementation. Future versions of GNU `gettext' will -very likely convey even more functionality. So it might be a good idea -to change to GNU `gettext' as soon as possible. - - So you need _not_ provide this option if you are using GNU libc 2 or -you have installed a recent copy of the GNU gettext package with the -included `libintl'. - -1.2 INSTALL Matters +1.1 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs @@ -56,36 +28,19 @@ internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already -provides the GNU `gettext' functions. If not, the included GNU -`gettext' library will be used. This library is wholly contained -within this package, usually in the `intl/' subdirectory, so prior -installation of the GNU `gettext' package is _not_ required. -Installers may use special options at configuration time for changing -the default behaviour. The commands: +provides the GNU `gettext' functions. Installers may use special +options at configuration time for changing the default behaviour. The +command: - ./configure --with-included-gettext ./configure --disable-nls -will, respectively, bypass any pre-existing `gettext' to use the -internationalizing routines provided within this package, or else, -_totally_ disable translation of messages. +will _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will -probably detect the previously built and installed `libintl.a' file and -will decide to use this. This might not be desirable. You should use -the more recent version of the GNU `gettext' library. I.e. if the file -`intl/VERSION' shows that the library which comes with this package is -more recent, you should use - - ./configure --with-included-gettext - -to prevent auto-detection. - - The configuration process will not test for the `catgets' function -and therefore it will not be used. The reason is that even an -emulation of `gettext' on top of `catgets' could not provide all the -extensions of the GNU `gettext' library. +probably detect the previously built and installed `libintl' library +and will decide to use it. If not, you may have to to use the +`--with-libintl-prefix' option to tell `configure' where to look for it. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless @@ -96,13 +51,16 @@ may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. -1.3 Using This Package +1.2 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate -`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, -and `CC' is an ISO 3166 two-letter country code. For example, let's +`LL_CC' combination. If you happen to have the `LC_ALL' or some other +`LC_xxx' environment variables set, you should unset them before +setting `LANG', otherwise the setting of `LANG' will not have the +desired effect. Here `LL' is an ISO 639 two-letter language code, and +`CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). @@ -145,7 +103,7 @@ to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. -1.4 Translating Teams +1.3 Translating Teams ===================== For the Free Translation Project to be a success, we need interested @@ -153,8 +111,7 @@ people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, -`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" -area. +`http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. @@ -168,911 +125,1125 @@ message to `sv-request@li.org', having this message body: _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to -get started, please write to `translation@iro.umontreal.ca' to reach the -coordinator for all translator teams. +get started, please write to `coordinator@translationproject.org' to +reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing -the terminology in use. Proven linguistic skill are praised more than -programming skill, here. +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. -1.5 Available Packages +1.4 Available Packages ====================== Languages are not equally supported in all packages. The following -matrix shows the current state of internationalization, as of July -2006. The matrix shows, in regard of each package, for which languages +matrix shows the current state of internationalization, as of June +2010. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. - Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo - +----------------------------------------------------+ - GNUnet | [] | - a2ps | [] [] [] [] [] | - aegis | () | - ant-phone | () | - anubis | [] | - ap-utils | | - aspell | [] [] [] [] | - bash | [] [] [] | - batchelor | [] | - bfd | | - bibshelf | [] | - binutils | [] | - bison | [] [] | - bison-runtime | [] | - bluez-pin | [] [] [] [] [] | - cflow | [] | - clisp | [] [] | - console-tools | [] [] | - coreutils | [] [] [] [] | - cpio | | - cpplib | [] [] [] | - cryptonit | [] | - darkstat | [] () [] | - dialog | [] [] [] [] [] [] | - diffutils | [] [] [] [] [] [] | - doodle | [] | - e2fsprogs | [] [] | - enscript | [] [] [] [] | - error | [] [] [] [] | - fetchmail | [] [] () [] | - fileutils | [] [] | - findutils | [] [] [] | - flex | [] [] [] | - fslint | [] | - gas | | - gawk | [] [] [] | - gbiff | [] | - gcal | [] | - gcc | [] | - gettext-examples | [] [] [] [] [] | - gettext-runtime | [] [] [] [] [] | - gettext-tools | [] [] | - gimp-print | [] [] [] [] | - gip | [] | - gliv | [] | - glunarclock | [] | - gmult | [] [] | - gnubiff | () | - gnucash | () () [] | - gnucash-glossary | [] () | - gnuedu | | - gnulib | [] [] [] [] [] [] | - gnunet-gtk | | - gnutls | | - gpe-aerial | [] [] | - gpe-beam | [] [] | - gpe-calendar | [] [] | - gpe-clock | [] [] | - gpe-conf | [] [] | - gpe-contacts | | - gpe-edit | [] | - gpe-filemanager | | - gpe-go | [] | - gpe-login | [] [] | - gpe-ownerinfo | [] [] | - gpe-package | | - gpe-sketchbook | [] [] | - gpe-su | [] [] | - gpe-taskmanager | [] [] | - gpe-timesheet | [] | - gpe-today | [] [] | - gpe-todo | | - gphoto2 | [] [] [] [] | - gprof | [] [] | - gpsdrive | () () | - gramadoir | [] [] | - grep | [] [] [] [] [] [] | - gretl | | - gsasl | | - gss | | - gst-plugins | [] [] [] [] | - gst-plugins-base | [] [] [] | - gst-plugins-good | [] [] [] [] [] [] [] | - gstreamer | [] [] [] [] [] [] [] | - gtick | [] () | - gtkam | [] [] [] | - gtkorphan | [] [] | - gtkspell | [] [] [] [] | - gutenprint | [] | - hello | [] [] [] [] [] | - id-utils | [] [] | - impost | | - indent | [] [] [] | - iso_3166 | [] [] | - iso_3166_1 | [] [] [] [] [] | - iso_3166_2 | | - iso_3166_3 | [] | - iso_4217 | [] | - iso_639 | [] [] | - jpilot | [] | - jtag | | - jwhois | | - kbd | [] [] [] [] | - keytouch | | - keytouch-editor | | - keytouch-keyboa... | | - latrine | () | - ld | [] | - leafpad | [] [] [] [] [] | - libc | [] [] [] [] [] | - libexif | [] | - libextractor | [] | - libgpewidget | [] [] [] | - libgpg-error | [] | - libgphoto2 | [] [] | - libgphoto2_port | [] [] | - libgsasl | | - libiconv | [] [] | - libidn | [] [] | - lifelines | [] () | - lilypond | [] | - lingoteach | | - lynx | [] [] [] [] | - m4 | [] [] [] [] | - mailutils | [] | - make | [] [] | - man-db | [] () [] [] | - minicom | [] [] [] | - mysecretdiary | [] [] | - nano | [] [] () [] | - nano_1_0 | [] () [] [] | - opcodes | [] | - parted | | - pilot-qof | [] | - psmisc | [] | - pwdutils | | - python | | - qof | | - radius | [] | - recode | [] [] [] [] [] [] | - rpm | [] [] | - screem | | - scrollkeeper | [] [] [] [] [] [] [] [] | - sed | [] [] [] | - sh-utils | [] [] | - shared-mime-info | [] [] [] | - sharutils | [] [] [] [] [] [] | - shishi | | - silky | | - skencil | [] () | - sketch | [] () | - solfege | | - soundtracker | [] [] | - sp | [] | - stardict | [] | - system-tools-ba... | [] [] [] [] [] [] [] [] [] | - tar | [] | - texinfo | [] [] [] | - textutils | [] [] [] | - tin | () () | - tp-robot | [] | - tuxpaint | [] [] [] [] [] | - unicode-han-tra... | | - unicode-transla... | | - util-linux | [] [] [] [] | - vorbis-tools | [] [] [] [] | - wastesedge | () | - wdiff | [] [] [] [] | - wget | [] [] | - xchat | [] [] [] [] [] | - xkeyboard-config | | - xpad | [] [] | - +----------------------------------------------------+ - af am ar az be bg bs ca cs cy da de el en en_GB eo - 11 0 1 2 8 21 1 42 43 2 62 99 18 1 16 16 - - es et eu fa fi fr ga gl gu he hi hr hu id is it + Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca +--------------------------------------------------+ - GNUnet | | - a2ps | [] [] [] () | + a2ps | [] [] | aegis | | - ant-phone | [] | - anubis | [] | - ap-utils | [] [] | - aspell | [] [] [] | - bash | [] [] [] | - batchelor | [] [] | - bfd | [] | - bibshelf | [] [] [] | - binutils | [] [] [] | - bison | [] [] [] [] [] [] | - bison-runtime | [] [] [] [] [] | - bluez-pin | [] [] [] [] [] | - cflow | | - clisp | [] [] | - console-tools | | - coreutils | [] [] [] [] [] [] | - cpio | [] [] [] | - cpplib | [] [] | - cryptonit | [] | - darkstat | [] () [] [] [] | - dialog | [] [] [] [] [] [] [] [] | - diffutils | [] [] [] [] [] [] [] [] [] | - doodle | [] [] | - e2fsprogs | [] [] [] | - enscript | [] [] [] | - error | [] [] [] [] [] | - fetchmail | [] | - fileutils | [] [] [] [] [] [] | - findutils | [] [] [] [] | - flex | [] [] [] | - fslint | [] | - gas | [] [] | - gawk | [] [] [] [] | - gbiff | [] | - gcal | [] [] | - gcc | [] | - gettext-examples | [] [] [] [] [] | - gettext-runtime | [] [] [] [] [] [] | - gettext-tools | [] [] [] | - gimp-print | [] [] | - gip | [] [] [] | - gliv | () | - glunarclock | [] [] [] | - gmult | [] [] [] | - gnubiff | () () | - gnucash | () () () | - gnucash-glossary | [] [] | - gnuedu | [] | - gnulib | [] [] [] [] [] [] [] [] | - gnunet-gtk | | - gnutls | | - gpe-aerial | [] [] | - gpe-beam | [] [] | - gpe-calendar | [] [] [] [] | - gpe-clock | [] [] [] [] | - gpe-conf | [] | - gpe-contacts | [] [] | - gpe-edit | [] [] [] [] | - gpe-filemanager | [] | - gpe-go | [] [] [] | - gpe-login | [] [] [] | - gpe-ownerinfo | [] [] [] [] [] | - gpe-package | [] | - gpe-sketchbook | [] [] | - gpe-su | [] [] [] [] | - gpe-taskmanager | [] [] [] | - gpe-timesheet | [] [] [] [] | - gpe-today | [] [] [] [] | - gpe-todo | [] | - gphoto2 | [] [] [] [] [] | - gprof | [] [] [] [] | - gpsdrive | () () [] () | - gramadoir | [] [] | - grep | [] [] [] [] [] [] [] [] [] [] [] [] | - gretl | [] [] [] | - gsasl | [] | - gss | [] | - gst-plugins | [] [] [] | - gst-plugins-base | [] [] | - gst-plugins-good | [] [] [] | - gstreamer | [] [] [] | - gtick | [] [] [] [] [] | - gtkam | [] [] [] [] | - gtkorphan | [] [] | - gtkspell | [] [] [] [] [] [] | - gutenprint | [] | - hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | - id-utils | [] [] [] [] [] | - impost | [] [] | - indent | [] [] [] [] [] [] [] [] [] [] | - iso_3166 | [] [] [] | - iso_3166_1 | [] [] [] [] [] [] [] | - iso_3166_2 | [] | - iso_3166_3 | [] | - iso_4217 | [] [] [] [] | - iso_639 | [] [] [] [] [] | - jpilot | [] [] | - jtag | [] | - jwhois | [] [] [] [] [] | - kbd | [] [] | - keytouch | [] | - keytouch-editor | [] | - keytouch-keyboa... | [] | - latrine | [] [] [] | - ld | [] [] | - leafpad | [] [] [] [] [] [] | - libc | [] [] [] [] [] | - libexif | [] | - libextractor | [] | - libgpewidget | [] [] [] [] [] | - libgpg-error | | - libgphoto2 | [] [] [] | - libgphoto2_port | [] [] | - libgsasl | [] [] | - libiconv | [] | - libidn | [] [] | - lifelines | () | - lilypond | [] | - lingoteach | [] [] [] | - lynx | [] [] [] | - m4 | [] [] [] [] | - mailutils | [] [] | - make | [] [] [] [] [] [] [] [] | - man-db | () | - minicom | [] [] [] [] | - mysecretdiary | [] [] [] | - nano | [] () [] [] [] [] | - nano_1_0 | [] [] [] [] [] | - opcodes | [] [] [] [] | - parted | [] [] [] [] | - pilot-qof | | - psmisc | [] [] [] | - pwdutils | | - python | | - qof | | - radius | [] [] | - recode | [] [] [] [] [] [] [] [] | - rpm | [] [] | - screem | | - scrollkeeper | [] [] [] | - sed | [] [] [] [] [] | - sh-utils | [] [] [] [] [] [] [] | - shared-mime-info | [] [] [] [] [] [] | - sharutils | [] [] [] [] [] [] [] [] | - shishi | | - silky | [] | - skencil | [] [] | - sketch | [] [] | - solfege | [] | - soundtracker | [] [] [] | - sp | [] | - stardict | [] | - system-tools-ba... | [] [] [] [] [] [] [] [] | - tar | [] [] [] [] [] [] | - texinfo | [] [] | - textutils | [] [] [] [] [] | - tin | [] () | - tp-robot | [] [] [] [] | - tuxpaint | [] [] | - unicode-han-tra... | | - unicode-transla... | [] [] | - util-linux | [] [] [] [] [] [] [] | - vorbis-tools | [] [] | - wastesedge | () | - wdiff | [] [] [] [] [] [] [] [] | - wget | [] [] [] [] [] [] [] [] | - xchat | [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] [] [] | - xpad | [] [] [] | - +--------------------------------------------------+ - es et eu fa fi fr ga gl gu he hi hr hu id is it - 89 21 16 2 41 119 61 14 1 8 1 6 61 30 0 53 - - ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no - +--------------------------------------------------+ - GNUnet | | - a2ps | () [] [] () | - aegis | () | - ant-phone | [] | - anubis | [] [] [] | - ap-utils | [] | - aspell | [] [] | - bash | [] | - batchelor | [] [] | + ant-phone | | + anubis | | + aspell | [] [] | + bash | | bfd | | - bibshelf | [] | + bibshelf | [] | binutils | | - bison | [] [] [] | - bison-runtime | [] [] [] | - bluez-pin | [] [] [] | + bison | | + bison-runtime | [] | + bluez-pin | [] [] | + bombono-dvd | | + buzztard | | cflow | | - clisp | [] | - console-tools | | - coreutils | [] | + clisp | | + coreutils | [] [] | cpio | | - cpplib | [] | - cryptonit | [] | - darkstat | [] [] | - dialog | [] [] | - diffutils | [] [] [] | + cppi | | + cpplib | [] | + cryptsetup | | + dfarc | | + dialog | [] [] | + dico | | + diffutils | [] | + dink | | doodle | | - e2fsprogs | [] | - enscript | [] | - error | [] | - fetchmail | [] [] | - fileutils | [] [] | - findutils | [] | - flex | [] [] | - fslint | [] [] | + e2fsprogs | [] | + enscript | [] | + exif | | + fetchmail | [] | + findutils | [] | + flex | [] | + freedink | | gas | | - gawk | [] [] | - gbiff | [] | - gcal | | + gawk | [] [] | + gcal | [] | gcc | | - gettext-examples | [] [] | - gettext-runtime | [] [] [] | - gettext-tools | [] [] | - gimp-print | [] [] | - gip | [] [] | - gliv | [] | - glunarclock | [] [] | - gmult | [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] | + gettext-tools | [] [] | + gip | [] | + gjay | | + gliv | [] | + glunarclock | [] [] | gnubiff | | - gnucash | () () | - gnucash-glossary | [] | + gnucash | [] | gnuedu | | - gnulib | [] [] [] [] | + gnulib | | + gnunet | | gnunet-gtk | | gnutls | | - gpe-aerial | [] | - gpe-beam | [] | - gpe-calendar | [] | - gpe-clock | [] [] | - gpe-conf | [] [] | - gpe-contacts | [] | - gpe-edit | [] [] | - gpe-filemanager | [] | - gpe-go | [] [] | - gpe-login | [] [] | - gpe-ownerinfo | [] | - gpe-package | [] | - gpe-sketchbook | [] [] | - gpe-su | [] [] | - gpe-taskmanager | [] [] [] | - gpe-timesheet | [] | - gpe-today | [] | + gold | | + gpe-aerial | | + gpe-beam | | + gpe-bluetooth | | + gpe-calendar | | + gpe-clock | [] | + gpe-conf | | + gpe-contacts | | + gpe-edit | | + gpe-filemanager | | + gpe-go | | + gpe-login | | + gpe-ownerinfo | [] | + gpe-package | | + gpe-sketchbook | | + gpe-su | [] | + gpe-taskmanager | [] | + gpe-timesheet | [] | + gpe-today | [] | gpe-todo | | - gphoto2 | [] [] | - gprof | | - gpsdrive | () () () | - gramadoir | () | - grep | [] [] [] | - gretl | | - gsasl | [] | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | [] [] | + gsasl | | gss | | - gst-plugins | [] | - gst-plugins-base | | - gst-plugins-good | [] | - gstreamer | [] | - gtick | [] | - gtkam | [] | - gtkorphan | [] | - gtkspell | [] [] | + gst-plugins-bad | [] | + gst-plugins-base | [] | + gst-plugins-good | [] | + gst-plugins-ugly | [] | + gstreamer | [] [] [] | + gtick | | + gtkam | [] | + gtkorphan | [] | + gtkspell | [] [] [] | gutenprint | | - hello | [] [] [] [] [] [] [] [] | - id-utils | [] | - impost | | - indent | [] [] | - iso_3166 | [] | - iso_3166_1 | [] [] | - iso_3166_2 | [] | - iso_3166_3 | [] | - iso_4217 | [] [] [] | - iso_639 | [] [] | - jpilot | () () () | - jtag | | - jwhois | [] | - kbd | [] | - keytouch | [] | + hello | [] | + help2man | | + hylafax | | + idutils | | + indent | [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | | + iso_639 | [] [] [] [] | + iso_639_3 | | + jwhois | | + kbd | | + keytouch | [] | keytouch-editor | | - keytouch-keyboa... | | - latrine | [] | - ld | | - leafpad | [] [] | - libc | [] [] [] [] [] | - libexif | | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | | + ld | [] | + leafpad | [] [] | + libc | [] [] | + libexif | () | libextractor | | - libgpewidget | [] | + libgnutls | | + libgpewidget | | libgpg-error | | - libgphoto2 | [] | - libgphoto2_port | [] | - libgsasl | [] | - libiconv | | - libidn | [] [] | - lifelines | [] | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | [] | + libidn | | + lifelines | | + liferea | [] [] | lilypond | | - lingoteach | [] | - lynx | [] [] | - m4 | [] [] | + linkdr | [] | + lordsawar | | + lprng | | + lynx | [] | + m4 | | + mailfromd | | mailutils | | - make | [] [] [] | - man-db | () | - minicom | [] | - mysecretdiary | [] | - nano | [] [] [] | - nano_1_0 | [] [] [] | - opcodes | [] | - parted | [] [] | - pilot-qof | | - psmisc | [] [] [] | + make | | + man-db | | + man-db-manpages | | + minicom | | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | | + psmisc | | + pspp | [] | pwdutils | | - python | | - qof | | - radius | | - recode | [] | - rpm | [] [] | - screem | [] | - scrollkeeper | [] [] [] [] | - sed | [] [] | - sh-utils | [] [] | - shared-mime-info | [] [] [] [] [] | - sharutils | [] [] | + radius | [] | + recode | [] [] | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] | + sed | [] [] | + sharutils | [] [] | shishi | | - silky | [] | skencil | | - sketch | | solfege | | + solfege-manual | | soundtracker | | - sp | () | - stardict | [] [] | - system-tools-ba... | [] [] [] [] | - tar | [] [] [] | - texinfo | [] [] [] | - textutils | [] [] [] | + sp | | + sysstat | | + tar | [] | + texinfo | | tin | | - tp-robot | [] | - tuxpaint | [] | unicode-han-tra... | | unicode-transla... | | - util-linux | [] [] | - vorbis-tools | [] | - wastesedge | [] | - wdiff | [] [] | - wget | [] [] | - xchat | [] [] [] [] | - xkeyboard-config | [] | - xpad | [] [] [] | + util-linux-ng | [] | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] [] | + wyslij-po | | + xchat | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] | +--------------------------------------------------+ - ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no - 40 24 2 1 1 3 1 2 3 21 0 15 1 101 5 3 + af am an ar as ast az be be@latin bg bn_IN bs ca + 6 0 1 2 3 19 1 10 3 28 3 1 38 - nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta - +------------------------------------------------------+ - GNUnet | | - a2ps | () [] [] [] [] [] [] | - aegis | () () | - ant-phone | [] [] | - anubis | [] [] [] | - ap-utils | () | - aspell | [] [] | - bash | [] [] [] | - batchelor | [] [] | - bfd | | - bibshelf | [] | - binutils | [] [] | - bison | [] [] [] [] [] | - bison-runtime | [] [] [] [] | - bluez-pin | [] [] [] [] [] [] [] [] [] | - cflow | [] | - clisp | [] | - console-tools | [] | - coreutils | [] [] [] [] | - cpio | [] [] [] | - cpplib | [] | - cryptonit | [] [] | - darkstat | [] [] [] [] [] [] | - dialog | [] [] [] [] [] [] [] [] [] | - diffutils | [] [] [] [] [] [] | - doodle | [] [] | - e2fsprogs | [] [] | - enscript | [] [] [] [] [] | - error | [] [] [] [] | - fetchmail | [] [] [] | - fileutils | [] [] [] [] [] | - findutils | [] [] [] [] [] [] | - flex | [] [] [] [] [] | - fslint | [] [] [] [] | - gas | | - gawk | [] [] [] [] | - gbiff | [] | - gcal | [] | - gcc | [] | - gettext-examples | [] [] [] [] [] [] [] [] | - gettext-runtime | [] [] [] [] [] [] [] [] | - gettext-tools | [] [] [] [] [] [] [] | - gimp-print | [] [] | - gip | [] [] [] [] | - gliv | [] [] [] [] | - glunarclock | [] [] [] [] [] [] | - gmult | [] [] [] [] | - gnubiff | () | - gnucash | () [] | - gnucash-glossary | [] [] [] | - gnuedu | | - gnulib | [] [] [] [] [] | - gnunet-gtk | [] | - gnutls | [] [] | - gpe-aerial | [] [] [] [] [] [] [] | - gpe-beam | [] [] [] [] [] [] [] | - gpe-calendar | [] [] [] [] [] [] [] [] | - gpe-clock | [] [] [] [] [] [] [] [] | - gpe-conf | [] [] [] [] [] [] [] | - gpe-contacts | [] [] [] [] [] | - gpe-edit | [] [] [] [] [] [] [] [] | - gpe-filemanager | [] [] | - gpe-go | [] [] [] [] [] [] | - gpe-login | [] [] [] [] [] [] [] [] | - gpe-ownerinfo | [] [] [] [] [] [] [] [] | - gpe-package | [] [] | - gpe-sketchbook | [] [] [] [] [] [] [] [] | - gpe-su | [] [] [] [] [] [] [] [] | - gpe-taskmanager | [] [] [] [] [] [] [] [] | - gpe-timesheet | [] [] [] [] [] [] [] [] | - gpe-today | [] [] [] [] [] [] [] [] | - gpe-todo | [] [] [] [] | - gphoto2 | [] [] [] [] [] | - gprof | [] [] [] | - gpsdrive | [] [] [] | - gramadoir | [] [] | - grep | [] [] [] [] [] [] [] [] | - gretl | [] | - gsasl | [] [] | - gss | [] [] [] | - gst-plugins | [] [] [] [] | - gst-plugins-base | [] | - gst-plugins-good | [] [] [] [] | - gstreamer | [] [] [] | - gtick | [] [] [] | - gtkam | [] [] [] [] | - gtkorphan | [] | - gtkspell | [] [] [] [] [] [] [] [] | - gutenprint | [] | - hello | [] [] [] [] [] [] [] [] | - id-utils | [] [] [] [] | - impost | [] | - indent | [] [] [] [] [] [] | - iso_3166 | [] [] [] [] [] [] | - iso_3166_1 | [] [] [] [] | - iso_3166_2 | | - iso_3166_3 | [] [] [] [] | - iso_4217 | [] [] [] [] | - iso_639 | [] [] [] [] | - jpilot | | - jtag | [] | - jwhois | [] [] [] [] | - kbd | [] [] [] | - keytouch | [] | - keytouch-editor | [] | - keytouch-keyboa... | [] | - latrine | [] [] | - ld | [] | - leafpad | [] [] [] [] [] [] | - libc | [] [] [] [] [] | - libexif | [] | - libextractor | [] [] | - libgpewidget | [] [] [] [] [] [] [] | - libgpg-error | [] [] | - libgphoto2 | [] | - libgphoto2_port | [] [] [] | - libgsasl | [] [] [] [] | - libiconv | | - libidn | [] [] () | - lifelines | [] [] | - lilypond | | - lingoteach | [] | - lynx | [] [] [] | - m4 | [] [] [] [] [] | - mailutils | [] [] [] [] | - make | [] [] [] [] | - man-db | [] [] | - minicom | [] [] [] [] [] | - mysecretdiary | [] [] [] [] | - nano | [] [] | - nano_1_0 | [] [] [] [] | - opcodes | [] [] | - parted | [] | - pilot-qof | [] | - psmisc | [] [] | - pwdutils | [] [] | - python | | - qof | [] | - radius | [] [] | - recode | [] [] [] [] [] [] [] | - rpm | [] [] [] [] | - screem | | - scrollkeeper | [] [] [] [] [] [] [] | - sed | [] [] [] [] [] [] [] [] [] | - sh-utils | [] [] [] | - shared-mime-info | [] [] [] [] [] | - sharutils | [] [] [] [] | - shishi | [] | - silky | [] | - skencil | [] [] [] | - sketch | [] [] [] | - solfege | [] | - soundtracker | [] [] | - sp | | - stardict | [] [] [] | - system-tools-ba... | [] [] [] [] [] [] [] [] [] | - tar | [] [] [] [] [] | - texinfo | [] [] [] [] | - textutils | [] [] [] | - tin | () | - tp-robot | [] | - tuxpaint | [] [] [] [] [] | - unicode-han-tra... | | - unicode-transla... | | - util-linux | [] [] [] [] | - vorbis-tools | [] [] | - wastesedge | | - wdiff | [] [] [] [] [] [] | - wget | [] [] [] [] | - xchat | [] [] [] [] [] [] [] | - xkeyboard-config | [] [] | - xpad | [] [] [] | - +------------------------------------------------------+ - nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta - 0 2 3 58 31 53 5 76 72 5 42 48 12 51 130 2 + crh cs da de el en en_GB en_ZA eo es et eu fa + +-------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] () | + anubis | [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] | + bfd | [] | + bibshelf | [] [] [] | + binutils | [] | + bison | [] [] | + bison-runtime | [] [] [] [] | + bluez-pin | [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] [] [] | + cflow | [] [] | + clisp | [] [] [] [] | + coreutils | [] [] [] [] | + cpio | | + cppi | | + cpplib | [] [] [] | + cryptsetup | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] | + doodle | [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] | + exif | () [] [] | + fetchmail | [] [] () [] [] [] | + findutils | [] [] [] | + flex | [] [] | + freedink | [] [] [] | + gas | [] | + gawk | [] [] [] | + gcal | [] | + gcc | [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] [] [] | + gip | [] [] [] [] | + gjay | [] | + gliv | [] [] [] | + glunarclock | [] [] | + gnubiff | () | + gnucash | [] () () () () | + gnuedu | [] [] | + gnulib | [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] | + gpe-aerial | [] [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] | + gpe-conf | [] [] [] | + gpe-contacts | [] [] [] | + gpe-edit | [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] () [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] | + grub | [] [] | + gsasl | [] | + gss | | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] () [] | + gtkam | [] [] () [] [] | + gtkorphan | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | [] [] [] | + hello | [] [] [] [] | + help2man | [] | + hylafax | [] [] | + idutils | [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] [] [] [] () [] [] [] () | + iso_3166_2 | () | + iso_4217 | [] [] [] () [] [] | + iso_639 | [] [] [] [] () [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | [] [] [] [] [] | + keytouch | [] [] | + keytouch-editor | [] [] | + keytouch-keyboa... | [] | + klavaro | [] [] [] [] | + latrine | [] () | + ld | [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | [] [] | + libgphoto2 | [] () | + libgphoto2_port | [] () [] | + libgsasl | | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + lifelines | [] () | + liferea | [] [] [] [] [] | + lilypond | [] [] [] | + linkdr | [] [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] | + make | [] [] [] | + man-db | | + man-db-manpages | | + minicom | [] [] [] [] | + mkisofs | | + myserver | | + nano | [] [] [] | + opcodes | [] [] | + parted | [] [] | + pies | | + popt | [] [] [] [] [] | + psmisc | [] [] [] | + pspp | [] | + pwdutils | [] | + radius | [] | + recode | [] [] [] [] [] [] | + rosegarden | () () () | + rpm | [] [] [] | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] | + sed | [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | | + skencil | [] () [] | + solfege | [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] [] | + sp | [] | + sysstat | [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] | + tin | [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] | + vice | () () | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] | + wyslij-po | | + xchat | [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] | + +-------------------------------------------------+ + crh cs da de el en en_GB en_ZA eo es et eu fa + 5 64 105 117 18 1 8 0 28 89 18 19 0 + + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + +----------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] [] | + ant-phone | [] [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] [] | + bibshelf | [] [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] | + cflow | [] [] [] | + clisp | [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] | + cppi | [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] [] [] [] | + dink | [] | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] | + freedink | [] [] [] | + gas | [] [] | + gawk | [] [] [] [] () [] | + gcal | [] | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] | + gip | [] [] [] [] [] [] | + gjay | [] | + gliv | [] () | + glunarclock | [] [] [] [] | + gnubiff | () [] () | + gnucash | () () () () () [] | + gnuedu | [] [] | + gnulib | [] [] [] [] [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] [] | + gpe-aerial | [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] [] [] | + gpe-calendar | [] [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] [] [] | + gpe-contacts | [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] [] | + gpe-go | [] [] [] [] [] | + gpe-login | [] [] [] | + gpe-ownerinfo | [] [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] [] [] | + hello | [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] [] | + indent | [] [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | () [] [] [] | + iso_4217 | [] () [] [] [] [] | + iso_639 | [] () [] [] [] [] [] [] [] | + iso_639_3 | () [] [] | + jwhois | [] [] [] [] [] | + kbd | [] [] | + keytouch | [] [] [] [] [] [] | + keytouch-editor | [] [] [] [] [] | + keytouch-keyboa... | [] [] [] [] [] | + klavaro | [] [] | + latrine | [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] | + libidn | [] [] [] [] | + lifelines | () | + liferea | [] [] [] [] | + lilypond | [] [] | + linkdr | [] [] [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | | + mailutils | [] [] | + make | [] [] [] [] [] [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] [] | + myserver | | + nano | [] [] [] [] [] [] | + opcodes | [] [] [] [] | + parted | [] [] [] [] | + pies | | + popt | [] [] [] [] [] [] [] [] [] | + psmisc | [] [] [] | + pspp | | + pwdutils | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () () () () | + rpm | [] [] | + rush | | + sarg | [] | + screem | [] [] | + scrollkeeper | [] [] [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] [] | + shishi | [] | + skencil | [] | + solfege | [] [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] | + sp | [] () | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux-ng | [] [] [] [] [] [] | + vice | () () () | + vmm | [] | + vorbis-tools | [] | + wastesedge | () () | + wdiff | [] | + wget | [] [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] | + +----------------------------------------------------+ + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 + + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + +-----------------------------------------------+ + a2ps | [] | + aegis | | + ant-phone | | + anubis | [] [] | + aspell | [] | + bash | | + bfd | | + bibshelf | [] [] | + binutils | | + bison | [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] | + bombono-dvd | | + buzztard | | + cflow | | + clisp | | + coreutils | [] | + cpio | | + cppi | | + cpplib | | + cryptsetup | | + dfarc | [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] | + dink | | + doodle | | + e2fsprogs | | + enscript | | + exif | [] | + fetchmail | | + findutils | | + flex | | + freedink | [] | + gas | | + gawk | | + gcal | | + gcc | | + gettext-examples | [] [] [] [] | + gettext-runtime | [] | + gettext-tools | [] | + gip | [] [] | + gjay | | + gliv | | + glunarclock | [] | + gnubiff | | + gnucash | () () () () | + gnuedu | | + gnulib | | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gold | | + gpe-aerial | [] | + gpe-beam | [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] | + gpe-contacts | [] [] | + gpe-edit | [] | + gpe-filemanager | [] [] | + gpe-go | [] [] [] | + gpe-login | [] | + gpe-ownerinfo | [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] | + gpe-timesheet | [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | | + gsasl | | + gss | | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | | + gtick | | + gtkam | [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | | + hello | [] [] [] | + help2man | | + hylafax | | + idutils | | + indent | | + iso_15924 | [] [] | + iso_3166 | [] [] () [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] | + iso_639 | [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | [] | + ld | | + leafpad | [] [] [] | + libc | [] | + libexif | | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | | + libidn | | + lifelines | | + liferea | | + lilypond | | + linkdr | | + lordsawar | | + lprng | | + lynx | | + m4 | | + mailfromd | | + mailutils | | + make | [] | + man-db | | + man-db-manpages | | + minicom | [] | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | [] [] [] | + psmisc | | + pspp | | + pwdutils | | + radius | | + recode | | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] | + sed | | + sharutils | | + shishi | | + skencil | | + solfege | [] | + solfege-manual | | + soundtracker | | + sp | | + sysstat | [] | + tar | [] | + texinfo | [] | + tin | | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] | + wyslij-po | | + xchat | [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +-----------------------------------------------+ + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 + + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + +---------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] | + bfd | [] | + bibshelf | [] [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] () | + buzztard | [] [] | + cflow | [] | + clisp | [] [] | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] | + cppi | [] | + cpplib | [] | + cryptsetup | [] | + dfarc | [] | + dialog | [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] [] | + dink | () | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] [] | + exif | [] [] [] () [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] | + gas | | + gawk | [] [] [] [] | + gcal | | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] | + gip | [] [] [] [] [] | + gjay | | + gliv | [] [] [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | [] () | + gnucash | [] () () () | + gnuedu | [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gnutls | [] [] | + gold | | + gpe-aerial | [] [] [] [] [] [] [] | + gpe-beam | [] [] [] [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] [] [] [] [] | + gpe-conf | [] [] [] [] [] [] [] | + gpe-contacts | [] [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] [] [] [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] [] [] [] [] [] | + gpe-su | [] [] [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] [] | + gpe-todo | [] [] [] [] [] | + gphoto2 | [] [] [] [] [] [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] | + gramadoir | [] [] | + grep | [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkorphan | [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] | + hello | [] [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] [] [] [] | + iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] [] | + iso_4217 | [] [] [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + jwhois | [] [] [] [] | + kbd | [] [] [] | + keytouch | [] [] [] | + keytouch-editor | [] [] [] | + keytouch-keyboa... | [] [] [] | + klavaro | [] [] | + latrine | [] [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] | + lifelines | [] [] | + liferea | [] [] [] [] [] () () [] | + lilypond | [] | + linkdr | [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] | + pies | [] | + popt | [] [] [] [] | + psmisc | [] [] [] | + pspp | [] [] | + pwdutils | [] | + radius | [] [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () | + rpm | [] [] [] | + rush | [] [] | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] | + skencil | [] [] | + solfege | [] [] [] [] | + solfege-manual | [] [] [] | + soundtracker | [] | + sp | | + sysstat | [] [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] [] | + vice | [] | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 - tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu + sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW +---------------------------------------------------+ - GNUnet | [] | 2 - a2ps | [] [] [] | 19 - aegis | | 0 - ant-phone | [] [] | 6 - anubis | [] [] [] | 11 - ap-utils | () [] | 4 - aspell | [] [] [] | 14 - bash | [] | 11 - batchelor | [] [] | 9 - bfd | | 1 - bibshelf | [] | 7 - binutils | [] [] [] | 9 - bison | [] [] [] | 19 - bison-runtime | [] [] [] | 16 - bluez-pin | [] [] [] [] [] [] | 28 - cflow | [] [] | 4 - clisp | | 6 - console-tools | [] [] | 5 - coreutils | [] [] | 17 - cpio | [] [] [] | 9 - cpplib | [] [] [] [] | 11 - cryptonit | | 5 - darkstat | [] () () | 15 - dialog | [] [] [] [] [] | 30 - diffutils | [] [] [] [] | 28 - doodle | [] | 6 - e2fsprogs | [] [] | 10 - enscript | [] [] [] | 16 - error | [] [] [] [] | 18 - fetchmail | [] [] | 12 - fileutils | [] [] [] | 18 - findutils | [] [] [] | 17 - flex | [] [] | 15 - fslint | [] | 9 - gas | [] | 3 - gawk | [] [] | 15 - gbiff | [] | 5 - gcal | [] | 5 - gcc | [] [] [] | 6 - gettext-examples | [] [] [] [] [] [] | 26 - gettext-runtime | [] [] [] [] [] [] | 28 - gettext-tools | [] [] [] [] [] | 19 - gimp-print | [] [] | 12 - gip | [] [] | 12 - gliv | [] [] | 8 - glunarclock | [] [] [] | 15 - gmult | [] [] [] [] | 15 - gnubiff | [] | 1 - gnucash | () | 2 - gnucash-glossary | [] [] | 9 - gnuedu | [] | 2 - gnulib | [] [] [] [] [] | 28 - gnunet-gtk | | 1 - gnutls | | 2 - gpe-aerial | [] [] | 14 - gpe-beam | [] [] | 14 - gpe-calendar | [] [] [] [] | 19 - gpe-clock | [] [] [] [] | 20 - gpe-conf | [] [] | 14 - gpe-contacts | [] [] | 10 - gpe-edit | [] [] [] [] | 19 - gpe-filemanager | [] | 5 - gpe-go | [] [] | 14 - gpe-login | [] [] [] [] [] | 20 - gpe-ownerinfo | [] [] [] [] | 20 - gpe-package | [] | 5 - gpe-sketchbook | [] [] | 16 - gpe-su | [] [] [] | 19 - gpe-taskmanager | [] [] [] | 19 - gpe-timesheet | [] [] [] [] | 18 - gpe-today | [] [] [] [] [] | 20 - gpe-todo | [] | 6 - gphoto2 | [] [] [] [] | 20 - gprof | [] [] | 11 - gpsdrive | | 4 - gramadoir | [] | 7 - grep | [] [] [] [] | 33 - gretl | | 4 - gsasl | [] [] | 6 - gss | [] | 5 - gst-plugins | [] [] [] | 15 - gst-plugins-base | [] [] [] | 9 - gst-plugins-good | [] [] [] | 18 - gstreamer | [] [] [] | 17 - gtick | [] | 11 - gtkam | [] | 13 - gtkorphan | [] | 7 - gtkspell | [] [] [] [] [] [] | 26 - gutenprint | | 3 - hello | [] [] [] [] [] | 39 - id-utils | [] [] | 14 - impost | [] | 4 - indent | [] [] [] [] | 25 - iso_3166 | [] [] [] | 15 - iso_3166_1 | [] [] | 20 - iso_3166_2 | | 2 - iso_3166_3 | [] [] | 9 - iso_4217 | [] [] | 14 - iso_639 | [] | 14 - jpilot | [] [] [] [] | 7 - jtag | [] | 3 - jwhois | [] [] [] | 13 - kbd | [] [] | 12 - keytouch | [] | 4 - keytouch-editor | | 2 - keytouch-keyboa... | | 2 - latrine | [] [] | 8 - ld | [] [] [] [] | 8 - leafpad | [] [] [] [] | 23 - libc | [] [] [] | 23 - libexif | [] | 4 - libextractor | [] | 5 - libgpewidget | [] [] [] | 19 - libgpg-error | [] | 4 - libgphoto2 | [] | 8 - libgphoto2_port | [] [] [] | 11 - libgsasl | [] | 8 - libiconv | [] | 4 - libidn | [] [] | 10 - lifelines | | 4 - lilypond | | 2 - lingoteach | [] | 6 - lynx | [] [] [] | 15 - m4 | [] [] [] | 18 - mailutils | [] | 8 - make | [] [] [] | 20 - man-db | [] | 6 - minicom | [] | 14 - mysecretdiary | [] [] | 12 - nano | [] [] | 15 - nano_1_0 | [] [] [] | 18 - opcodes | [] [] | 10 - parted | [] [] [] | 10 - pilot-qof | [] | 3 - psmisc | [] | 10 - pwdutils | [] | 3 - python | | 0 - qof | [] | 2 - radius | [] | 6 - recode | [] [] [] | 25 - rpm | [] [] [] [] | 14 - screem | [] | 2 - scrollkeeper | [] [] [] [] | 26 - sed | [] [] [] | 22 - sh-utils | [] | 15 - shared-mime-info | [] [] [] [] | 23 - sharutils | [] [] [] | 23 - shishi | | 1 - silky | [] | 4 - skencil | [] | 7 - sketch | | 6 - solfege | | 2 - soundtracker | [] [] | 9 - sp | [] | 3 - stardict | [] [] [] [] | 11 - system-tools-ba... | [] [] [] [] [] [] [] | 37 - tar | [] [] [] [] | 19 - texinfo | [] [] [] | 15 - textutils | [] [] [] | 17 - tin | | 1 - tp-robot | [] [] [] | 10 - tuxpaint | [] [] [] | 16 + a2ps | [] [] [] [] [] | 27 + aegis | [] | 9 + ant-phone | [] [] [] [] | 9 + anubis | [] [] [] [] | 15 + aspell | [] [] [] | 20 + bash | [] [] [] | 12 + bfd | [] | 6 + bibshelf | [] [] [] | 16 + binutils | [] [] | 8 + bison | [] [] | 12 + bison-runtime | [] [] [] [] [] [] | 29 + bluez-pin | [] [] [] [] [] [] [] [] | 37 + bombono-dvd | [] | 4 + buzztard | [] | 7 + cflow | [] [] [] | 9 + clisp | | 10 + coreutils | [] [] [] [] | 22 + cpio | [] [] [] [] [] [] | 13 + cppi | [] [] | 5 + cpplib | [] [] [] [] [] [] | 14 + cryptsetup | [] [] | 7 + dfarc | [] | 9 + dialog | [] [] [] [] [] [] [] | 30 + dico | [] | 2 + diffutils | [] [] [] [] [] [] | 30 + dink | | 4 + doodle | [] [] | 7 + e2fsprogs | [] [] [] | 11 + enscript | [] [] [] [] | 17 + exif | [] [] [] | 16 + fetchmail | [] [] [] | 17 + findutils | [] [] [] [] [] | 20 + flex | [] [] [] [] | 15 + freedink | [] | 10 + gas | [] | 4 + gawk | [] [] [] [] | 18 + gcal | [] [] | 5 + gcc | [] [] [] | 7 + gettext-examples | [] [] [] [] [] [] [] | 34 + gettext-runtime | [] [] [] [] [] [] [] | 29 + gettext-tools | [] [] [] [] [] [] | 22 + gip | [] [] [] [] | 22 + gjay | [] | 3 + gliv | [] [] [] | 14 + glunarclock | [] [] [] [] [] | 19 + gnubiff | [] [] | 4 + gnucash | () [] () [] () | 10 + gnuedu | [] [] | 7 + gnulib | [] [] [] [] | 16 + gnunet | [] | 1 + gnunet-gtk | [] [] [] | 5 + gnutls | [] [] [] | 10 + gold | [] | 4 + gpe-aerial | [] [] [] | 18 + gpe-beam | [] [] [] | 19 + gpe-bluetooth | [] [] [] | 13 + gpe-calendar | [] [] [] [] | 12 + gpe-clock | [] [] [] [] [] | 28 + gpe-conf | [] [] [] [] | 20 + gpe-contacts | [] [] [] | 17 + gpe-edit | [] [] [] | 12 + gpe-filemanager | [] [] [] [] | 16 + gpe-go | [] [] [] [] [] | 25 + gpe-login | [] [] [] | 11 + gpe-ownerinfo | [] [] [] [] [] | 25 + gpe-package | [] [] [] | 13 + gpe-sketchbook | [] [] [] | 20 + gpe-su | [] [] [] [] [] | 30 + gpe-taskmanager | [] [] [] [] [] | 29 + gpe-timesheet | [] [] [] [] [] | 25 + gpe-today | [] [] [] [] [] [] | 30 + gpe-todo | [] [] [] [] | 17 + gphoto2 | [] [] [] [] [] | 24 + gprof | [] [] [] | 15 + gpsdrive | [] [] [] | 11 + gramadoir | [] [] [] | 11 + grep | [] [] [] | 10 + grub | [] [] [] | 14 + gsasl | [] [] [] [] | 14 + gss | [] [] [] | 11 + gst-plugins-bad | [] [] [] [] | 26 + gst-plugins-base | [] [] [] [] [] | 24 + gst-plugins-good | [] [] [] [] | 24 + gst-plugins-ugly | [] [] [] [] [] | 29 + gstreamer | [] [] [] [] | 22 + gtick | [] [] [] | 13 + gtkam | [] [] [] | 20 + gtkorphan | [] [] [] | 14 + gtkspell | [] [] [] [] [] [] [] [] [] | 45 + gutenprint | [] | 10 + hello | [] [] [] [] [] [] | 21 + help2man | [] [] | 7 + hylafax | [] | 5 + idutils | [] [] [] [] | 17 + indent | [] [] [] [] [] [] | 30 + iso_15924 | () [] () [] [] | 16 + iso_3166 | [] [] () [] [] () [] [] [] () | 53 + iso_3166_2 | () [] () [] | 9 + iso_4217 | [] () [] [] () [] [] | 26 + iso_639 | [] [] [] () [] () [] [] [] [] | 38 + iso_639_3 | [] () | 8 + jwhois | [] [] [] [] [] | 16 + kbd | [] [] [] [] [] | 15 + keytouch | [] [] [] | 16 + keytouch-editor | [] [] [] | 14 + keytouch-keyboa... | [] [] [] | 14 + klavaro | [] | 11 + latrine | [] [] [] | 10 + ld | [] [] [] [] | 11 + leafpad | [] [] [] [] [] [] | 33 + libc | [] [] [] [] [] | 21 + libexif | [] () | 7 + libextractor | [] | 1 + libgnutls | [] [] [] | 9 + libgpewidget | [] [] [] | 14 + libgpg-error | [] [] [] | 9 + libgphoto2 | [] [] | 8 + libgphoto2_port | [] [] [] [] | 14 + libgsasl | [] [] [] | 13 + libiconv | [] [] [] [] | 21 + libidn | () [] [] | 11 + lifelines | [] | 4 + liferea | [] [] [] | 21 + lilypond | [] | 7 + linkdr | [] [] [] [] [] | 17 + lordsawar | | 1 + lprng | [] | 3 + lynx | [] [] [] [] | 17 + m4 | [] [] [] [] | 19 + mailfromd | [] [] | 3 + mailutils | [] | 5 + make | [] [] [] [] | 21 + man-db | [] [] [] | 8 + man-db-manpages | | 4 + minicom | [] [] | 16 + mkisofs | [] [] | 9 + myserver | | 0 + nano | [] [] [] [] | 21 + opcodes | [] [] [] | 11 + parted | [] [] [] [] [] | 15 + pies | [] [] | 3 + popt | [] [] [] [] [] [] | 27 + psmisc | [] [] | 11 + pspp | | 4 + pwdutils | [] [] | 6 + radius | [] [] | 9 + recode | [] [] [] [] | 28 + rosegarden | () | 0 + rpm | [] [] [] | 11 + rush | [] [] | 4 + sarg | | 1 + screem | [] | 3 + scrollkeeper | [] [] [] [] [] | 27 + sed | [] [] [] [] [] | 30 + sharutils | [] [] [] [] [] | 22 + shishi | [] | 3 + skencil | [] [] | 7 + solfege | [] [] [] [] | 16 + solfege-manual | [] | 8 + soundtracker | [] [] [] | 9 + sp | [] | 3 + sysstat | [] [] | 15 + tar | [] [] [] [] [] [] | 23 + texinfo | [] [] [] [] [] | 17 + tin | | 4 unicode-han-tra... | | 0 unicode-transla... | | 2 - util-linux | [] [] [] | 20 - vorbis-tools | [] [] | 11 - wastesedge | | 1 - wdiff | [] [] | 22 - wget | [] [] [] | 19 - xchat | [] [] [] [] | 28 - xkeyboard-config | [] [] [] [] | 11 - xpad | [] [] [] | 14 + util-linux-ng | [] [] [] [] | 20 + vice | () () | 1 + vmm | [] | 4 + vorbis-tools | [] | 6 + wastesedge | | 2 + wdiff | [] [] | 7 + wget | [] [] [] [] [] | 26 + wyslij-po | [] [] | 8 + xchat | [] [] [] [] [] [] | 36 + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 + xkeyboard-config | [] [] [] | 22 +---------------------------------------------------+ - 77 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu - 172 domains 0 1 1 78 39 0 135 13 1 50 3 54 0 2054 + 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW + 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are @@ -1085,12 +1256,12 @@ distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. - If July 2006 seems to be old, you may fetch a more recent copy of + If June 2010 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at -`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. +`http://translationproject.org/extra/matrix.html'. -1.6 Using `gettext' in new packages +1.5 Using `gettext' in new packages =================================== If you are writing a freely available program and want to @@ -1106,6 +1277,6 @@ the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact -`translation@iro.umontreal.ca' to make the `.pot' files available to -the translation teams. +`coordinator@translationproject.org' to make the `.pot' files available +to the translation teams. diff --git a/AUTHORS b/AUTHORS index 38c73fc..f4e5175 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,4 @@ Jana Saout Clemens Fruhwirth Milan Broz +Ondrej Kozina diff --git a/ChangeLog b/ChangeLog index e056c5c..b6c11ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,4 +3,4 @@ Since version 1.6 this file is no longer maintained. See docs/*ReleaseNotes for release changes documentation. See version control history for full commit messages. - http://code.google.com/p/cryptsetup/source/list + https://gitlab.com/cryptsetup/cryptsetup/commits/master diff --git a/FAQ b/FAQ index 08b52ad..31060dd 100644 --- a/FAQ +++ b/FAQ @@ -1,5 +1,6 @@ -Sections +Frequently Asked Questions Cryptsetup/LUKS +Sections 1. General Questions 2. Setup 3. Common Problems @@ -8,134 +9,145 @@ Sections 6. Backup and Data Recovery 7. Interoperability with other Disk Encryption Tools 8. Issues with Specific Versions of cryptsetup -9. References and Further Reading +9. The Initrd question +10. LUKS2 Questions +11. References and Further Reading A. Contributors - -1. General Questions +1. General Questions - * 1.1 What is this? + * 1.1 What is this? - This is the FAQ (Frequently Asked Questions) for cryptsetup. It - covers Linux disk encryption with plain dm-crypt (one passphrase, - no management, no metadata on disk) and LUKS (multiple user keys - with one master key, anti-forensic features, metadata block at - start of device, ...). The latest version of this FAQ should - usually be available at + This is the FAQ (Frequently Asked Questions) for cryptsetup. It covers + Linux disk encryption with plain dm-crypt (one passphrase, no + management, no metadata on disk) and LUKS (multiple user keys with one + master key, anti-forensic features, metadata block at start of device, + ...). The latest version of this FAQ should usually be available at https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions - * 1.2 WARNINGS - - ATTENTION: If you are going to read just one thing, make it the - section on Backup and Data Recovery. By far the most questions on - the cryptsetup mailing list are from people that managed to damage - the start of their LUKS partitions, i.e. the LUKS header. In - most cases, there is nothing that can be done to help these poor - souls recover their data. Make sure you understand the problem and - limitations imposed by the LUKS security model BEFORE you face - such a disaster! In particular, make sure you have a current header - backup before doing any potentially dangerous operations. - - SSDs/FLASH DRIVES: SSDs and Flash are different. Currently it is - unclear how to get LUKS or plain dm-crypt to run on them with the - full set of security features intact. This may or may not be a - problem, depending on the attacker model. See Section 5.19. - - BACKUP: Yes, encrypted disks die, just as normal ones do. A full - backup is mandatory, see Section "6. Backup and Data Recovery" on - options for doing encrypted backup. - - CLONING/IMAGING: If you clone or image a LUKS container, you make a - copy of the LUKS header and the master key will stay the same! - That means that if you distribute an image to several machines, the - same master key will be used on all of them, regardless of whether - you change the passphrases. Do NOT do this! If you do, a root-user - on any of the machines with a mapped (decrypted) container or a - passphrase on that machine can decrypt all other copies, breaking - security. See also Item 6.15. - - DISTRIBUTION INSTALLERS: Some distribution installers offer to - create LUKS containers in a way that can be mistaken as activation - of an existing container. Creating a new LUKS container on top of - an existing one leads to permanent, complete and irreversible data - loss. It is strongly recommended to only use distribution - installers after a complete backup of all LUKS containers has been - made. - - UBUNTU INSTALLER: In particular the Ubuntu installer seems to be - quite willing to kill LUKS containers in several different ways. - Those responsible at Ubuntu seem not to care very much (it is very - easy to recognize a LUKS container), so treat the process of - installing Ubuntu as a severe hazard to any LUKS container you may - have. - - NO WARNING ON NON-INTERACTIVE FORMAT: If you feed cryptsetup from - STDIN (e.g. via GnuPG) on LUKS format, it does not give you the - warning that you are about to format (and e.g. will lose any - pre-existing LUKS container on the target), as it assumes it is - used from a script. In this scenario, the responsibility for - warning the user and possibly checking for an existing LUKS header - is shifted to the script. This is a more general form of the - previous item. - - LUKS PASSPHRASE IS NOT THE MASTER KEY: The LUKS passphrase is not - used in deriving the master key. It is used in decrypting a master - key that is randomly selected on header creation. This means that - if you create a new LUKS header on top of an old one with - exactly the same parameters and exactly the same passphrase as the - old one, it will still have a different master key and your data - will be permanently lost. - - PASSPHRASE CHARACTER SET: Some people have had difficulties with - this when upgrading distributions. It is highly advisable to only - use the 95 printable characters from the first 128 characters of - the ASCII table, as they will always have the same binary - representation. Other characters may have different encoding - depending on system configuration and your passphrase will not - work with a different encoding. A table of the standardized first - 128 ASCII characters can, e.g. be found on + * 1.2 WARNINGS + + LUKS2 COMPATIBILITY: This FAQ was originally written for LUKS1, not + LUKS2. Hence regarding LUKS2, some of the answers found here may not + apply. Updates for LUKS2 have been done and anything not applying to + LUKS2 should clearly say LUKS1. However, this is a Frequently Asked + Questions, and questions for LUKS2 are limited at this time or at least + those that have reached me are. In the following, "LUKS" refers to both + LUKS1 and LUKS2. + + The LUKS1 on-disk format specification is at + https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf + The LUKS2 on-disk format specification is at + https://gitlab.com/cryptsetup/LUKS2-docs + + ATTENTION: If you are going to read just one thing, make it the section + on Backup and Data Recovery. By far the most questions on the + cryptsetup mailing list are from people that managed to damage the start + of their LUKS partitions, i.e. the LUKS header. In most cases, there + is nothing that can be done to help these poor souls recover their data. + Make sure you understand the problem and limitations imposed by the LUKS + security model BEFORE you face such a disaster! In particular, make + sure you have a current header backup before doing any potentially + dangerous operations. The LUKS2 header should be a bit more resilient + as critical data starts later and is stored twice, but you can decidely + still destroy it or a keyslot permanently by accident. + + DEBUG COMMANDS: While the --debug and --debug-json options should not + leak secret data, "strace" and the like can leak your full passphrase. + Do not post an strace output with the correct passphrase to a + mailing-list or online! See Item 4.5 for more explanation. + + SSDs/FLASH DRIVES: SSDs and Flash are different. Currently it is + unclear how to get LUKS or plain dm-crypt to run on them with the full + set of security assurances intact. This may or may not be a problem, + depending on the attacker model. See Section 5.19. + + BACKUP: Yes, encrypted disks die, just as normal ones do. A full backup + is mandatory, see Section "6. Backup and Data Recovery" on options for + doing encrypted backup. + + CLONING/IMAGING: If you clone or image a LUKS container, you make a copy + of the LUKS header and the master key will stay the same! That means + that if you distribute an image to several machines, the same master key + will be used on all of them, regardless of whether you change the + passphrases. Do NOT do this! If you do, a root-user on any of the + machines with a mapped (decrypted) container or a passphrase on that + machine can decrypt all other copies, breaking security. See also Item + 6.15. + + DISTRIBUTION INSTALLERS: Some distribution installers offer to create + LUKS containers in a way that can be mistaken as activation of an + existing container. Creating a new LUKS container on top of an existing + one leads to permanent, complete and irreversible data loss. It is + strongly recommended to only use distribution installers after a + complete backup of all LUKS containers has been made. + + UBUNTU INSTALLER: In particular the Ubuntu installer seems to be quite + willing to kill LUKS containers in several different ways. Those + responsible at Ubuntu seem not to care very much (it is very easy to + recognize a LUKS container), so treat the process of installing Ubuntu + as a severe hazard to any LUKS container you may have. + + NO WARNING ON NON-INTERACTIVE FORMAT: If you feed cryptsetup from STDIN + (e.g. via GnuPG) on LUKS format, it does not give you the warning that + you are about to format (and e.g. will lose any pre-existing LUKS + container on the target), as it assumes it is used from a script. In + this scenario, the responsibility for warning the user and possibly + checking for an existing LUKS header is shifted to the script. This is + a more general form of the previous item. + + LUKS PASSPHRASE IS NOT THE MASTER KEY: The LUKS passphrase is not used + in deriving the master key. It is used in decrypting a master key that + is randomly selected on header creation. This means that if you create + a new LUKS header on top of an old one with exactly the same parameters + and exactly the same passphrase as the old one, it will still have a + different master key and your data will be permanently lost. + + PASSPHRASE CHARACTER SET: Some people have had difficulties with this + when upgrading distributions. It is highly advisable to only use the 95 + printable characters from the first 128 characters of the ASCII table, + as they will always have the same binary representation. Other + characters may have different encoding depending on system configuration + and your passphrase will not work with a different encoding. A table of + the standardized first 128 ASCII characters can, e.g. be found on http://en.wikipedia.org/wiki/ASCII + KEYBOARD NUM-PAD: Apparently some pre-boot authentication environments + (these are done by the distro, not by cryptsetup, so complain there) + treat digits entered on the num-pad and ones entered regularly + different. This may be because the BIOS USB keyboard driver is used and + that one may have bugs on some computers. If you cannot open your + device in pre-boot, try entering the digits over the regular digit keys. - * 1.3 System specific warnings - - - Ubuntu as of 4/2011: It seems the installer offers to create - LUKS partitions in a way that several people mistook for an offer - to activate their existing LUKS partition. The installer gives no - or an inadequate warning and will destroy your old LUKS header, - causing permanent data loss. See also the section on Backup and - Data Recovery. - This issue has been acknowledged by the Ubuntu dev team, see here: - http://launchpad.net/bugs/420080 + * 1.3 System specific warnings - Update 4/2013: I am still unsure whether this has been fixed by - now, best be careful. They also seem to have added even more LUKS - killer functionality to the Ubuntu installer. I can only strongly - recommended to not install Ubuntu on a system with existing LUKS - containers without complete backups. + - The Ubuntu Natty uinstaller has a "won't fix" defect that may destroy + LUKS containers. This is quite old an not relevant for most people. + Reference: + https://bugs.launchpad.net/ubuntu/+source/partman-crypto/+bug/420080 - * 1.4 My LUKS-device is broken! Help! + * 1.4 My LUKS-device is broken! Help! First: Do not panic! In many cases the data is still recoverable. Do not do anything hasty! Steps: - - Take some deep breaths. Maybe add some relaxing music. This may - sound funny, but I am completely serious. Often, critical damage is + - Take some deep breaths. Maybe add some relaxing music. This may + sound funny, but I am completely serious. Often, critical damage is done only after the initial problem. - - Do not reboot. The keys mays still be in the kernel if the device - is mapped. + - Do not reboot. The keys may still be in the kernel if the device is + mapped. - Make sure others do not reboot the system. - - Do not write to your disk without a clear understanding why this - will not make matters worse. Do a sector-level backup before any - writes. Often you do not need to write at all to get enough access - to make a backup of the data. + - Do not write to your disk without a clear understanding why this will + not make matters worse. Do a sector-level backup before any writes. + Often you do not need to write at all to get enough access to make a + backup of the data. - Relax some more. @@ -144,1962 +156,2113 @@ A. Contributors - Ask on the mailing-list if you need more help. - * 1.5 Who wrote this? + * 1.5 Who wrote this? - Current FAQ maintainer is Arno Wagner . If you - want to send me encrypted email, my current PGP key is DSA key - CB5D9718, fingerprint 12D6 C03B 1B30 33BB 13CF B774 E35C 5FA1 CB5D - 9718. + Current FAQ maintainer is Arno Wagner . If you want + to send me encrypted email, my current PGP key is DSA key CB5D9718, + fingerprint 12D6 C03B 1B30 33BB 13CF B774 E35C 5FA1 CB5D 9718. - Other contributors are listed at the end. If you want to contribute, - send your article, including a descriptive headline, to the - maintainer, or the dm-crypt mailing list with something like "FAQ - ..." in the subject. You can also send more raw information and - have me write the section. Please note that by contributing to this - FAQ, you accept the license described below. + Other contributors are listed at the end. If you want to contribute, + send your article, including a descriptive headline, to the maintainer, + or the dm-crypt mailing list with something like "FAQ ..." + in the subject. You can also send more raw information and have + me write the section. Please note that by contributing to this FAQ, + you accept the license described below. - This work is under the "Attribution-Share Alike 3.0 Unported" - license, which means distribution is unlimited, you may create - derived works, but attributions to original authors and this - license statement must be retained and the derived work must be - under the same license. See - http://creativecommons.org/licenses/by-sa/3.0/ for more details of - the license. + This work is under the "Attribution-Share Alike 3.0 Unported" license, + which means distribution is unlimited, you may create derived works, but + attributions to original authors and this license statement must be + retained and the derived work must be under the same license. See + http://creativecommons.org/licenses/by-sa/3.0/ for more details of the + license. - Side note: I did text license research some time ago and I think - this license is best suited for the purpose at hand and creates the - least problems. + Side note: I did text license research some time ago and I think this + license is best suited for the purpose at hand and creates the least + problems. - * 1.6 Where is the project website? + * 1.6 Where is the project website? - There is the project website at https://gitlab.com/cryptsetup/cryptsetup/ - Please do not post questions there, nobody will read them. Use - the mailing-list instead. + There is the project website at + https://gitlab.com/cryptsetup/cryptsetup/ Please do not post + questions there, nobody will read them. Use the mailing-list + instead. - * 1.7 Is there a mailing-list? + * 1.7 Is there a mailing-list? Instructions on how to subscribe to the mailing-list are at on the - project website. People are generally helpful and friendly on the + project website. People are generally helpful and friendly on the list. - The question of how to unsubscribe from the list does crop up - sometimes. For this you need your list management URL, which is - sent to you initially and once at the start of each month. Go to - the URL mentioned in the email and select "unsubscribe". This page - also allows you to request a password reminder. + The question of how to unsubscribe from the list does crop up sometimes. + For this you need your list management URL, which is sent to you + initially and once at the start of each month. Go to the URL mentioned + in the email and select "unsubscribe". This page also allows you to + request a password reminder. - Alternatively, you can send an Email to dm-crypt-request@saout.de - with just the word "help" in the subject or message body. Make sure - to send it from your list address. + Alternatively, you can send an Email to dm-crypt-request@saout.de with + just the word "help" in the subject or message body. Make sure to send + it from your list address. The mailing list archive is here: - http://dir.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt + https://marc.info/?l=dm-crypt - * 1.8 Unsubscribe from the mailing-list + * 1.8 Unsubscribe from the mailing-list - Send mail to dm-crypt-unsubscribe@saout.de from the subscribed - account. You will get an email with instructions. + Send mail to dm-crypt-unsubscribe@saout.de from the subscribed account. + You will get an email with instructions. Basically, you just have to respond to it unmodified to get - unsubscribed. The listserver admin functions are not very fast. It - can take 15 minutes or longer for a reply to arrive (I suspect - greylisting is in use), so be patient. + unsubscribed. The listserver admin functions are not very fast. It can + take 15 minutes or longer for a reply to arrive (I suspect greylisting + is in use), so be patient. - Also note that nobody on the list can unsubscribe you, sending - demands to be unsubscribed to the list just annoys people that are - entirely blameless for you being subscribed. + Also note that nobody on the list can unsubscribe you, sending demands + to be unsubscribed to the list just annoys people that are entirely + blameless for you being subscribed. - If you are subscribed, a subscription confirmation email was sent - to your email account and it had to be answered before the - subscription went active. The confirmation emails from the - listserver have subjects like these (with other numbers): + If you are subscribed, a subscription confirmation email was sent to + your email account and it had to be answered before the subscription + went active. The confirmation emails from the listserver have subjects + like these (with other numbers): - Subject: confirm 9964cf10..... - - and are sent from dm-crypt-request@saout.de. You should check - whether you have anything like it in your sent email folder. If - you find nothing and are sure you did not confirm, then you should - look into a possible compromise of your email account. + Subject: confirm 9964cf10..... + and are sent from dm-crypt-request@saout.de. You should check whether + you have anything like it in your sent email folder. If you find + nothing and are sure you did not confirm, then you should look into a + possible compromise of your email account. -2. Setup +2. Setup - * 2.1 LUKS Container Setup mini-HOWTO + * 2.1 LUKS Container Setup mini-HOWTO This item tries to give you a very brief list of all the steps you - should go though when creating a new LUKS encrypted container, i.e. + should go though when creating a new LUKS encrypted container, i.e. encrypted disk, partition or loop-file. - 01) All data will be lost, if there is data on the target, make a + 01) All data will be lost, if there is data on the target, make a backup. - 02) Make very sure you have the right target disk, partition or + 02) Make very sure you use the right target disk, partition or loop-file. - 03) If the target was in use previously, it is a good idea to - wipe it before creating the LUKS container in order to remove any - trace of old file systems and data. For example, some users have - managed to run e2fsck on a partition containing a LUKS container, - possibly because of residual ext2 superblocks from an earlier use. - This can do arbitrary damage up to complete and permanent loss of - all data in the LUKS container. + 03) If the target was in use previously, it is a good idea to wipe it + before creating the LUKS container in order to remove any trace of old + file systems and data. For example, some users have managed to run + e2fsck on a partition containing a LUKS container, possibly because of + residual ext2 superblocks from an earlier use. This can do arbitrary + damage up to complete and permanent loss of all data in the LUKS + container. To just quickly wipe file systems (old data may remain), use - wipefs -a - + wipefs -a + To wipe file system and data, use something like - cat /dev/zero > - - This can take a while. To get a progress indicator, you can use - the tool dd_rescue (->google) instead or use my stream meter "wcs" - (source here: http://www.tansi.org/tools/index.html) in the - following fashion: + cat /dev/zero > + + This can take a while. To get a progress indicator, you can use the + tool dd_rescue (->google) instead or use my stream meter "wcs" (source + here: http://www.tansi.org/tools/index.html) in the following fashion: + + cat /dev/zero | wcs > + + Plain "dd" also gives you the progress on a SIGUSR1, see its man-page. - cat /dev/zero | wcs > - Be very sure you have the right target, all data will be lost! - Note that automatic wiping is on the TODO list for cryptsetup, so - at some time in the future this will become unnecessary. + Note that automatic wiping is on the TODO list for cryptsetup, so at + some time in the future this will become unnecessary. - Alternatively, plain cm-crypt can be used for a very fast wipe with + Alternatively, plain dm-crypt can be used for a very fast wipe with crypto-grade randomness, see Item 2.19 - 04) Create the LUKS container: - cryptsetup luksFormat - - Just follow the on-screen instructions. + 04) Create the LUKS container. - Note: Passphrase iteration is determined by cryptsetup depending on - CPU power. On a slow device, this may be lower than you want. I - recently benchmarked this on a Raspberry Pi and it came out at - about 1/15 of the iteration count for a typical PC. If security is - paramount, you may want to increase the time spent in iteration, at - the cost of a slower unlock later. For the Raspberry Pi, using + LUKS1: - cryptsetup luksFormat -i 15000 - - gives you an iteration count and security level equal to an average - PC for passphrase iteration and master-key iteration. If in doubt, - check the iteration counts with + cryptsetup luksFormat --type luks1 - cryptsetup luksDump - - and adjust the iteration count accordingly by creating the container - again with a different iteration time (the number after '-i' is the - iteration time in milicesonds) until your requirements are met. + LUKS2: + + cryptsetup luksFormat --type luks2 + + + Just follow the on-screen instructions. + + Note: Passprase iteration count is based on time and hence security + level depends on CPU power of the system the LUKS container is created + on. For example on a Raspberry Pi and LUKS1, I found some time ago that + the iteration count is 15 times lower than for a regular PC (well, for + my old one). Depending on security requirements, this may need + adjustment. For LUKS1, you can just look at the iteration count on + different systems and select one you like. You can also change the + benchmark time with the -i parameter to create a header for a slower + system. + + For LUKS2, the parameters are more complex. ARGON2 has iteration, + parallelism and memory parameter. cryptsetup actually may adjust the + memory parameter for time scaling. Hence to use -i is the easiest way + to get slower or faster opening (default: 2000 = 2sec). Just make sure + to not drop this too low or you may get a memory parameter that is to + small to be secure. The luksDump command lists the memory parameter of + a created LUKS2 keyslot in kB. That parameter should probably be not + much lower than 100000, i.e. 100MB, but don't take my word for it. 05) Map the container. Here it will be mapped to /dev/mapper/c1: - cryptsetup luksOpen c1 - - 06) (Optionally) wipe the container (make sure you have the right target!): - cat /dev/zero > /dev/mapper/c1 - - Note that this creates a small information leak, as an attacker can - determine whether a 512 byte block is zero if the attacker has - access to the encrypted container multiple times. Typically a - competent attacker that has access multiple times can install a - passphrase sniffer anyways, so this leakage is not very - significant. For getting a progress indicator, see step 03. - - Note that at some time in the future, cryptsetup will do this for - you, but currently it is a TODO list item. - - 07) Create a file system in the mapped container, for example an + + cryptsetup luksOpen c1 + + 06) (Optionally) wipe the container (make sure you have the right + target!): + + cat /dev/zero > /dev/mapper/c1 + + This will take a while. Note that this creates a small information + leak, as an attacker can determine whether a 512 byte block is zero if + the attacker has access to the encrypted container multiple times. + Typically a competent attacker that has access multiple times can + install a passphrase sniffer anyways, so this leakage is not very + significant. For getting a progress indicator, see step 03. + + 07) Create a file system in the mapped container, for example an ext3 file system (any other file system is possible): - mke2fs -j /dev/mapper/c1 - + mke2fs -j /dev/mapper/c1 + 08) Mount your encrypted file system, here on /mnt: - mount /dev/mapper/c1 /mnt - - Done. You can now use the encrypted file system to store data. Be - sure to read though the rest of the FAQ, these are just the very - basics. In particular, there are a number of mistakes that are - easy to make, but will compromise your security. + mount /dev/mapper/c1 /mnt - * 2.2 LUKS on partitions or raw disks? + 09) Make a LUKS header backup and plan for a container backup. + See Section 6 for details. - This is a complicated question, and made more so by the availability - of RAID and LVM. I will try to give some scenarios and discuss - advantages and disadvantages. Note that I say LUKS for simplicity, - but you can do all the things described with plain dm-crypt as well. - Also note that your specific scenario may be so special that most - or even all things I say below do not apply. + Done. You can now use the encrypted file system to store data. Be sure + to read though the rest of the FAQ, these are just the very basics. In + particular, there are a number of mistakes that are easy to make, but + will compromise your security. + + + * 2.2 LUKS on partitions or raw disks? What about RAID? + + Also see Item 2.8. + This is a complicated question, and made more so by the availability of + RAID and LVM. I will try to give some scenarios and discuss advantages + and disadvantages. Note that I say LUKS for simplicity, but you can do + all the things described with plain dm-crypt as well. Also note that + your specific scenario may be so special that most or even all things I + say below do not apply. Be aware that if you add LVM into the mix, things can get very - complicated. Same with RAID but less so. In particular, data - recovery can get exceedingly difficult. Only do so if you have a - really good reason and always remember KISS is what separates an - engineer from an amateur. Of course, if you really need the added - complexity, KISS is satisfied. But be very sure as there is a price - to pay for it. In engineering, complexity is always the enemy and - needs to be fought without mercy when encountered. + complicated. Same with RAID but less so. In particular, data recovery + can get exceedingly difficult. Only add LVM if you have a really good + reason and always remember KISS is what separates an engineer from an + amateur. Of course, if you really need the added complexity, KISS is + satisfied. But be very sure as there is a price to pay for it. In + engineering, complexity is always the enemy and needs to be fought + without mercy when encountered. Also consider using RAID instead of LVM, as at least with the old - superblock format 0.90, the RAID superblock is in the place (end - of disk) where the risk of it permanently damaging the LUKS header - is smallest and you can have your array assembled by the RAID - controller (i.e. the kernel), as it should be. Use partition type - 0xfd for that. I recommend staying away from superblock formats - 1.0, 1.1 and 1.2 unless you really need them. Be aware that you - lose autodetection with them and have to fall back to some - user-space script to do it. + superblock format 0.90, the RAID superblock is in the place (end of + disk) where the risk of it damaging the LUKS header is smallest and you + can have your array assembled by the RAID controller (i.e. the kernel), + as it should be. Use partition type 0xfd for that. I recommend staying + away from superblock formats 1.0, 1.1 and 1.2 unless you really need + them. Scenarios: - (1) Encrypted partition: Just make a partition to your liking, - and put LUKS on top of it and a filesystem into the LUKS container. - This gives you isolation of differently-tasked data areas, just as - ordinary partitioning does. You can have confidential data, - non-confidential data, data for some specific applications, - user-homes, root, etc. Advantages are simplicity as there is a 1:1 - mapping between partitions and filesystems, clear security - functionality and the ability to separate data into different, - independent (!) containers. + (1) Encrypted partition: Just make a partition to your liking, and put + LUKS on top of it and a filesystem into the LUKS container. This gives + you isolation of differently-tasked data areas, just as ordinary + partitioning does. You can have confidential data, non-confidential + data, data for some specific applications, user-homes, root, etc. + Advantages are simplicity as there is a 1:1 mapping between partitions + and filesystems, clear security functionality and the ability to + separate data into different, independent (!) containers. Note that you cannot do this for encrypted root, that requires an - initrd. On the other hand, an initrd is about as vulnerable to a + initrd. On the other hand, an initrd is about as vulnerable to a competent attacker as a non-encrypted root, so there really is no - security advantage to doing it that way. An attacker that wants to - compromise your system will just compromise the initrd or the - kernel itself. The better way to deal with this is to make sure the - root partition does not store any critical data and move that to - additional encrypted partitions. If you really are concerned your - root partition may be sabotaged by somebody with physical access - (that would however strangely not, say, sabotage your BIOS, - keyboard, etc.), protect it in some other way. The PC is just not - set-up for a really secure boot-chain (whatever some people may - claim). - - (2) Fully encrypted raw block device: For this, put LUKS on the - raw device (e.g. /dev/sdb) and put a filesystem into the LUKS - container, no partitioning whatsoever involved. This is very - suitable for things like external USB disks used for backups or - offline data-storage. + security advantage to doing it that way. An attacker that wants to + compromise your system will just compromise the initrd or the kernel + itself. The better way to deal with this is to make sure the root + partition does not store any critical data and to move that to + additional encrypted partitions. If you really are concerned your root + partition may be sabotaged by somebody with physical access (who would + however strangely not, say, sabotage your BIOS, keyboard, etc.), protect + it in some other way. The PC is just not set-up for a really secure + boot-chain (whatever some people may claim). + + (2) Fully encrypted raw block device: For this, put LUKS on the raw + device (e.g. /dev/sdb) and put a filesystem into the LUKS container, no + partitioning whatsoever involved. This is very suitable for things like + external USB disks used for backups or offline data-storage. (3) Encrypted RAID: Create your RAID from partitions and/or full - devices. Put LUKS on top of the RAID device, just if it were an - ordinary block device. Applications are just the same as above, but - you get redundancy. (Side note as many people seem to be unaware of - it: You can do RAID1 with an arbitrary number of components in - Linux.) See also Item 2.8. - - (4) Now, some people advocate doing the encryption below the RAID - layer. That has several serious problems. One is that suddenly - debugging RAID issues becomes much harder. You cannot do automatic - RAID assembly anymore. You need to keep the encryption keys for the - components in sync or manage them somehow. The only possible - advantage is that things may run a little faster as more CPUs do - the encryption, but if speed is a priority over security and - simplicity, you are doing this wrong anyways. A good way to - mitigate a speed issue is to get a CPU that does hardware AES. - - - * 2.3 How do I set up encrypted swap? - - As things that are confidential can end up in swap (keys, - passphrases, etc. are usually protected against being swapped to - disk, but other things may not be), it may be advisable to do - something about the issue. One option is to run without swap, which - generally works well in a desktop-context. It may cause problems - in a server-setting or under special circumstances. The solution to - that is to encrypt swap with a random key at boot-time. + devices. Put LUKS on top of the RAID device, just if it were an + ordinary block device. Applications are just the same as above, but you + get redundancy. (Side note as many people seem to be unaware of it: You + can do RAID1 with an arbitrary number of components in Linux.) See also + Item 2.8. + + (4) Now, some people advocate doing the encryption below the RAID layer. + That has several serious problems. One is that suddenly debugging RAID + issues becomes much harder. You cannot do automatic RAID assembly + anymore. You need to keep the encryption keys for the different RAID + components in sync or manage them somehow. The only possible advantage + is that things may run a little faster as more CPUs do the encryption, + but if speed is a priority over security and simplicity, you are doing + this wrong anyways. A good way to mitigate a speed issue is to get a + CPU that does hardware AES as most do today. + + + * 2.3 How do I set up encrypted swap? + + As things that are confidential can end up in swap (keys, passphrases, + etc. are usually protected against being swapped to disk, but other + things may not be), it may be advisable to do something about the issue. + One option is to run without swap, which generally works well in a + desktop-context. It may cause problems in a server-setting or under + special circumstances. The solution to that is to encrypt swap with a + random key at boot-time. NOTE: This is for Debian, and should work for Debian-derived - distributions. For others you may have to write your own startup - script or use other mechanisms. - - 01) Add the swap partition to /etc/crypttab. A line like the following - should do it: - - swap /dev/ /dev/urandom swap,noearly - - Warning: While Debian refuses to overwrite partitions with a - filesystem or RAID signature on it, if your disk IDs may change - (adding or removing disks, failure of disk during boot, etc.), you - may want to take additional precautions. Yes, this means that your - kernel device names like sda, sdb, ... can change between reboots! - This is not a concern if you have only one disk. One possibility is - to make sure the partition number is not present on additional - disks or also swap there. Another is to encapsulate the swap - partition (by making it a 1-disk RAID1 or by using LVM), so that it - gets a persistent identifier. Specifying it directly by UUID does - not work, unfortunately, as the UUID is part of the swap signature - and that is not visible from the outside due to the encryption and - in addition changes on each reboot with this setup. - - Note: Use /dev/random if you are paranoid or in a potential - low-entropy situation (embedded system, etc.). This may cause the - operation to take a long time during boot. If you are in a "no - entropy" situation, you cannot encrypt swap securely. In this - situation you should find some entropy, also because nothing else - using crypto will be secure, like ssh, ssl or GnuPG. - - Note: The "noearly" option makes sure things like LVM, RAID, etc. - are running. As swap is non-critical for boot, it is fine to start - it late. + distributions. For others you may have to write your own startup script + or use other mechanisms. + + 01) Add the swap partition to /etc/crypttab. A line like the + following should do it: + + swap /dev/ /dev/urandom swap,noearly + + Warning: While Debian refuses to overwrite partitions with a filesystem + or RAID signature on it, as your disk IDs may change (adding or removing + disks, failure of disk during boot, etc.), you may want to take + additional precautions. Yes, this means that your kernel device names + like sda, sdb, ... can change between reboots! This is not a concern + if you have only one disk. One possibility is to make sure the + partition number is not present on additional disks or also swap there. + Another is to encapsulate the swap partition (by making it a 1-partition + RAID1 or by using LVM), as that gets a persistent identifier. + Specifying it directly by UUID does not work, unfortunately, as the UUID + is part of the swap signature and that is not visible from the outside + due to the encryption and in addition changes on each reboot with this + setup. + + Note: Use /dev/random if you are paranoid or in a potential low-entropy + situation (embedded system, etc.). This may cause the operation to take + a long time during boot however. If you are in a "no entropy" + situation, you cannot encrypt swap securely. In this situation you + should find some entropy, also because nothing else using crypto will be + secure, like ssh, ssl or GnuPG. + + Note: The "noearly" option makes sure things like LVM, RAID, etc. are + running. As swap is non-critical for boot, it is fine to start it late. 02) Add the swap partition to /etc/fstab. A line like the following should do it: - /dev/mapper/swap none swap sw 0 0 - - That is it. Reboot or start it manually to activate encrypted swap. + /dev/mapper/swap none swap sw 0 0 + + That is it. Reboot or start it manually to activate encrypted swap. Manual start would look like this: - /etc/init.d/crypdisks start - swapon /dev/mapper/swap - + /etc/init.d/crypdisks start + swapon /dev/mapper/swap + - * 2.4 What is the difference between "plain" and LUKS format? + * 2.4 What is the difference between "plain" and LUKS format? First, unless you happen to understand the cryptographic background - well, you should use LUKS. It does protect the user from a lot of - common mistakes. Plain dm-crypt is for experts. + well, you should use LUKS. It does protect the user from a lot of + common mistakes. Plain dm-crypt is for experts. Plain format is just that: It has no metadata on disk, reads all - parameters from the commandline (or the defaults), derives a - master-key from the passphrase and then uses that to de-/encrypt - the sectors of the device, with a direct 1:1 mapping between - encrypted and decrypted sectors. - - Primary advantage is high resilience to damage, as one damaged - encrypted sector results in exactly one damaged decrypted sector. - Also, it is not readily apparent that there even is encrypted data - on the device, as an overwrite with crypto-grade randomness (e.g. - from /dev/urandom) looks exactly the same on disk. - - Side-note: That has limited value against the authorities. In - civilized countries, they cannot force you to give up a crypto-key - anyways. In quite a few countries around the world, they can force - you to give up the keys (using imprisonment or worse to pressure - you, sometimes without due process), and in the worst case, they - only need a nebulous "suspicion" about the presence of encrypted - data. Sometimes this applies to everybody, sometimes only when you - are suspected of having "illicit data" (definition subject to - change) and sometimes specifically when crossing a border. Note - that this is going on in countries like the US and the UK, to - different degrees and sometimes with courts restricting what the - authorities can actually demand. + parameters from the commandline (or the defaults), derives a master-key + from the passphrase and then uses that to de-/encrypt the sectors of the + device, with a direct 1:1 mapping between encrypted and decrypted + sectors. + + Primary advantage is high resilience to damage, as one damaged encrypted + sector results in exactly one damaged decrypted sector. Also, it is not + readily apparent that there even is encrypted data on the device, as an + overwrite with crypto-grade randomness (e.g. from + /dev/urandom) looks exactly the same on disk. + + Side-note: That has limited value against the authorities. In civilized + countries, they cannot force you to give up a crypto-key anyways. In + quite a few countries around the world, they can force you to give up + the keys (using imprisonment or worse to pressure you, sometimes without + due process), and in the worst case, they only need a nebulous + "suspicion" about the presence of encrypted data. Sometimes this + applies to everybody, sometimes only when you are suspected of having + "illicit data" (definition subject to change) and sometimes specifically + when crossing a border. Note that this is going on in countries like + the US and the UK to different degrees and sometimes with courts + restricting what the authorities can actually demand. My advice is to either be ready to give up the keys or to not have encrypted data when traveling to those countries, especially when - crossing the borders. The latter also means not having any - high-entropy (random) data areas on your disk, unless you can - explain them and demonstrate that explanation. Hence doing a - zero-wipe of all free space, including unused space, may be a good - idea. - - Disadvantages are that you do not have all the nice features that - the LUKS metadata offers, like multiple passphrases that can be - changed, the cipher being stored in the metadata, anti-forensic - properties like key-slot diffusion and salts, etc.. - - LUKS format uses a metadata header and 8 key-slot areas that are - being placed at the beginning of the disk, see below under "What - does the LUKS on-disk format looks like?". The passphrases are used - to decrypt a single master key that is stored in the anti-forensic - stripes. + crossing the borders. The latter also means not having any high-entropy + (random) data areas on your disk, unless you can explain them and + demonstrate that explanation. Hence doing a zero-wipe of all free + space, including unused space, may be a good idea. + + Disadvantages are that you do not have all the nice features that the + LUKS metadata offers, like multiple passphrases that can be changed, the + cipher being stored in the metadata, anti-forensic properties like + key-slot diffusion and salts, etc.. + + LUKS format uses a metadata header and 8 key-slot areas that are being + placed at the beginning of the disk, see below under "What does the LUKS + on-disk format looks like?". The passphrases are used to decrypt a + single master key that is stored in the anti-forensic stripes. LUKS2 + adds some more flexibility. Advantages are a higher usability, automatic configuration of - non-default crypto parameters, defenses against low-entropy - passphrases like salting and iterated PBKDF2 passphrase hashing, - the ability to change passphrases, and others. + non-default crypto parameters, defenses against low-entropy passphrases + like salting and iterated PBKDF2 or ARGON 2 passphrase hashing, the + ability to change passphrases, and others. - Disadvantages are that it is readily obvious there is encrypted - data on disk (but see side note above) and that damage to the - header or key-slots usually results in permanent data-loss. See - below under "6. Backup and Data Recovery" on how to reduce that - risk. Also the sector numbers get shifted by the length of the - header and key-slots and there is a loss of that size in capacity - (1MB+4096B for defaults and 2MB for the most commonly used - non-default XTS mode). + Disadvantages are that it is readily obvious there is encrypted data on + disk (but see side note above) and that damage to the header or + key-slots usually results in permanent data-loss. See below under "6. + Backup and Data Recovery" on how to reduce that risk. Also the sector + numbers get shifted by the length of the header and key-slots and there + is a loss of that size in capacity. Unless you have a specific need, + use LUKS2. - * 2.5 Can I encrypt an already existing, non-empty partition to use - LUKS? + * 2.5 Can I encrypt an existing, non-empty partition to use LUKS? - There is no converter, and it is not really needed. The way to do - this is to make a backup of the device in question, securely wipe - the device (as LUKS device initialization does not clear away old - data), do a luksFormat, optionally overwrite the encrypted device, - create a new filesystem and restore your backup on the now - encrypted device. Also refer to sections "Security Aspects" and - "Backup and Data Recovery". + There is no converter, and it is not really needed. The way to do this + is to make a backup of the device in question, securely wipe the device + (as LUKS device initialization does not clear away old data), do a + luksFormat, optionally overwrite the encrypted device, create a new + filesystem and restore your backup on the now encrypted device. Also + refer to sections "Security Aspects" and "Backup and Data Recovery". - For backup, plain GNU tar works well and backs up anything likely - to be in a filesystem. + For backup, plain GNU tar works well and backs up anything likely to be + in a filesystem. - * 2.6 How do I use LUKS with a loop-device? + * 2.6 How do I use LUKS with a loop-device? - This can be very handy for experiments. Setup is just the same as - with any block device. If you want, for example, to use a 100MiB - file as LUKS container, do something like this: + This can be very handy for experiments. Setup is just the same as with + any block device. If you want, for example, to use a 100MiB file as + LUKS container, do something like this: + + head -c 100M /dev/zero > luksfile # create empty file + losetup /dev/loop0 luksfile # map file to /dev/loop0 + cryptsetup luksFormat --type luks2 /dev/loop0 # create LUKS2 container - head -c 100M /dev/zero > luksfile # create empty file - losetup /dev/loop0 luksfile # map luksfile to /dev/loop0 - cryptsetup luksFormat /dev/loop0 # create LUKS on loop device - Afterwards just use /dev/loop0 as a you would use a LUKS partition. To unmap the file when done, use "losetup -d /dev/loop0". - * 2.7 When I add a new key-slot to LUKS, it asks for a passphrase but - then complains about there not being a key-slot with that - passphrase? + * 2.7 When I add a new key-slot to LUKS, it asks for a passphrase + but then complains about there not being a key-slot with that + passphrase? - That is as intended. You are asked a passphrase of an existing - key-slot first, before you can enter the passphrase for the new - key-slot. Otherwise you could break the encryption by just adding a - new key-slot. This way, you have to know the passphrase of one of - the already configured key-slots in order to be able to configure a - new key-slot. + That is as intended. You are asked a passphrase of an existing key-slot + first, before you can enter the passphrase for the new key-slot. + Otherwise you could break the encryption by just adding a new key-slot. + This way, you have to know the passphrase of one of the already + configured key-slots in order to be able to configure a new key-slot. - * 2.8 Encryption on top of RAID or the other way round? + * 2.8 Encryption on top of RAID or the other way round? + Also see Item 2.2. Unless you have special needs, place encryption between RAID and - filesystem, i.e. encryption on top of RAID. You can do it the other + filesystem, i.e. encryption on top of RAID. You can do it the other way round, but you have to be aware that you then need to give the - passphrase for each individual disk and RAID autodetection will - not work anymore. Therefore it is better to encrypt the RAID - device, e.g. /dev/dm0 . + passphrase for each individual disk and RAID auto-detection will not + work anymore. Therefore it is better to encrypt the RAID device, e.g. + /dev/dm0 . This means that the typical layering looks like this: Filesystem <- top | - Encryption + Encryption (LUKS) | RAID | - Raw partitions + Raw partitions (optional) | Raw disks <- bottom - - The big advantage is that you can manage the RAID container just - like any RAID container, it does not care that what is in it is - encrypted. + + The big advantage of this is that you can manage the RAID container just + like any other regular RAID container, it does not care that its content + is encrypted. This strongly cuts down on complexity, something very + valuable with storage encryption. - * 2.9 How do I read a dm-crypt key from file? + * 2.9 How do I read a dm-crypt key from file? Use the --key-file option, like this: - cryptsetup create --key-file keyfile e1 /dev/loop0 - - This will read the binary key from file, i.e. no hashing or - transformation will be applied to the keyfile before its bits are - used as key. Extra bits (beyond the length of the key) at the end - are ignored. Note that if you read from STDIN, the data will still - be hashed, just as a key read interactively from the terminal. See - the man-page sections "NOTES ON PASSPHRASE PROCESSING..." for more - detail. + cryptsetup create --key-file keyfile e1 /dev/loop0 + This will read the binary key from file, i.e. no hashing or + transformation will be applied to the keyfile before its bits are used + as key. Extra bits (beyond the length of the key) at the end are + ignored. Note that if you read from STDIN, the data will be hashed, + just as a key read interactively from the terminal. See the man-page + sections "NOTES ON PASSPHRASE PROCESSING..." for more detail. - * 2.10 How do I read a LUKS slot key from file? - What you really do here is to read a passphrase from file, just as - you would with manual entry of a passphrase for a key-slot. You can - add a new passphrase to a free key-slot, set the passphrase of an - specific key-slot or put an already configured passphrase into a - file. In the last case make sure no trailing newline (0x0a) is - contained in the key file, or the passphrase will not work because - the whole file is used as input. + * 2.10 How do I read a LUKS slot key from file? + + What you really do here is to read a passphrase from file, just as you + would with manual entry of a passphrase for a key-slot. You can add a + new passphrase to a free key-slot, set the passphrase of an specific + key-slot or put an already configured passphrase into a file. Make sure + no trailing newline (0x0a) is contained in the input key file, or the + passphrase will not work because the whole file is used as input. To add a new passphrase to a free key slot from file, use something like this: - cryptsetup luksAddKey /dev/loop0 keyfile - - To add a new passphrase to a specific key-slot, use something like - this: + cryptsetup luksAddKey /dev/loop0 keyfile + + To add a new passphrase to a specific key-slot, use something + like this: + + cryptsetup luksAddKey --key-slot 7 /dev/loop0 keyfile - cryptsetup luksAddKey --key-slot 7 /dev/loop0 keyfile - To supply a key from file to any LUKS command, use the --key-file option, e.g. like this: - cryptsetup luksOpen --key-file keyfile /dev/loop0 e1 - + cryptsetup luksOpen --key-file keyfile /dev/loop0 e1 - * 2.11 How do I read the LUKS master key from file? - The question you should ask yourself first is why you would want to - do this. The only legitimate reason I can think of is if you want - to have two LUKS devices with the same master key. Even then, I - think it would be preferable to just use key-slots with the same - passphrase, or to use plain dm-crypt instead. If you really have a - good reason, please tell me. If I am convinced, I will add how to - do this here. + * 2.11 How do I read the LUKS master key from file? - * 2.12 What are the security requirements for a key read from file? + The question you should ask yourself first is why you would want to do + this. The only legitimate reason I can think of is if you want to have + two LUKS devices with the same master key. Even then, I think it would + be preferable to just use key-slots with the same passphrase, or to use + plain dm-crypt instead. If you really have a good reason, please tell + me. If I am convinced, I will add how to do this here. - A file-stored key or passphrase has the same security requirements - as one entered interactively, however you can use random bytes and - thereby use bytes you cannot type on the keyboard. You can use any - file you like as key file, for example a plain text file with a - human readable passphrase. To generate a file with random bytes, - use something like this: - head -c 256 /dev/random > keyfile - + * 2.12 What are the security requirements for a key read from file? + + A file-stored key or passphrase has the same security requirements as + one entered interactively, however you can use random bytes and thereby + use bytes you cannot type on the keyboard. You can use any file you + like as key file, for example a plain text file with a human readable + passphrase. To generate a file with random bytes, use something like + this: - * 2.13 If I map a journaled file system using dm-crypt/LUKS, does it - still provide its usual transactional guarantees? + head -c 256 /dev/random > keyfile - Yes, it does, unless a very old kernel is used. The required flags - come from the filesystem layer and are processed and passed onwards - by dm-crypt. A bit more information on the process by which - transactional guarantees are implemented can be found here: + + + * 2.13 If I map a journaled file system using dm-crypt/LUKS, does + it still provide its usual transactional guarantees? + + Yes, it does, unless a very old kernel is used. The required flags come + from the filesystem layer and are processed and passed onward by + dm-crypt (regardless of direct key management or LUKS key management). + A bit more information on the process by which transactional guarantees + are implemented can be found here: http://lwn.net/Articles/400541/ - Please note that these "guarantees" are weaker than they appear to - be. One problem is that quite a few disks lie to the OS about - having flushed their buffers. Some other things can go wrong as - well. The filesystem developers are aware of these problems and - typically can make it work anyways. That said, dm-crypt/LUKS will - not make things worse. - - One specific problem you can run into though is that you can get - short freezes and other slowdowns due to the encryption layer. - Encryption takes time and forced flushes will block for that time. - For example, I did run into frequent small freezes (1-2 sec) when - putting a vmware image on ext3 over dm-crypt. When I went back to - ext2, the problem went away. This seems to have gotten better with - kernel 2.6.36 and the reworking of filesystem flush locking - mechanism (less blocking of CPU activity during flushes). It - should improve further and eventually the problem should go away. - - - * 2.14 Can I use LUKS or cryptsetup with a more secure (external) - medium for key storage, e.g. TPM or a smartcard? - - Yes, see the answers on using a file-supplied key. You do have to - write the glue-logic yourself though. Basically you can have - cryptsetup read the key from STDIN and write it there with your - own tool that in turn gets the key from the more secure key - storage. + Please note that these "guarantees" are weaker than they appear to be. + One problem is that quite a few disks lie to the OS about having flushed + their buffers. This is likely still true with SSDs. Some other things + can go wrong as well. The filesystem developers are aware of these + problems and typically can make it work anyways. That said, + dm-crypt/LUKS will not make things worse. + + One specific problem you can run into is that you can get short freezes + and other slowdowns due to the encryption layer. Encryption takes time + and forced flushes will block for that time. For example, I did run + into frequent small freezes (1-2 sec) when putting a vmware image on + ext3 over dm-crypt. When I went back to ext2, the problem went away. + This seems to have gotten better with kernel 2.6.36 and the reworking of + filesystem flush locking mechanism (less blocking of CPU activity during + flushes). This should improve further and eventually the problem should + go away. + + + * 2.14 Can I use LUKS or cryptsetup with a more secure (external) + medium for key storage, e.g. TPM or a smartcard? + + Yes, see the answers on using a file-supplied key. You do have to write + the glue-logic yourself though. Basically you can have cryptsetup read + the key from STDIN and write it there with your own tool that in turn + gets the key from the more secure key storage. For TPM support, you may want to have a look at tpm-luks at - https://github.com/shpedoikal/tpm-luks. Note that tpm-luks is not + https://github.com/shpedoikal/tpm-luks. Note that tpm-luks is not related to the cryptsetup project. - * 2.15 Can I resize a dm-crypt or LUKS partition? + * 2.15 Can I resize a dm-crypt or LUKS container? + + Yes, you can, as neither dm-crypt nor LUKS1 stores partition size and + LUKS2 uses a generic "whole device" size as default. Note that LUKS2 + can use specified data-area sizes as a non-standard case and that these + may cause issues when resizing a LUKS2 container if set to a specific + value. - Yes, you can, as neither dm-crypt nor LUKS stores partition size. - Whether you should is a different question. Personally I recommend - backup, recreation of the encrypted partition with new size, - recreation of the filesystem and restore. This gets around the - tricky business of resizing the filesystem. Resizing a dm-crypt or - LUKS container does not resize the filesystem in it. The backup is - really non-optional here, as a lot can go wrong, resulting in - partial or complete data loss. Using something like gparted to - resize an encrypted partition is slow, but typically works. This - will not change the size of the filesystem hidden under the - encryption though. + Whether you should do this is a different question. Personally I + recommend backup, recreation of the dm-crypt or LUKS container with new + size, recreation of the filesystem and restore. This gets around the + tricky business of resizing the filesystem. Resizing a dm-crypt or LUKS + container does not resize the filesystem in it. A backup is really + non-optional here, as a lot can go wrong, resulting in partial or + complete data loss. But if you have that backup, you can also just + recreate everything. - You also need to be aware of size-based limitations. The one - currently relevant is that aes-xts-plain should not be used for - encrypted container sizes larger than 2TiB. Use aes-xts-plain64 - for that. + You also need to be aware of size-based limitations. The one currently + relevant is that aes-xts-plain should not be used for encrypted + container sizes larger than 2TiB. Use aes-xts-plain64 for that. - * 2.16 How do I Benchmark the Ciphers, Hashes and Modes? + * 2.16 How do I Benchmark the Ciphers, Hashes and Modes? - Since version 1.60 cryptsetup supports the "benchmark" command. + Since version 1.60 cryptsetup supports the "benchmark" command. Simply run as root: - cryptsetup benchmark - - It will output first iterations/second for the key-derivation - function PBKDF2 parameterized with different hash-functions, and - then the raw encryption speed of ciphers with different modes and - key-sizes. You can get more than the default benchmarks, see the - man-page for the relevant parameters. Note that XTS mode takes two - keys, hence the listed key sizes are double that for other modes - and half of it is the cipher key, the other half is the XTS key. - - - * 2.17 How do I Verify I have an Authentic cryptsetup Source Package? - - Current maintainer is Milan Broz and he signs the release packages - with his PGP key. The key he currently uses is the "RSA key ID - D93E98FC", fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B - D93E 98FC. While I have every confidence this really is his key and - that he is who he claims to be, don't depend on it if your life is - at stake. For that matter, if your life is at stake, don't depend - on me being who I claim to be either. - - That said, as cryptsetup is under good version control, a malicious - change should be noticed sooner or later, but it may take a while. - Also, the attacker model makes compromising the sources in a - non-obvious way pretty hard. Sure, you could put the master-key - somewhere on disk, but that is rather obvious as soon as somebody - looks as there would be data in an empty LUKS container in a place - it should not be. Doing this in a more nefarious way, for example - hiding the master-key in the salts, would need a look at the - sources to be discovered, but I think that somebody would find that - sooner or later as well. - - That said, this discussion is really a lot more complicated and - longer as an FAQ can sustain. If in doubt, ask on the mailing list. - - - * 2.18 Is there a concern with 4k Sectors? - - Not from dm-crypt itself. Encryption will be done in 512B blocks, - but if the partition and filesystem are aligned correctly and the - filesystem uses multiples of 4kiB as block size, the dm-crypt layer - will just process 8 x 512B = 4096B at a time with negligible - overhead. LUKS does place data at an offset, which is 2MiB per - default and will not break alignment. See also Item 6.12 of this - FAQ for more details. Note that if your partition or filesystem is - misaligned, dm-crypt can make the effect worse though. - - - * 2.19 How can I wipe a device with crypto-grade randomness? - - The conventional recommendation if you want to not just do a + cryptsetup benchmark + + You can get more than the default benchmarks, see the man-page for the + relevant parameters. Note that XTS mode takes two keys, hence the + listed key sizes are double that for other modes and half of it is the + cipher key, the other half is the XTS key. + + + * 2.17 How do I Verify I have an Authentic cryptsetup Source Package? + + Current maintainer is Milan Broz and he signs the release packages with + his PGP key. The key he currently uses is the "RSA key ID D93E98FC", + fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B D93E 98FC. While I + have every confidence this really is his key and that he is who he + claims to be, don't depend on it if your life is at stake. For that + matter, if your life is at stake, don't depend on me being who I claim + to be either. + + That said, as cryptsetup is under good version control and a malicious + change should be noticed sooner or later, but it may take a while. + Also, the attacker model makes compromising the sources in a non-obvious + way pretty hard. Sure, you could put the master-key somewhere on disk, + but that is rather obvious as soon as somebody looks as there would be + data in an empty LUKS container in a place it should not be. Doing this + in a more nefarious way, for example hiding the master-key in the salts, + would need a look at the sources to be discovered, but I think that + somebody would find that sooner or later as well. + + That said, this discussion is really a lot more complicated and longer + as an FAQ can sustain. If in doubt, ask on the mailing list. + + + * 2.18 Is there a concern with 4k Sectors? + + Not from dm-crypt itself. Encryption will be done in 512B blocks, but + if the partition and filesystem are aligned correctly and the filesystem + uses multiples of 4kiB as block size, the dm-crypt layer will just + process 8 x 512B = 4096B at a time with negligible overhead. LUKS does + place data at an offset, which is 2MiB per default and will not break + alignment. See also Item 6.12 of this FAQ for more details. Note that + if your partition or filesystem is misaligned, dm-crypt can make the + effect worse though. Also note that SSDs typically have much larger + blocks internally (e.g. 128kB or even larger). + + + * 2.19 How can I wipe a device with crypto-grade randomness? + + The conventional recommendation if you want to do more than just a zero-wipe is to use something like - cat /dev/urandom > - - That is very slow and painful at 10-20MB/s on a fast computer. - Using cryptsetup and a plain dm-crypt device with a random key, it - is much faster and gives you the same level of security. The + cat /dev/urandom > + + That used to very slow and painful at 10-20MB/s on a fast computer, but + newer kernels can give you > 200MB/s (depending on hardware). An + alternative is using cryptsetup and a plain dm-crypt device with a + random key, which is fast and on the same level of security. The defaults are quite enough. For device set-up, do the following: - cryptsetup open --type plain -d /dev/urandom /dev/ to_be_wiped - - Then you have several options. Simple wipe without - progress-indicator: + cryptsetup open --type plain -d /dev/urandom /dev/ target + + This maps the container as plain under /dev/mapper/target with a random + password. For the actual wipe you have several options. Basically, you + pipe zeroes into the opened container that then get encrypted. Simple + wipe without progress-indicator: + + cat /dev/zero > /dev/mapper/to_be_wiped - cat /dev/zero > /dev/mapper/to_be_wiped - Progress-indicator by dd_rescue: - dd_rescue -w /dev/zero /dev/mapper/to_be_wiped - + dd_rescue -w /dev/zero /dev/mapper/to_be_wiped + Progress-indicator by my "wcs" stream meter (available from http://www.tansi.org/tools/index.html ): - cat /dev/zero | wcs > /dev/mapper/to_be_wiped - + cat /dev/zero | wcs > /dev/mapper/to_be_wiped + + Or use plain "dd", which gives you the progress when sent a SIGUSR1, see + the dd man page. + Remove the mapping at the end and you are done. -3. Common Problems + * 2.20 How to I wipe only the LUKS header? + + This does _not_ describe an emergency wipe procedure, see Item 5.4 for + that. This procedure here is intended to be used when the data should + stay intact, e.g. when you change your LUKS container to use a detached + header and want to remove the old one. Please only do this if you have + a current backup. + + LUKS1: + 01) Determine header size in 512 Byte sectors with luksDump: + + cryptsetup luksDump + +-> ... + Payload offset: + ... + + 02) Take the result number, multiply by 512 zeros and write to + the start of the device, e.g. like this: + + dd bs=512 count= if=/dev/zero of= + + LUKS2: (warning, untested! Remember that backup?) This assumes the + LUKS2 container uses the defaults, in particular there is only one data + segment. 01) Determine the data-segment offset using luksDump, same + as above for LUKS1: - * 3.1 My dm-crypt/LUKS mapping does not work! What general steps are - there to investigate the problem? +-> ... + Data segments: + 0: crypt + offset: [bytes] + ... - If you get a specific error message, investigate what it claims - first. If not, you may want to check the following things. + 02) Overwrite the stated number of bytes from the start of the device. + Just to give yet another way to get a defined number of zeros: - - Check that "/dev", including "/dev/mapper/control" is there. If it - is missing, you may have a problem with the "/dev" tree itself or - you may have broken udev rules. + head -c /dev/zero > /dev/ + + +3. Common Problems + + + * 3.1 My dm-crypt/LUKS mapping does not work! What general steps + are there to investigate the problem? + + If you get a specific error message, investigate what it claims first. + If not, you may want to check the following things. + + - Check that "/dev", including "/dev/mapper/control" is there. If it is + missing, you may have a problem with the "/dev" tree itself or you may + have broken udev rules. - Check that you have the device mapper and the crypt target in your - kernel. The output of "dmsetup targets" should list a "crypt" - target. If it is not there or the command fails, add device mapper - and crypt-target to the kernel. + kernel. The output of "dmsetup targets" should list a "crypt" target. + If it is not there or the command fails, add device mapper and + crypt-target to the kernel. - - Check that the hash-functions and ciphers you want to use are in - the kernel. The output of "cat /proc/crypto" needs to list them. + - Check that the hash-functions and ciphers you want to use are in the + kernel. The output of "cat /proc/crypto" needs to list them. - * 3.2 My dm-crypt mapping suddenly stopped when upgrading cryptsetup. + * 3.2 My dm-crypt mapping suddenly stopped when upgrading cryptsetup. - The default cipher, hash or mode may have changed (the mode changed - from 1.0.x to 1.1.x). See under "Issues With Specific Versions of + The default cipher, hash or mode may have changed (the mode changed from + 1.0.x to 1.1.x). See under "Issues With Specific Versions of cryptsetup". - * 3.3 When I call cryptsetup from cron/CGI, I get errors about - unknown features? + * 3.3 When I call cryptsetup from cron/CGI, I get errors about + unknown features? If you get errors about unknown parameters or the like that are not - present when cryptsetup is called from the shell, make sure you - have no older version of cryptsetup on your system that then gets - called by cron/CGI. For example some distributions install - cryptsetup into /usr/sbin, while a manual install could go to - /usr/local/sbin. As a debugging aid, call "cryptsetup --version" - from cron/CGI or the non-shell mechanism to be sure the right - version gets called. - - - * 3.4 Unlocking a LUKS device takes very long. Why? - - The iteration time for a key-slot (see Section 5 for an explanation - what iteration does) is calculated when setting a passphrase. By - default it is 1 second on the machine where the passphrase is set. - If you set a passphrase on a fast machine and then unlock it on a - slow machine, the unlocking time can be much longer. Also take into - account that up to 8 key-slots have to be tried in order to find the - right one. - - If this is problem, you can add another key-slot using the slow - machine with the same passphrase and then remove the old key-slot. - The new key-slot will have an iteration count adjusted to 1 second - on the slow machine. Use luksKeyAdd and then luksKillSlot or - luksRemoveKey. - - However, this operation will not change volume key iteration count - (MK iterations in output of "cryptsetup luksDump"). In order to - change that, you will have to backup the data in the LUKS - container (i.e. your encrypted data), luksFormat on the slow - machine and restore the data. Note that in the original LUKS - specification this value was fixed to 10, but it is now derived - from the PBKDF2 benchmark as well and set to iterations in 0.125 - sec or 1000, whichever is larger. Also note that MK iterations - are not very security relevant. But as each key-slot already takes - 1 second, spending the additional 0.125 seconds really does not - matter. - - - * 3.5 "blkid" sees a LUKS UUID and an ext2/swap UUID on the same - device. What is wrong? - - Some old versions of cryptsetup have a bug where the header does - not get completely wiped during LUKS format and an older ext2/swap - signature remains on the device. This confuses blkid. + present when cryptsetup is called from the shell, make sure you have no + older version of cryptsetup on your system that then gets called by + cron/CGI. For example some distributions install cryptsetup into + /usr/sbin, while a manual install could go to /usr/local/sbin. As a + debugging aid, call "cryptsetup --version" from cron/CGI or the + non-shell mechanism to be sure the right version gets called. + + + * 3.4 Unlocking a LUKS device takes very long. Why? + + The unlock time for a key-slot (see Section 5 for an explanation what + iteration does) is calculated when setting a passphrase. By default it + is 1 second (2 seconds for LUKS2). If you set a passphrase on a fast + machine and then unlock it on a slow machine, the unlocking time can be + much longer. Also take into account that up to 8 key-slots (LUKS2: up + to 32 key-slots) have to be tried in order to find the right one. + + If this is problem, you can add another key-slot using the slow machine + with the same passphrase and then remove the old key-slot. The new + key-slot will have the unlock time adjusted to the slow machine. Use + luksKeyAdd and then luksKillSlot or luksRemoveKey. You can also use + the -i option to reduce iteration time (and security level) when setting + a passphrase. Default is 1000 (1 sec) for LUKS1 and 2000 (2sec) for + LUKS2. + + However, this operation will not change volume key iteration count ("MK + iterations" for LUKS1, "Iterations" under "Digests" for LUKS2). In + order to change that, you will have to backup the data in the LUKS + container (i.e. your encrypted data), luksFormat on the slow machine + and restore the data. Note that MK iterations are not very security + relevant. + + + * 3.5 "blkid" sees a LUKS UUID and an ext2/swap UUID on the same + device. What is wrong? + + Some old versions of cryptsetup have a bug where the header does not get + completely wiped during LUKS format and an older ext2/swap signature + remains on the device. This confuses blkid. Fix: Wipe the unused header areas by doing a backup and restore of - the header with cryptsetup 1.1.x: + the header with cryptsetup 1.1.x or later: - cryptsetup luksHeaderBackup --header-backup-file - cryptsetup luksHeaderRestore --header-backup-file - + cryptsetup luksHeaderBackup --header-backup-file + cryptsetup luksHeaderRestore --header-backup-file - * 3.6 cryptsetup segfaults on Gentoo amd64 hardened ... - There seems to be some interference between the hardening and and - the way cryptsetup benchmarks PBKDF2. The solution to this is - currently not quite clear for an encrypted root filesystem. For - other uses, you can apparently specify USE="dynamic" as compile - flag, see http://bugs.gentoo.org/show_bug.cgi?id=283470 - -4. Troubleshooting +4. Troubleshooting - * 4.1 I get the error "LUKS keyslot x is invalid." What does that - mean? + * 4.1 I get the error "LUKS keyslot x is invalid." What does that mean? - This means that the given keyslot has an offset that points - outside the valid keyslot area. Typically, the reason is a - corrupted LUKS header because something was written to the start of - the device the LUKS container is on. Refer to Section "Backup and - Data Recovery" and ask on the mailing list if you have trouble - diagnosing and (if still possible) repairing this. + For LUKS1, this means that the given keyslot has an offset that points + outside the valid keyslot area. Typically, the reason is a corrupted + LUKS1 header because something was written to the start of the device + the LUKS1 container is on. For LUKS2, I do not know when this error can + happen, but I expect it will be something similar. Refer to Section + "Backup and Data Recovery" and ask on the mailing list if you have + trouble diagnosing and (if still possible) repairing this. - * 4.2 I cannot unlock my LUKS container! What could be the problem? + * 4.2 I cannot unlock my LUKS container! What could be the problem? - First, make sure you have a correct passphrase. Then make sure you - have the correct key-map and correct keyboard. And then make sure - you have the correct character set and encoding, see also - "PASSPHRASE CHARACTER SET" under Section 1.2. + First, make sure you have a correct passphrase. Then make sure you have + the correct key-map and correct keyboard. And then make sure you have + the correct character set and encoding, see also "PASSPHRASE CHARACTER + SET" under Section 1.2. If you are sure you are entering the passphrase right, there is the - possibility that the respective key-slot has been damaged. There - is no way to recover a damaged key-slot, except from a header - backup (see Section 6). For security reasons, there is also no - checksum in the key-slots that could tell you whether a key-slot has - been damaged. The only checksum present allows recognition of a - correct passphrase, but that only works if the passphrase is - correct and the respective key-slot is intact. - - In order to find out whether a key-slot is damaged one has to look - for "non-random looking" data in it. There is a tool that - automatizes this in the cryptsetup distribution from version 1.6.0 - onwards. It is located in misc/keyslot_checker/. Instructions how - to use and how to interpret results are in the README file. Note - that this tool requires a libcryptsetup from cryptsetup 1.6.0 or - later (which means libcryptsetup.so.4.5.0 or later). If the tool - complains about missing functions in libcryptsetup, you likely - have an earlier version from your distribution still installed. You - can either point the symbolic link(s) from libcryptsetup.so.4 to - the new version manually, or you can uninstall the distribution - version of cryptsetup and re-install that from cryptsetup >= 1.6.0 - again to fix this. - - - * 4.3 Can a bad RAM module cause problems? + possibility that the respective key-slot has been damaged. There is no + way to recover a damaged key-slot, except from a header backup (see + Section 6). For security reasons, there is also no checksum in the + key-slots that could tell you whether a key-slot has been damaged. The + only checksum present allows recognition of a correct passphrase, but + that only works with that correct passphrase and a respective key-slot + that is intact. + + In order to find out whether a key-slot is damaged one has to look for + "non-random looking" data in it. There is a tool that automatizes this + for LUKS1 in the cryptsetup distribution from version 1.6.0 onwards. It + is located in misc/keyslot_checker/. Instructions how to use and how to + interpret results are in the README file. Note that this tool requires + a libcryptsetup from cryptsetup 1.6.0 or later (which means + libcryptsetup.so.4.5.0 or later). If the tool complains about missing + functions in libcryptsetup, you likely have an earlier version from your + distribution still installed. You can either point the symbolic link(s) + from libcryptsetup.so.4 to the new version manually, or you can + uninstall the distribution version of cryptsetup and re-install that + from cryptsetup >= 1.6.0 again to fix this. + + + * 4.3 Can a bad RAM module cause problems? LUKS and dm-crypt can give the RAM quite a workout, especially when - combined with software RAID. In particular the combination RAID5 + - LUKS + XFS seems to uncover RAM problems that never caused obvious - problems before. Symptoms vary, but often the problem manifest + combined with software RAID. In particular the combination RAID5 + + LUKS1 + XFS seems to uncover RAM problems that do not cause obvious + problems otherwise. Symptoms vary, but often the problem manifest itself when copying large amounts of data, typically several times larger than your main memory. - Side note: One thing you should always do on large data - copy/movements is to run a verify, for example with the "-d" - option of "tar" or by doing a set of MD5 checksums on the source - or target with + Note: One thing you should always do on large data copying or movements + is to run a verify, for example with the "-d" option of "tar" or by + doing a set of MD5 checksums on the source or target with - find . -type f -exec md5sum \{\} \; > checksum-file - - and then a "md5sum -c checksum-file" on the other side. If you get - mismatches here, RAM is the primary suspect. A lesser suspect is - an overclocked CPU. I have found countless hardware problems in - verify runs after copying or making backups. Bit errors are much - more common than most people think. + find . -type f -exec md5sum \{\} \; > checksum-file + + and then a "md5sum -c checksum-file" on the other side. If you get + mismatches here, RAM is the primary suspect. A lesser suspect is an + overclocked CPU. I have found countless hardware problems in verify + runs after copying data or making backups. Bit errors are much more + common than most people think. Some RAM issues are even worse and corrupt structures in one of the - layers. This typically results in lockups, CPU state dumps in the - system logs, kernel panic or other things. It is quite possible to - have the problem with an encrypted device, but not with an - otherwise the same unencrypted device. The reason for that is that - encryption has an error amplification property: You flip one bit - in an encrypted data block, and the decrypted version has half of - its bits flipped. This is an important security property for modern - ciphers. With the usual modes in cryptsetup (CBC, ESSIV, XTS), you - get up to a completely changed 512 byte block per bit error. A - corrupt block causes a lot more havoc than the occasionally - flipped single bit and can result in various obscure errors. - - Note, that a verify run on copying between encrypted or - unencrypted devices will reliably detect corruption, even when the - copying itself did not report any problems. If you find defect - RAM, assume all backups and copied data to be suspect, unless you - did a verify. - - - * 4.4 How do I test RAM? - - First you should know that overclocking often makes memory - problems worse. So if you overclock (which I strongly recommend - against in a system holding data that has some worth), run the - tests with the overclocking active. - - There are two good options. One is Memtest86+ and the other is - "memtester" by Charles Cazabon. Memtest86+ requires a reboot and - then takes over the machine, while memtester runs from a - root-shell. Both use different testing methods and I have found - problems fast with each one that the other needed long to find. I - recommend running the following procedure until the first error is - found: + layers. This typically results in lockups, CPU state dumps in the + system logs, kernel panic or other things. It is quite possible to have + a problem with an encrypted device, but not with an otherwise the same + unencrypted device. The reason for that is that encryption has an error + amplification property: If you flip one bit in an encrypted data block, + the decrypted version has half of its bits flipped. This is actually an + important security property for modern ciphers. With the usual modes in + cryptsetup (CBC, ESSIV, XTS), you can get a completely changed 512 byte + block for a bit error. A corrupt block causes a lot more havoc than the + occasionally flipped single bit and can result in various obscure + errors. + + Note that a verify run on copying between encrypted or unencrypted + devices will reliably detect corruption, even when the copying itself + did not report any problems. If you find defect RAM, assume all backups + and copied data to be suspect, unless you did a verify. + + + * 4.4 How do I test RAM? + + First you should know that overclocking often makes memory problems + worse. So if you overclock (which I strongly recommend against in a + system holding data that has any worth), run the tests with the + overclocking active. + + There are two good options. One is Memtest86+ and the other is + "memtester" by Charles Cazabon. Memtest86+ requires a reboot and then + takes over the machine, while memtester runs from a root-shell. Both + use different testing methods and I have found problems fast with either + one that the other needed long to find. I recommend running the + following procedure until the first error is found: - Run Memtest86+ for one cycle - Run memtester for one cycle (shut down as many other applications - as possible) + as possible and use the largest memory area you can get) - Run Memtest86+ for 24h or more - Run memtester for 24h or more If all that does not produce error messages, your RAM may be sound, - but I have had one weak bit that Memtest86+ needed around 60 hours - to find. If you can reproduce the original problem reliably, a good - additional test may be to remove half of the RAM (if you have more - than one module) and try whether the problem is still there and if - so, try with the other half. If you just have one module, get a - different one and try with that. If you do overclocking, reduce - the settings to the most conservative ones available and try with - that. + but I have had one weak bit in the past that Memtest86+ needed around + 60 hours to find. If you can reproduce the original problem reliably, + a good additional test may be to remove half of the RAM (if you have + more than one module) and try whether the problem is still there and if + so, try with the other half. If you just have one module, get a + different one and try with that. If you do overclocking, reduce the + settings to the most conservative ones available and try with that. -5. Security Aspects + * 4.5 Is there a risk using debugging tools like strace? + There most definitely is. A dump from strace and friends can contain + all data entered, including the full passphrase. Example with strace + and passphrase "test": - * 5.1 How long is a secure passphrase ? + > strace cryptsetup luksOpen /dev/sda10 c1 + ... + read(6, "test\n", 512) = 5 + ... - This is just the short answer. For more info and explanation of - some of the terms used in this item, read the rest of Section 5. - The actual recommendation is at the end of this item. + Depending on different factors and the tool used, the passphrase may + also be encoded and not plainly visible. Hence it is never a good idea + to give such a trace from a live container to anybody. Recreate the + problem with a test container or set a temporary passphrase like "test" + and use that for the trace generation. Item 2.6 explains how to create + a loop-file backed LUKS container that may come in handy for this + purpose. - First, passphrase length is not really the right measure, - passphrase entropy is. For example, a random lowercase letter (a-z) - gives you 4.7 bit of entropy, one element of a-z0-9 gives you 5.2 - bits of entropy, an element of a-zA-Z0-9 gives you 5.9 bits and - a-zA-Z0-9!@#$%^&:-+ gives you 6.2 bits. On the other hand, a random - English word only gives you 0.6...1.3 bits of entropy per - character. Using sentences that make sense gives lower entropy, - series of random words gives higher entropy. Do not use sentences - that can be tied to you or found on your computer. This type of - attack is done routinely today. + See also Item 6.10 for another set of data you should not give to + others. - That said, it does not matter too much what scheme you use, but it - does matter how much entropy your passphrase contains, because an - attacker has to try on average - 1/2 * 2^(bits of entropy in passphrase) - +5. Security Aspects + + + * 5.1 How long is a secure passphrase ? + + This is just the short answer. For more info and explanation of some of + the terms used in this item, read the rest of Section 5. The actual + recommendation is at the end of this item. + + First, passphrase length is not really the right measure, passphrase + entropy is. If your passphrase is 200 times the letter "a", it is long + but has very low entropy and is pretty insecure. + + For example, a random lowercase letter (a-z) gives you 4.7 bit of + entropy, one element of a-z0-9 gives you 5.2 bits of entropy, an element + of a-zA-Z0-9 gives you 5.9 bits and a-zA-Z0-9!@#$%\^&:-+ gives you 6.2 + bits. On the other hand, a random English word only gives you 0.6...1.3 + bits of entropy per character. Using sentences that make sense gives + lower entropy, series of random words gives higher entropy. Do not use + sentences that can be tied to you or found on your computer. This type + of attack is done routinely today. + + That said, it does not matter too much what scheme you use, but it does + matter how much entropy your passphrase contains, because an attacker + has to try on average + + 1/2 * 2^(bits of entropy in passphrase) + different passphrases to guess correctly. - Historically, estimations tended to use computing time estimates, - but more modern approaches try to estimate cost of guessing a - passphrase. + Historically, estimations tended to use computing time estimates, but + more modern approaches try to estimate cost of guessing a passphrase. As an example, I will try to get an estimate from the numbers in - http://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes - More references can be found a the end of this document. Note that - these are estimates from the defender side, so assuming something - is easier than it actually is is fine. An attacker may still have - vastly higher cost than estimated here. - - LUKS uses SHA1 for hashing per default. The claim in the reference - is 63 billion tries/second for SHA1. We will leave aside the check - whether a try actually decrypts a key-slot. Now, the machine has 25 - GPUs, which I will estimate at an overall lifetime cost of USD/EUR - 1000 each, and an useful lifetime of 2 years. (This is on the low - side.) Disregarding downtime, the machine can then break - - N = 63*10^9 * 3600 * 24 * 365 * 2 ~ 4*10^18 - - passphrases for EUR/USD 25k. That is one 62 bit passphrase hashed - once with SHA1 for EUR/USD 25k. Note that as this can be - parallelized, it can be done faster than 2 years with several of - these machines. - - For plain dm-crypt (no hash iteration) this is it. This gives (with - SHA1, plain dm-crypt default is ripemd160 which seems to be - slightly slower than SHA1): - - Passphrase entropy Cost to break - 60 bit EUR/USD 6k + https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a270c40 This + thing costs 23kUSD and does 68Ghashes/sec for SHA1. This is in 2017. + + Incidentally, my older calculation for a machine around 1000 times + slower was off by a factor of about 1000, but in the right direction, + i.e. I estimated the attack to be too easy. Nobody noticed ;-) On the + plus side, the tables are now (2017) pretty much accurate. + + More references can be found a the end of this document. Note that + these are estimates from the defender side, so assuming something is + easier than it actually is is fine. An attacker may still have + significantly higher cost than estimated here. + + LUKS1 used SHA1 (since version 1.7.0 it uses SHA256) for hashing per + default. We will leave aside the check whether a try actually decrypts + a key-slot. I will assume a useful lifetime of the hardware of 2 years. + (This is on the low side.) Disregarding downtime, the machine can then + break + + N = 68*10^9 * 3600 * 24 * 365 * 2 ~ 4*10^18 + + passphrases for EUR/USD 23k. That is one 62 bit passphrase hashed once + with SHA1 for EUR/USD 23k. This can be parallelized, it can be done + faster than 2 years with several of these machines. + + For LUKS2, things look a bit better, as the advantage of using graphics + cards is massively reduced. Using the recommendations below should + hence be fine for LUKS2 as well and give a better security margin. + + For plain dm-crypt (no hash iteration) this is it. This gives (with + SHA1, plain dm-crypt default is ripemd160 which seems to be slightly + slower than SHA1): + + Passphrase entropy Cost to break + 60 bit EUR/USD 6k 65 bit EUR/USD 200K 70 bit EUR/USD 6M 75 bit EUR/USD 200M 80 bit EUR/USD 6B 85 bit EUR/USD 200B - ... ... - - For LUKS, you have to take into account hash iteration in PBKDF2. - For a current CPU, there are about 100k iterations (as can be - queried with ''cryptsetup luksDump''. + ... ... + + + For LUKS1, you have to take into account hash iteration in PBKDF2. + For a current CPU, there are about 100k iterations (as can be queried + with ''cryptsetup luksDump''. The table above then becomes: - Passphrase entropy Cost to break - 50 bit EUR/USD 600k + Passphrase entropy Cost to break + 50 bit EUR/USD 600k 55 bit EUR/USD 20M - 60 bit EUR/USD 600M + 60 bit EUR/USD 600M 65 bit EUR/USD 20B 70 bit EUR/USD 600B 75 bit EUR/USD 20T - ... ... - + ... ... + + Recommendation: - To get reasonable security for the next 10 years, it is a good idea + To get reasonable security for the next 10 years, it is a good idea to overestimate by a factor of at least 1000. - Then there is the question of how much the attacker is willing to - spend. That is up to your own security evaluation. For general use, - I will assume the attacker is willing to spend up to 1 million - EUR/USD. Then we get the following recommendations: + Then there is the question of how much the attacker is willing to spend. + That is up to your own security evaluation. For general use, I will + assume the attacker is willing to spend up to 1 million EUR/USD. Then + we get the following recommendations: Plain dm-crypt: Use > 80 bit. That is e.g. 17 random chars from a-z or a random English sentence of > 135 characters length. - LUKS: Use > 65 bit. That is e.g. 14 random chars from a-z or a - random English sentence of > 108 characters length. + LUKS1 and LUKS2: Use > 65 bit. That is e.g. 14 random chars from a-z + or a random English sentence of > 108 characters length. If paranoid, add at least 20 bit. That is roughly four additional characters for random passphrases and roughly 32 characters for a - random English sentence. - - - * 5.2 Is LUKS insecure? Everybody can see I have encrypted data! - - In practice it does not really matter. In most civilized countries - you can just refuse to hand over the keys, no harm done. In some - countries they can force you to hand over the keys, if they suspect - encryption. However the suspicion is enough, they do not have to - prove anything. This is for practical reasons, as even the presence - of a header (like the LUKS header) is not enough to prove that you - have any keys. It might have been an experiment, for example. Or it - was used as encrypted swap with a key from /dev/random. So they - make you prove you do not have encrypted data. Of course that is - just as impossible as the other way round. - - This means that if you have a large set of random-looking data, - they can already lock you up. Hidden containers (encryption hidden - within encryption), as possible with Truecrypt, do not help - either. They will just assume the hidden container is there and - unless you hand over the key, you will stay locked up. Don't have - a hidden container? Though luck. Anybody could claim that. - - Still, if you are concerned about the LUKS header, use plain - dm-crypt with a good passphrase. See also Section 2, "What is the - difference between "plain" and LUKS format?" - - - * 5.3 Should I initialize (overwrite) a new LUKS/dm-crypt partition? - - If you just create a filesystem on it, most of the old data will - still be there. If the old data is sensitive, you should overwrite - it before encrypting. In any case, not initializing will leave the - old data there until the specific sector gets written. That may - enable an attacker to determine how much and where on the - partition data was written. If you think this is a risk, you can - prevent this by overwriting the encrypted device (here assumed to - be named "e1") with zeros like this: - - dd_rescue -w /dev/zero /dev/mapper/e1 - + random English sentence. + + + * 5.2 Is LUKS insecure? Everybody can see I have encrypted data! + + In practice it does not really matter. In most civilized countries you + can just refuse to hand over the keys, no harm done. In some countries + they can force you to hand over the keys if they suspect encryption. + The suspicion is enough, they do not have to prove anything. This is + for practical reasons, as even the presence of a header (like the LUKS + header) is not enough to prove that you have any keys. It might have + been an experiment, for example. Or it was used as encrypted swap with + a key from /dev/random. So they make you prove you do not have + encrypted data. Of course, if true, that is impossible and hence the + whole idea is not compatible with fair laws. Note that in this context, + countries like the US or the UK are not civilized and do not have fair + laws. + + This means that if you have a large set of random-looking data, they can + already lock you up. Hidden containers (encryption hidden within + encryption), as possible with Truecrypt, do not help either. They will + just assume the hidden container is there and unless you hand over the + key, you will stay locked up. Don't have a hidden container? Though + luck. Anybody could claim that. + + Still, if you are concerned about the LUKS header, use plain dm-crypt + with a good passphrase. See also Section 2, "What is the difference + between "plain" and LUKS format?" + + + * 5.3 Should I initialize (overwrite) a new LUKS/dm-crypt partition? + + If you just create a filesystem on it, most of the old data will still + be there. If the old data is sensitive, you should overwrite it before + encrypting. In any case, not initializing will leave the old data there + until the specific sector gets written. That may enable an attacker to + determine how much and where on the partition data was written. If you + think this is a risk, you can prevent this by overwriting the encrypted + device (here assumed to be named "e1") with zeros like this: + + dd_rescue -w /dev/zero /dev/mapper/e1 + or alternatively with one of the following more standard commands: - cat /dev/zero > /dev/mapper/e1 - dd if=/dev/zero of=/dev/mapper/e1 - - - * 5.4 How do I securely erase a LUKS (or other) partition? - - For LUKS, if you are in a desperate hurry, overwrite the LUKS - header and key-slot area. This means overwriting the first - (keyslots x stripes x keysize) + offset bytes. For the default - parameters, this is the 1'052'672 bytes, i.e. 1MiB + 4096 of the - LUKS partition. For 512 bit key length (e.g. for aes-xts-plain with - 512 bit key) this is 2MiB. (The different offset stems from - differences in the sector alignment of the key-slots.) If in doubt, - just be generous and overwrite the first 10MB or so, it will likely - still be fast enough. A single overwrite with zeros should be - enough. If you anticipate being in a desperate hurry, prepare the - command beforehand. Example with /dev/sde1 as the LUKS partition - and default parameters: - - head -c 1052672 /dev/zero > /dev/sde1; sync - - A LUKS header backup or full backup will still grant access to - most or all data, so make sure that an attacker does not have - access to backups or destroy them as well. - - If you have time, overwrite the whole LUKS partition with a single - pass of zeros. This is enough for current HDDs. For SSDs or FLASH - (USB sticks) you may want to overwrite the whole drive several - times to be sure data is not retained by wear leveling. This is - possibly still insecure as SSD technology is not fully understood - in this regard. Still, due to the anti-forensic properties of the - LUKS key-slots, a single overwrite of an SSD or FLASH drive could - be enough. If in doubt, use physical destruction in addition. Here - is a link to some current research results on erasing SSDs and - FLASH drives: + cat /dev/zero > /dev/mapper/e1 + dd if=/dev/zero of=/dev/mapper/e1 + + + + * 5.4 How do I securely erase a LUKS container? + + For LUKS, if you are in a desperate hurry, overwrite the LUKS header and + key-slot area. For LUKS1 and LUKS2, just be generous and overwrite the + first 100MB. A single overwrite with zeros should be enough. If you + anticipate being in a desperate hurry, prepare the command beforehand. + Example with /dev/sde1 as the LUKS partition and default parameters: + + head -c 100000000 /dev/zero > /dev/sde1; sync + + A LUKS header backup or full backup will still grant access to most or + all data, so make sure that an attacker does not have access to backups + or destroy them as well. + + Also note that SSDs and also some HDDs (SMR and hybrid HDDs, for + example) may not actually overwrite the header and only do that an + unspecified and possibly very long time later. The only way to be sure + there is physical destruction. If the situation permits, do both + overwrite and physical destruction. + + If you have time, overwrite the whole drive with a single pass of random + data. This is enough for most HDDs. For SSDs or FLASH (USB sticks) or + SMR or hybrid drives, you may want to overwrite the whole drive several + times to be sure data is not retained. This is possibly still insecure + as the respective technologies are not fully understood in this regard. + Still, due to the anti-forensic properties of the LUKS key-slots, a + single overwrite could be enough. If in doubt, use physical destruction + in addition. Here is a link to some current research results on erasing + SSDs and FLASH drives: http://www.usenix.org/events/fast11/tech/full_papers/Wei.pdf Keep in mind to also erase all backups. - Example for a zero-overwrite erase of partition sde1 done with + Example for a random-overwrite erase of partition sde1 done with dd_rescue: - dd_rescue -w /dev/zero /dev/sde1 - + dd_rescue -w /dev/urandom /dev/sde1 - * 5.5 How do I securely erase a backup of a LUKS partition or header? - That depends on the medium it is stored on. For HDD and SSD, use - overwrite with zeros. For an SSD or FLASH drive (USB stick), you - may want to overwrite the complete SSD several times and use - physical destruction in addition, see last item. For re-writable - CD/DVD, a single overwrite should also be enough, due to the - anti-forensic properties of the LUKS keyslots. For write-once - media, use physical destruction. For low security requirements, - just cut the CD/DVD into several parts. For high security needs, - shred or burn the medium. If your backup is on magnetic tape, I - advise physical destruction by shredding or burning, after - overwriting . The problem with magnetic tape is that it has a - higher dynamic range than HDDs and older data may well be - recoverable after overwrites. Also write-head alignment issues can - lead to data not actually being deleted at all during overwrites. + * 5.5 How do I securely erase a backup of a LUKS partition or header? - * 5.6 What about backup? Does it compromise security? + That depends on the medium it is stored on. For HDD and SSD, use + overwrite with random data. For an SSD, FLASH drive (USB stick) hybrid + HDD or SMR HDD, you may want to overwrite the complete drive several + times and use physical destruction in addition, see last item. For + re-writable CD/DVD, a single overwrite should be enough, due to the + anti-forensic properties of the LUKS keyslots. For write-once media, + use physical destruction. For low security requirements, just cut the + CD/DVD into several parts. For high security needs, shred or burn the + medium. + + If your backup is on magnetic tape, I advise physical destruction by + shredding or burning, after (!) overwriting . The problem with magnetic + tape is that it has a higher dynamic range than HDDs and older data may + well be recoverable after overwrites. Also write-head alignment issues + can lead to data not actually being deleted during overwrites. + + The best option is to actually encrypt the backup, for example with + PGP/GnuPG and then just destroy all copies of the encryption key if + needed. Best keep them on paper, as that has excellent durability and + secure destruction is easy, for example by burning and then crushing the + ashes to a fine powder. A blender and water also works nicely. + + + * 5.6 What about backup? Does it compromise security? That depends. See item 6.7. - * 5.7 Why is all my data permanently gone if I overwrite the LUKS - header? + * 5.7 Why is all my data permanently gone if I overwrite the LUKS header? - Overwriting the LUKS header in part or in full is the most common - reason why access to LUKS containers is lost permanently. - Overwriting can be done in a number of fashions, like creating a - new filesystem on the raw LUKS partition, making the raw partition - part of a raid array and just writing to the raw partition. + Overwriting the LUKS header in part or in full is the most common reason + why access to LUKS containers is lost permanently. Overwriting can be + done in a number of fashions, like creating a new filesystem on the raw + LUKS partition, making the raw partition part of a raid array and just + writing to the raw partition. - The LUKS header contains a 256 bit "salt" per key-slot and without - that no decryption is possible. While the salts are not secret, - they are key-grade material and cannot be reconstructed. This is a - cryptographically strong "cannot". From observations on the - cryptsetup mailing-list, people typically go though the usual - stages of grief (Denial, Anger, Bargaining, Depression, Acceptance) - when this happens to them. Observed times vary between 1 day and 2 - weeks to complete the cycle. Seeking help on the mailing-list is - fine. Even if we usually cannot help with getting back your data, - most people found the feedback comforting. + The LUKS1 header contains a 256 bit "salt" per key-slot and without that + no decryption is possible. While the salts are not secret, they are + key-grade material and cannot be reconstructed. This is a + cryptographically strong "cannot". From observations on the cryptsetup + mailing-list, people typically go though the usual stages of grief + (Denial, Anger, Bargaining, Depression, Acceptance) when this happens to + them. Observed times vary between 1 day and 2 weeks to complete the + cycle. Seeking help on the mailing-list is fine. Even if we usually + cannot help with getting back your data, most people found the feedback + comforting. If your header does not contain an intact key-slot salt, best go - directly to the last stage ("Acceptance") and think about what to - do now. There is one exception that I know of: If your LUKS - container is still open, then it may be possible to extract the - master key from the running system. See Item "How do I recover the - master key from a mapped LUKS container?" in Section "Backup and - Data Recovery". - - - * 5.8 What is a "salt"? - - A salt is a random key-grade value added to the passphrase before - it is processed. It is not kept secret. The reason for using salts - is as follows: If an attacker wants to crack the password for a - single LUKS container, then every possible passphrase has to be - tried. Typically an attacker will not try every binary value, but - will try words and sentences from a dictionary. - - If an attacker wants to attack several LUKS containers with the - same dictionary, then a different approach makes sense: Compute the - resulting slot-key for each dictionary element and store it on - disk. Then the test for each entry is just the slow unlocking with - the slot key (say 0.00001 sec) instead of calculating the slot-key - first (1 sec). For a single attack, this does not help. But if you - have more than one container to attack, this helps tremendously, - also because you can prepare your table before you even have the - container to attack! The calculation is also very simple to - parallelize. You could, for example, use the night-time unused CPU - power of your desktop PCs for this. - - This is where the salt comes in. If the salt is combined with the - passphrase (in the simplest form, just appended to it), you - suddenly need a separate table for each salt value. With a - reasonably-sized salt value (256 bit, e.g.) this is quite - infeasible. - - - * 5.9 Is LUKS secure with a low-entropy (bad) passphrase? - - Note: You should only use the 94 printable characters from 7 bit - ASCII code to prevent your passphrase from failing when the - character encoding changes, e.g. because of a system upgrade, see - also the note at the very start of this FAQ under "WARNINGS". - - This needs a bit of theory. The quality of your passphrase is - directly related to its entropy (information theoretic, not - thermodynamic). The entropy says how many bits of "uncertainty" or - "randomness" are in you passphrase. In other words, that is how - difficult guessing the passphrase is. + directly to the last stage ("Acceptance") and think about what to do + now. There is one exception that I know of: If your LUKS1 container is + still open, then it may be possible to extract the master key from the + running system. See Item "How do I recover the master key from a mapped + LUKS1 container?" in Section "Backup and Data Recovery". + + For LUKS2, things are both better and worse. First, the salts are in a + less vulnerable position now. But, on the other hand, the keys of a + mapped (open) container are now stored in the kernel key-store, and + while there probably is some way to get them out of there, I am not sure + how much effort that needs. + + + * 5.8 What is a "salt"? + + A salt is a random key-grade value added to the passphrase before it is + processed. It is not kept secret. The reason for using salts is as + follows: If an attacker wants to crack the password for a single LUKS + container, then every possible passphrase has to be tried. Typically an + attacker will not try every binary value, but will try words and + sentences from a dictionary. + + If an attacker wants to attack several LUKS containers with the same + dictionary, then a different approach makes sense: Compute the resulting + slot-key for each dictionary element and store it on disk. Then the + test for each entry is just the slow unlocking with the slot key (say + 0.00001 sec) instead of calculating the slot-key first (1 sec). For a + single attack, this does not help. But if you have more than one + container to attack, this helps tremendously, also because you can + prepare your table before you even have the container to attack! The + calculation is also very simple to parallelize. You could, for example, + use the night-time unused CPU power of your desktop PCs for this. + + This is where the salt comes in. If the salt is combined with the + passphrase (in the simplest form, just appended to it), you suddenly + need a separate table for each salt value. With a reasonably-sized salt + value (256 bit, e.g.) this is quite infeasible. + + + * 5.9 Is LUKS secure with a low-entropy (bad) passphrase? + + Short answer: yes. Do not use a low-entropy passphrase. + + Note: For LUKS2, protection for bad passphrases is a bit better + due to the use of Argon2, but that is only a gradual improvement. + + Longer answer: + This needs a bit of theory. The quality of your passphrase is directly + related to its entropy (information theoretic, not thermodynamic). The + entropy says how many bits of "uncertainty" or "randomness" are in you + passphrase. In other words, that is how difficult guessing the + passphrase is. Example: A random English sentence has about 1 bit of entropy per - character. A random lowercase (or uppercase) character has about - 4.7 bit of entropy. + character. A random lowercase (or uppercase) character has about 4.7 + bit of entropy. Now, if n is the number of bits of entropy in your passphrase and t is the time it takes to process a passphrase in order to open the LUKS container, then an attacker has to spend at maximum - attack_time_max = 2^n * t - - time for a successful attack and on average half that. There is no - way getting around that relationship. However, there is one thing - that does help, namely increasing t, the time it takes to use a - passphrase, see next FAQ item. - - Still, if you want good security, a high-entropy passphrase is the - only option. For example, a low-entropy passphrase can never be - considered secure against a TLA-level (Three Letter Agency level, - i.e. government-level) attacker, no matter what tricks are used in - the key-derivation function. Use at least 64 bits for secret stuff. - That is 64 characters of English text (but only if randomly chosen) - or a combination of 12 truly random letters and digits. - - For passphrase generation, do not use lines from very well-known - texts (religious texts, Harry potter, etc.) as they are to easy to - guess. For example, the total Harry Potter has about 1'500'000 - words (my estimation). Trying every 64 character sequence starting - and ending at a word boundary would take only something like 20 - days on a single CPU and is entirely feasible. To put that into - perspective, using a number of Amazon EC2 High-CPU Extra Large - instances (each gives about 8 real cores), this test costs - currently about 50USD/EUR, but can be made to run arbitrarily fast. - - On the other hand, choosing 1.5 lines from, say, the Wheel of Time - is in itself not more secure, but the book selection adds quite a - bit of entropy. (Now that I have mentioned it here, don't use tWoT - either!) If you add 2 or 3 typos or switch some words around, then - this is good passphrase material. - - - * 5.10 What is "iteration count" and why is decreasing it a bad idea? - - Iteration count is the number of PBKDF2 iterations a passphrase is - put through before it is used to unlock a key-slot. Iterations are - done with the explicit purpose to increase the time that it takes - to unlock a key-slot. This provides some protection against use of - low-entropy passphrases. - - The idea is that an attacker has to try all possible passphrases. - Even if the attacker knows the passphrase is low-entropy (see last - item), it is possible to make each individual try take longer. The - way to do this is to repeatedly hash the passphrase for a certain - time. The attacker then has to spend the same time (given the same - computing power) as the user per try. With LUKS, the default is 1 - second of PBKDF2 hashing. - - Example 1: Lets assume we have a really bad passphrase (e.g. a - girlfriends name) with 10 bits of entropy. With the same CPU, an - attacker would need to spend around 500 seconds on average to - break that passphrase. Without iteration, it would be more like - 0.0001 seconds on a modern CPU. - - Example 2: The user did a bit better and has 32 chars of English - text. That would be about 32 bits of entropy. With 1 second - iteration, that means an attacker on the same CPU needs around 136 - years. That is pretty impressive for such a weak passphrase. - Without the iterations, it would be more like 50 days on a modern - CPU, and possibly far less. - - In addition, the attacker can both parallelize and use special - hardware like GPUs or FPGAs to speed up the attack. The attack can - also happen quite some time after the luksFormat operation and CPUs - can have become faster and cheaper. For that reason you want a - bit of extra security. Anyways, in Example 1 your are screwed. - In example 2, not necessarily. Even if the attack is faster, it - still has a certain cost associated with it, say 10000 EUR/USD - with iteration and 1 EUR/USD without iteration. The first can be - prohibitively expensive, while the second is something you try - even without solid proof that the decryption will yield something - useful. - - The numbers above are mostly made up, but show the idea. Of course - the best thing is to have a high-entropy passphrase. - - Would a 100 sec iteration time be even better? Yes and no. - Cryptographically it would be a lot better, namely 100 times better. - However, usability is a very important factor for security - technology and one that gets overlooked surprisingly often. For - LUKS, if you have to wait 2 minutes to unlock the LUKS container, - most people will not bother and use less secure storage instead. It - is better to have less protection against low-entropy passphrases - and people actually use LUKS, than having them do without - encryption altogether. - - Now, what about decreasing the iteration time? This is generally a - very bad idea, unless you know and can enforce that the users only - use high-entropy passphrases. If you decrease the iteration time - without ensuring that, then you put your users at increased risk, - and considering how rarely LUKS containers are unlocked in a - typical work-flow, you do so without a good reason. Don't do it. - The iteration time is already low enough that users with entropy - low passphrases are vulnerable. Lowering it even further increases - this danger significantly. - - - * 5.11 Some people say PBKDF2 is insecure? + attack_time_max = 2^n * t + + time for a successful attack and on average half that. There is no way + getting around that relationship. However, there is one thing that does + help, namely increasing t, the time it takes to use a passphrase, see + next FAQ item. + + Still, if you want good security, a high-entropy passphrase is the only + option. For example, a low-entropy passphrase can never be considered + secure against a TLA-level (Three Letter Agency level, i.e. + government-level) attacker, no matter what tricks are used in the + key-derivation function. Use at least 64 bits for secret stuff. That + is 64 characters of English text (but only if randomly chosen) or a + combination of 12 truly random letters and digits. + + For passphrase generation, do not use lines from very well-known texts + (religious texts, Harry potter, etc.) as they are too easy to guess. + For example, the total Harry Potter has about 1'500'000 words (my + estimation). Trying every 64 character sequence starting and ending at + a word boundary would take only something like 20 days on a single CPU + and is entirely feasible. To put that into perspective, using a number + of Amazon EC2 High-CPU Extra Large instances (each gives about 8 real + cores), this test costs currently about 50USD/EUR, but can be made to + run arbitrarily fast. + + On the other hand, choosing 1.5 lines from, say, the Wheel of Time, is + in itself not more secure, but the book selection adds quite a bit of + entropy. (Now that I have mentioned it here, don't use tWoT either!) If + you add 2 or 3 typos and switch some words around, then this is good + passphrase material. + + + * 5.10 What is "iteration count" and why is decreasing it a bad idea? + + LUKS1: + Iteration count is the number of PBKDF2 iterations a passphrase is put + through before it is used to unlock a key-slot. Iterations are done + with the explicit purpose to increase the time that it takes to unlock a + key-slot. This provides some protection against use of low-entropy + passphrases. + + The idea is that an attacker has to try all possible passphrases. Even + if the attacker knows the passphrase is low-entropy (see last item), it + is possible to make each individual try take longer. The way to do this + is to repeatedly hash the passphrase for a certain time. The attacker + then has to spend the same time (given the same computing power) as the + user per try. With LUKS1, the default is 1 second of PBKDF2 hashing. + + Example 1: Lets assume we have a really bad passphrase (e.g. a + girlfriends name) with 10 bits of entropy. With the same CPU, an + attacker would need to spend around 500 seconds on average to break that + passphrase. Without iteration, it would be more like 0.0001 seconds on + a modern CPU. + + Example 2: The user did a bit better and has 32 chars of English text. + That would be about 32 bits of entropy. With 1 second iteration, that + means an attacker on the same CPU needs around 136 years. That is + pretty impressive for such a weak passphrase. Without the iterations, + it would be more like 50 days on a modern CPU, and possibly far less. + + In addition, the attacker can both parallelize and use special hardware + like GPUs or FPGAs to speed up the attack. The attack can also happen + quite some time after the luksFormat operation and CPUs can have become + faster and cheaper. For that reason you want a bit of extra security. + Anyways, in Example 1 your are screwed. In example 2, not necessarily. + Even if the attack is faster, it still has a certain cost associated + with it, say 10000 EUR/USD with iteration and 1 EUR/USD without + iteration. The first can be prohibitively expensive, while the second + is something you try even without solid proof that the decryption will + yield something useful. + + The numbers above are mostly made up, but show the idea. Of course the + best thing is to have a high-entropy passphrase. + + Would a 100 sec iteration time be even better? Yes and no. + Cryptographically it would be a lot better, namely 100 times better. + However, usability is a very important factor for security technology + and one that gets overlooked surprisingly often. For LUKS, if you have + to wait 2 minutes to unlock the LUKS container, most people will not + bother and use less secure storage instead. It is better to have less + protection against low-entropy passphrases and people actually use LUKS, + than having them do without encryption altogether. + + Now, what about decreasing the iteration time? This is generally a very + bad idea, unless you know and can enforce that the users only use + high-entropy passphrases. If you decrease the iteration time without + ensuring that, then you put your users at increased risk, and + considering how rarely LUKS containers are unlocked in a typical + work-flow, you do so without a good reason. Don't do it. The iteration + time is already low enough that users with low entropy passphrases are + vulnerable. Lowering it even further increases this danger + significantly. + + LUKS2: Pretty much the same reasoning applies. The advantages of using + GPUs or FPGAs in an attack have been significantly reduced, but that + is the only main difference. + + + * 5.11 Some people say PBKDF2 is insecure? There is some discussion that a hash-function should have a "large - memory" property, i.e. that it should require a lot of memory to be - computed. This serves to prevent attacks using special programmable - circuits, like FPGAs, and attacks using graphics cards. PBKDF2 - does not need a lot of memory and is vulnerable to these attacks. - However, the publication usually referred in these discussions is - not very convincing in proving that the presented hash really is - "large memory" (that may change, email the FAQ maintainer when it - does) and it is of limited usefulness anyways. Attackers that use - clusters of normal PCs will not be affected at all by a "large - memory" property. For example the US Secret Service is known to - use the off-hour time of all the office PCs of the Treasury for - password breaking. The Treasury has about 110'000 employees. - Assuming every one has an office PC, that is significant computing - power, all of it with plenty of memory for computing "large - memory" hashes. Bot-net operators also have all the memory they - want. The only protection against a resourceful attacker is a - high-entropy passphrase, see items 5.9 and 5.10. - - - * 5.12 What about iteration count with plain dm-crypt? - - Simple: There is none. There is also no salting. If you use plain - dm-crypt, the only way to be secure is to use a high entropy - passphrase. If in doubt, use LUKS instead. - - - * 5.13 Is LUKS with default parameters less secure on a slow CPU? - - Unfortunately, yes. However the only aspect affected is the - protection for low-entropy passphrase or master-key. All other - security aspects are independent of CPU speed. - - The master key is less critical, as you really have to work at it - to give it low entropy. One possibility is to supply the master key - yourself. If that key is low-entropy, then you get what you - deserve. The other known possibility is to use /dev/urandom for - key generation in an entropy-starved situation (e.g. automatic - installation on an embedded device without network and other entropy - sources). - - For the passphrase, don't use a low-entropy passphrase. If your - passphrase is good, then a slow CPU will not matter. If you insist - on a low-entropy passphrase on a slow CPU, use something like - "--iter-time=10" or higher and wait a long time on each LUKS unlock - and pray that the attacker does not find out in which way exactly - your passphrase is low entropy. This also applies to low-entropy - passphrases on fast CPUs. Technology can do only so much to - compensate for problems in front of the keyboard. - - - * 5.14 Why was the default aes-cbc-plain replaced with aes-cbc-essiv? + memory" property, i.e. that it should require a lot of memory to be + computed. This serves to prevent attacks using special programmable + circuits, like FPGAs, and attacks using graphics cards. PBKDF2 does not + need a lot of memory and is vulnerable to these attacks. However, the + publication usually referred in these discussions is not very convincing + in proving that the presented hash really is "large memory" (that may + change, email the FAQ maintainer when it does) and it is of limited + usefulness anyways. Attackers that use clusters of normal PCs will not + be affected at all by a "large memory" property. For example the US + Secret Service is known to use the off-hour time of all the office PCs + of the Treasury for password breaking. The Treasury has about 110'000 + employees. Assuming every one has an office PC, that is significant + computing power, all of it with plenty of memory for computing "large + memory" hashes. Bot-net operators also have all the memory they want. + The only protection against a resourceful attacker is a high-entropy + passphrase, see items 5.9 and 5.10. + + That said, LUKS2 defaults to Argon2, which has a large-memory property + and massively reduces the advantages of GPUs and FPGAs. + + + * 5.12 What about iteration count with plain dm-crypt? + + Simple: There is none. There is also no salting. If you use plain + dm-crypt, the only way to be secure is to use a high entropy passphrase. + If in doubt, use LUKS instead. + + + * 5.13 Is LUKS with default parameters less secure on a slow CPU? + + Unfortunately, yes. However the only aspect affected is the protection + for low-entropy passphrase or master-key. All other security aspects + are independent of CPU speed. + + The master key is less critical, as you really have to work at it to + give it low entropy. One possibility to mess this up is to supply the + master key yourself. If that key is low-entropy, then you get what you + deserve. The other known possibility to create a LUKS container with a + bad master key is to use /dev/urandom for key generation in an + entropy-starved situation (e.g. automatic installation on an embedded + device without network and other entropy sources or installation in a VM + under certain circumstances). + + For the passphrase, don't use a low-entropy passphrase. If your + passphrase is good, then a slow CPU will not matter. If you insist on a + low-entropy passphrase on a slow CPU, use something like + "--iter-time=10000" or higher and wait a long time on each LUKS unlock + and pray that the attacker does not find out in which way exactly your + passphrase is low entropy. This also applies to low-entropy passphrases + on fast CPUs. Technology can do only so much to compensate for problems + in front of the keyboard. + + Also note that power-saving modes will make your CPU slower. This will + reduce iteration count on LUKS container creation. It will keep unlock + times at the expected values though at this CPU speed. + + + * 5.14 Why was the default aes-cbc-plain replaced with aes-cbc-essiv? Note: This item applies both to plain dm-crypt and to LUKS - The problem is that cbc-plain has a fingerprint vulnerability, where - a specially crafted file placed into the crypto-container can be - recognized from the outside. The issue here is that for cbc-plain - the initialization vector (IV) is the sector number. The IV gets - XORed to the first data chunk of the sector to be encrypted. If you - make sure that the first data block to be stored in a sector - contains the sector number as well, the first data block to be - encrypted is all zeros and always encrypted to the same ciphertext. - This also works if the first data chunk just has a constant XOR - with the sector number. By having several shifted patterns you can - take care of the case of a non-power-of-two start sector number of - the file. - - This mechanism allows you to create a pattern of sectors that have - the same first ciphertext block and signal one bit per sector to the - outside, allowing you to e.g. mark media files that way for - recognition without decryption. For large files this is a - practical attack. For small ones, you do not have enough blocks to - signal and take care of different file starting offsets. - - In order to prevent this attack, the default was changed to - cbc-essiv. ESSIV uses a keyed hash of the sector number, with the - encryption key as key. This makes the IV unpredictable without - knowing the encryption key and the watermarking attack fails. - - - * 5.15 Are there any problems with "plain" IV? What is "plain64"? - - First, "plain" and "plain64" are both not secure to use with CBC, - see previous FAQ item. - - However there are modes, like XTS, that are secure with "plain" IV. - The next limit is that "plain" is 64 bit, with the upper 32 bit set - to zero. This means that on volumes larger than 2TiB, the IV - repeats, creating a vulnerability that potentially leaks some - data. To avoid this, use "plain64", which uses the full sector - number up to 64 bit. Note that "plain64" requires a kernel >= - 2.6.33. Also note that "plain64" is backwards compatible for - volume sizes <= 2TiB, but not for those > 2TiB. Finally, "plain64" - does not cause any performance penalty compared to "plain". - - - * 5.16 What about XTS mode? + The problem is that cbc-plain has a fingerprint vulnerability, where a + specially crafted file placed into the crypto-container can be + recognized from the outside. The issue here is that for cbc-plain the + initialization vector (IV) is the sector number. The IV gets XORed to + the first data chunk of the sector to be encrypted. If you make sure + that the first data block to be stored in a sector contains the sector + number as well, the first data block to be encrypted is all zeros and + always encrypted to the same ciphertext. This also works if the first + data chunk just has a constant XOR with the sector number. By having + several shifted patterns you can take care of the case of a + non-power-of-two start sector number of the file. + + This mechanism allows you to create a pattern of sectors that have the + same first ciphertext block and signal one bit per sector to the + outside, allowing you to e.g. mark media files that way for recognition + without decryption. For large files this is a practical attack. For + small ones, you do not have enough blocks to signal and take care of + different file starting offsets. + + In order to prevent this attack, the default was changed to cbc-essiv. + ESSIV uses a keyed hash of the sector number, with the encryption key as + key. This makes the IV unpredictable without knowing the encryption key + and the watermarking attack fails. + + + * 5.15 Are there any problems with "plain" IV? What is "plain64"? + + First, "plain" and "plain64" are both not secure to use with CBC, see + previous FAQ item. + + However there are modes, like XTS, that are secure with "plain" IV. The + next limit is that "plain" is 64 bit, with the upper 32 bit set to zero. + This means that on volumes larger than 2TiB, the IV repeats, creating a + vulnerability that potentially leaks some data. To avoid this, use + "plain64", which uses the full sector number up to 64 bit. Note that + "plain64" requires a kernel 2.6.33 or more recent. Also note that + "plain64" is backwards compatible for volume sizes of maximum size 2TiB, + but not for those > 2TiB. Finally, "plain64" does not cause any + performance penalty compared to "plain". + + + * 5.16 What about XTS mode? XTS mode is potentially even more secure than cbc-essiv (but only if - cbc-essiv is insecure in your scenario). It is a NIST standard and - used, e.g. in Truecrypt. From version 1.6.0 of cryptsetup onwards, - aes-xts-plain64 is the default for LUKS. If you want to use it - with a cryptsetup before version 1.6.0 or with plain dm-crypt, you - have to specify it manually as "aes-xts-plain", i.e. + cbc-essiv is insecure in your scenario). It is a NIST standard and + used, e.g. in Truecrypt. From version 1.6.0 of cryptsetup onwards, + aes-xts-plain64 is the default for LUKS. If you want to use it with a + cryptsetup before version 1.6.0 or with plain dm-crypt, you have to + specify it manually as "aes-xts-plain", i.e. - cryptsetup -c aes-xts-plain luksFormat - - For volumes >2TiB and kernels >= 2.6.33 use "plain64" (see FAQ - item on "plain" and "plain64"): + cryptsetup -c aes-xts-plain luksFormat - cryptsetup -c aes-xts-plain64 luksFormat - - There is a potential security issue with XTS mode and large blocks. - LUKS and dm-crypt always use 512B blocks and the issue does not - apply. + For volumes >2TiB and kernels >= 2.6.33 use "plain64" (see FAQ item + on "plain" and "plain64"): + + cryptsetup -c aes-xts-plain64 luksFormat + There is a potential security issue with XTS mode and large blocks. + LUKS and dm-crypt always use 512B blocks and the issue does not apply. - * 5.17 Is LUKS FIPS-140-2 certified? - No. But that is more a problem of FIPS-140-2 than of LUKS. From a + * 5.17 Is LUKS FIPS-140-2 certified? + + No. But that is more a problem of FIPS-140-2 than of LUKS. From a technical point-of-view, LUKS with the right parameters would be - FIPS-140-2 compliant, but in order to make it certified, somebody - has to pay real money for that. And then, whenever cryptsetup is - changed or extended, the certification lapses and has to be - obtained again. - - From the aspect of actual security, LUKS with default parameters - should be as good as most things that are FIPS-140-2 certified, - although you may want to make sure to use /dev/random (by - specifying --use-random on luksFormat) as randomness source for - the master key to avoid being potentially insecure in an - entropy-starved situation. - - - * 5.18 What about Plausible Deniability? - - First let me attempt a definition for the case of encrypted - filesystems: Plausible deniability is when you hide encrypted data - inside an encrypted container and it is not possible to prove it is - there. The idea is compelling and on first glance it seems - possible to do it. And from a cryptographic point of view, it - actually is possible. - - So, does it work in practice? No, unfortunately. The reasoning used - by its proponents is fundamentally flawed in several ways and the + FIPS-140-2 compliant, but in order to make it certified, somebody has to + pay real money for that. And then, whenever cryptsetup is changed or + extended, the certification lapses and has to be obtained again. + + From the aspect of actual security, LUKS with default parameters should + be as good as most things that are FIPS-140-2 certified, although you + may want to make sure to use /dev/random (by specifying --use-random on + luksFormat) as randomness source for the master key to avoid being + potentially insecure in an entropy-starved situation. + + + * 5.18 What about Plausible Deniability? + + First let me attempt a definition for the case of encrypted filesystems: + Plausible deniability is when you store data inside an encrypted + container and it is not possible to prove it is there without having a + special passphrase. And at the same time it must be "plausible" that + there actually is no hidden data there. + + As a simple entropy-analysis will show that here may be data there, the + second part is what makes it tricky. + + There seem to be a lot of misunderstandings about this idea, so let me + make it clear that this refers to the situation where the attackers can + prove that there is data that either may be random or may be part of a + plausible-deniability scheme, they just cannot prove which one it is. + Hence a plausible-deniability scheme must hold up when the attackers + know there is something potentially fishy. If you just hide data and + rely on it not being found, that is just simple deniability, not + "plausible" deniability and I am not talking about that in the + following. Simple deniability against a low-competence attacker may be + as simple as renaming a file or putting data into an unused part of a + disk. Simple deniability against a high-skill attacker with time to + invest is usually pointless unless you go for advanced steganographic + techniques, which have their own drawbacks, such as low data capacity. + + Now, the idea of plausible deniability is compelling and on a first + glance it seems possible to do it. And from a cryptographic point of + view, it actually is possible. + + So, does the idea work in practice? No, unfortunately. The reasoning + used by its proponents is fundamentally flawed in several ways and the cryptographic properties fail fatally when colliding with the real world. First, why should "I do not have a hidden partition" be any more - plausible than "I forgot my crypto key" or "I wiped that partition - with random data, nothing in there"? I do not see any reason. - - Second, there are two types of situations: Either they cannot force - you to give them the key (then you simply do not) or the can. In - the second case, they can always do bad things to you, because they - cannot prove that you have the key in the first place! This means - they do not have to prove you have the key, or that this random - looking data on your disk is actually encrypted data. So the - situation will allow them to waterboard/lock-up/deport you - anyways, regardless of how "plausible" your deniability is. Do not - have a hidden partition you could show to them, but there are - indications you may? Too bad for you. Unfortunately "plausible - deniability" also means you cannot prove there is no hidden data. - - Third, hidden partitions are not that hidden. There are basically - just two possibilities: a) Make a large crypto container, but put a - smaller filesystem in there and put the hidden partition into the - free space. Unfortunately this is glaringly obvious and can be - detected in an automated fashion. This means that the initial - suspicion to put you under duress in order to make you reveal you - hidden data is given. b) Make a filesystem that spans the whole - encrypted partition, and put the hidden partition into space not - currently used by that filesystem. Unfortunately that is also - glaringly obvious, as you then cannot write to the filesystem - without a high risk of destroying data in the hidden container. - Have not written anything to the encrypted filesystem in a while? - Too bad, they have the suspicion they need to do unpleasant things - to you. - - To be fair, if you prepare option b) carefully and directly before - going into danger, it may work. But then, the mere presence of - encrypted data may already be enough to get you into trouble in - those places were they can demand encryption keys. + plausible than "I forgot my crypto key" or "I wiped that partition with + random data, nothing in there"? I do not see any reason. + + Second, there are two types of situations: Either they cannot force you + to give them the key (then you simply do not) or they can. In the + second case, they can always do bad things to you, because they cannot + prove that you have the key in the first place! This means they do not + have to prove you have the key, or that this random looking data on your + disk is actually encrypted data. So the situation will allow them to + waterboard/lock-up/deport you anyways, regardless of how "plausible" + your deniability is. Do not have a hidden partition you could show to + them, but there are indications you may? Too bad for you. + Unfortunately "plausible deniability" also means you cannot prove there + is no hidden data. + + Third, hidden partitions are not that hidden. There are basically just + two possibilities: a) Make a large crypto container, but put a smaller + filesystem in there and put the hidden partition into the free space. + Unfortunately this is glaringly obvious and can be detected in an + automated fashion. This means that the initial suspicion to put you + under duress in order to make you reveal your hidden data is given. b) + Make a filesystem that spans the whole encrypted partition, and put the + hidden partition into space not currently used by that filesystem. + Unfortunately that is also glaringly obvious, as you then cannot write + to the filesystem without a high risk of destroying data in the hidden + container. Have not written anything to the encrypted filesystem in a + while? Too bad, they have the suspicion they need to do unpleasant + things to you. + + To be fair, if you prepare option b) carefully and directly before going + into danger, it may work. But then, the mere presence of encrypted data + may already be enough to get you into trouble in those places were they + can demand encryption keys. Here is an additional reference for some problems with plausible - deniability: http://www.schneier.com/paper-truecrypt-dfs.pdf I - strongly suggest you read it. - - So, no, I will not provide any instructions on how to do it with - plain dm-crypt or LUKS. If you insist on shooting yourself in the - foot, you can figure out how to do it yourself. - - - * 5.19 What about SSDs, Flash and Hybrid Drives? - - The problem is that you cannot reliably erase parts of these - devices, mainly due to wear-leveling and possibly defect - management. - - Basically, when overwriting a sector (of 512B), what the device - does is to move an internal sector (may be 128kB or even larger) to - some pool of discarded, not-yet erased unused sectors, take a - fresh empty sector from the empty-sector pool and copy the old - sector over with the changes to the small part you wrote. This is - done in some fashion so that larger writes do not cause a lot of - small internal updates. - - The thing is that the mappings between outside-addressable sectors - and inside sectors is arbitrary (and the vendors are not talking). - Also the discarded sectors are not necessarily erased immediately. - They may linger a long time. - - For plain dm-crypt, the consequences are that older encrypted data - may be lying around in some internal pools of the device. Thus may - or may not be a problem and depends on the application. Remember - the same can happen with a filesystem if consecutive writes to the - same area of a file can go to different sectors. - - However, for LUKS, the worst case is that key-slots and LUKS - header may end up in these internal pools. This means that password - management functionality is compromised (the old passwords may - still be around, potentially for a very long time) and that fast - erase by overwriting the header and key-slot area is insecure. - - Also keep in mind that the discarded/used pool may be large. For - example, a 240GB SSD has about 16GB of spare area in the chips that - it is free to do with as it likes. You would need to make each - individual key-slot larger than that to allow reliable overwriting. - And that assumes the disk thinks all other space is in use. - Reading the internal pools using forensic tools is not that hard, - but may involve some soldering. + deniability: http://www.schneier.com/paper-truecrypt-dfs.pdf I strongly + suggest you read it. + + So, no, I will not provide any instructions on how to do it with plain + dm-crypt or LUKS. If you insist on shooting yourself in the foot, you + can figure out how to do it yourself. + + + * 5.19 What about SSDs, Flash, Hybrid and SMR Drives? + + The problem is that you cannot reliably erase parts of these devices, + mainly due to wear-leveling and possibly defect management and delayed + writes to the main data area. + + For example for SSDs, when overwriting a sector, what the device does is + to move an internal sector (may be 128kB or even larger) to some pool of + discarded, not-yet erased unused sectors, take a fresh empty sector from + the empty-sector pool and copy the old sector over with the changes to + the small part you wrote. This is done in some fashion so that larger + writes do not cause a lot of small internal updates. + + The thing is that the mappings between outside-addressable sectors and + inside sectors is arbitrary (and the vendors are not talking). Also the + discarded sectors are not necessarily erased immediately. They may + linger a long time. + + For plain dm-crypt, the consequences are that older encrypted data may + be lying around in some internal pools of the device. Thus may or may + not be a problem and depends on the application. Remember the same can + happen with a filesystem if consecutive writes to the same area of a + file can go to different sectors. + + However, for LUKS, the worst case is that key-slots and LUKS header may + end up in these internal pools. This means that password management + functionality is compromised (the old passwords may still be around, + potentially for a very long time) and that fast erase by overwriting the + header and key-slot area is insecure. + + Also keep in mind that the discarded/used pool may be large. For + example, a 240GB SSD has about 16GB of spare area in the chips that it + is free to do with as it likes. You would need to make each individual + key-slot larger than that to allow reliable overwriting. And that + assumes the disk thinks all other space is in use. Reading the internal + pools using forensic tools is not that hard, but may involve some + soldering. What to do? - If you trust the device vendor (you probably should not...) you can - try an ATA "secure erase" command for SSDs. That does not work for - USB keys though and may or may not be secure for a hybrid drive. If - it finishes on an SSD after a few seconds, it was possibly faked. - Unfortunately, for hybrid drives that indicator does not work, as - the drive may well take the time to truly erase the magnetic part, - but only mark the SSD/Flash part as erased while data is still in - there. + If you trust the device vendor (you probably should not...) you can try + an ATA "secure erase" command. That is not present in USB keys though + and may or may not be secure for a hybrid drive. If you can do without password management and are fine with doing - physical destruction for permanently deleting data (always after - one or several full overwrites!), you can use plain dm-crypt or - LUKS. - - If you want or need all the original LUKS security features to work, - you can use a detached LUKS header and put that on a conventional, - magnetic disk. That leaves potentially old encrypted data in the - pools on the disk, but otherwise you get LUKS with the same - security as on a magnetic disk. - - If you are concerned about your laptop being stolen, you are likely - fine using LUKS on an SSD or hybrid drive. An attacker would need - to have access to an old passphrase (and the key-slot for this old - passphrase would actually need to still be somewhere in the SSD) - for your data to be at risk. So unless you pasted your old - passphrase all over the Internet or the attacker has knowledge of - it from some other source and does a targeted laptop theft to get - at your data, you should be fine. - - - * 5.20 LUKS is broken! It uses SHA-1! - - No, it is not. SHA-1 is (academically) broken for finding - collisions, but not for using it in a key-derivation function. And - that collision vulnerability is for non-iterated use only. And you - need the hash-value in verbatim. - - This basically means that if you already have a slot-key, and you - have set the PBKDF2 iteration count to 1 (it is > 10'000 normally), - you could (maybe) derive a different passphrase that gives you the - the same slot-key. But if you have the slot-key, you can already - unlock the key-slot and get the master key, breaking everything. So - basically, this SHA-1 vulnerability allows you to open a LUKS - container with high effort when you already have it open. - - The real problem here is people that do not understand crypto and - claim things are broken just because some mechanism is used that - has been broken for a specific different use. The way the mechanism - is used matters very much. A hash that is broken for one use can be - completely secure for other uses and here it is. + physical destruction for permanently deleting data (always after one or + several full overwrites!), you can use plain dm-crypt. + + If you want or need all the original LUKS security features to work, you + can use a detached LUKS header and put that on a conventional, magnetic + disk. That leaves potentially old encrypted data in the pools on the + main disk, but otherwise you get LUKS with the same security as on a + traditional magnetic disk. Note however that storage vendors are prone + to lying to their customers. For example, it recently came out that + HDDs sold without any warning or mentioning in the data-sheets were + actually using SMR and that will write data first to a faster area and + only overwrite the original data area some time later when things are + quiet. + + If you are concerned about your laptop being stolen, you are likely fine + using LUKS on an SSD or hybrid drive. An attacker would need to have + access to an old passphrase (and the key-slot for this old passphrase + would actually need to still be somewhere in the SSD) for your data to + be at risk. So unless you pasted your old passphrase all over the + Internet or the attacker has knowledge of it from some other source and + does a targeted laptop theft to get at your data, you should be fine. + + + * 5.20 LUKS1 is broken! It uses SHA-1! + + No, it is not. SHA-1 is (academically) broken for finding collisions, + but not for using it in a key-derivation function. And that collision + vulnerability is for non-iterated use only. And you need the hash-value + in verbatim. + + This basically means that if you already have a slot-key, and you have + set the PBKDF2 iteration count to 1 (it is > 10'000 normally), you could + (maybe) derive a different passphrase that gives you the the same + slot-key. But if you have the slot-key, you can already unlock the + key-slot and get the master key, breaking everything. So basically, + this SHA-1 vulnerability allows you to open a LUKS1 container with high + effort when you already have it open. + + The real problem here is people that do not understand crypto and claim + things are broken just because some mechanism is used that has been + broken for a specific different use. The way the mechanism is used + matters very much. A hash that is broken for one use can be completely + secure for other uses and here it is. + + Since version 1.7.0, cryptsetup uses SHA-256 as default to ensure that + it will be compatible in the future. There are already some systems + where SHA-1 is completely phased out or disabled by a security policy. * 5.21 Why is there no "Nuke-Option"? - A "Nuke-Option" or "Kill-switch" is a password that when entered - upon unlocking instead wipes the header and all passwords. So when - somebody forces you to enter your password, you can destroy the - data instead. + A "Nuke-Option" or "Kill-switch" is a password that when entered upon + unlocking instead wipes the header and all passwords. So when somebody + forces you to enter your password, you can destroy the data instead. While this sounds attractive at first glance, it does not make sense - once a real security analysis is done. One problem is that you have - to have some kind of HSM (Hardware Security Module) in order to - implement it securely. In the movies, a HSM starts to smoke and - melt once the Nuke-Option has been activated. In reality, it just - wipes some battery-backed RAM cells. A proper HSM costs something - like 20'000...100'000 EUR/USD and there a Nuke-Option may make some - sense. BTW, a chipcard or a TPM is not a HSM, although some - vendors are promoting that myth. - - Now, a proper HSMs will have a wipe option but not a Nuke-Option, - i.e. you can explicitly wipe the HSM, but by a different process - than unlocking it takes. Why is that? Simple: If somebody can force - you to reveal passwords, then they can also do bad things to you if - you do not or if you enter a nuke password instead. Think locking - you up for a few years for "destroying evidence" or for far longer - and without trial for being a "terrorist suspect". No HSM maker - will want to expose its customers to that risk. - - Now think of the typical LUKS application scenario, i.e. disk - encryption. Usually the ones forcing you to hand over your password + once a real security analysis is done. One problem is that you have to + have some kind of HSM (Hardware Security Module) in order to implement + it securely. In the movies, a HSM starts to smoke and melt once the + Nuke-Option has been activated. In actual reality, it just wipes some + battery-backed RAM cells. A proper HSM costs something like + 20'000...100'000 EUR/USD and there a Nuke-Option may make some sense. + BTW, a chipcard or a TPM is not a HSM, although some vendors are + promoting that myth. + + Now, a proper HSMs will have a wipe option but not a Nuke-Option, i.e. + you can explicitly wipe the HSM, but by a different process than + unlocking it takes. Why is that? Simple: If somebody can force you to + reveal passwords, then they can also do bad things to you if you do not + or if you enter a nuke password instead. Think locking you up for a few + years for "destroying evidence" or for far longer and without trial for + being a "terrorist suspect". No HSM maker will want to expose its + customers to that risk. + + Now think of the typical LUKS application scenario, i.e. disk + encryption. Usually the ones forcing you to hand over your password will have access to the disk as well, and, if they have any real - suspicion, they will mirror your disk before entering anything - supplied by you. This neatly negates any Nuke-Option. If they have - no suspicion (just harassing people that cross some border for - example), the Nuke-Option would work, but see above about likely - negative consequences and remember that a Nuke-Option may not work - reliably on SSD and hybrid drives anyways. + suspicion, they will mirror your disk before entering anything supplied + by you. This neatly negates any Nuke-Option. If they have no suspicion + (just harassing people that cross some border for example), the + Nuke-Option would work, but see above about likely negative consequences + and remember that a Nuke-Option may not work reliably on SSD and hybrid + drives anyways. Hence my advice is to never take data that you do not want to reveal - into any such situation in the first place. There is no need to - transfer data on physical carriers today. The Internet makes it - quite possible to transfer data between arbitrary places and modern - encryption makes it secure. If you do it right, nobody will even be - able to identify source or destination. (How to do that is out of - scope of this document. It does require advanced skills in this age - of pervasive surveillance.) - - Hence, LUKS has not kill option because it would do much more harm - than good. - - Still, if you have a good use-case (i.e. non-abstract real-world - situation) where a Nuke-Option would actually be beneficial, please - let me know. + into any such situation in the first place. There is no need to + transfer data on physical carriers today. The Internet makes it quite + possible to transfer data between arbitrary places and modern encryption + makes it secure. If you do it right, nobody will even be able to + identify source or destination. (How to do that is out of scope of this + document. It does require advanced skills in this age of pervasive + surveillance.) + Hence, LUKS has not kill option because it would do much more harm than + good. -6. Backup and Data Recovery + Still, if you have a good use-case (i.e. non-abstract real-world + situation) where a Nuke-Option would actually be beneficial, please let + me know. + + + * 5.22 Does cryptsetup open network connections to websites, etc. ? + + This question seems not to make much sense at first glance, but here is + an example form the real world: The TrueCrypt GUI has a "Donation" + button. Press it, and a web-connection to the TrueCrypt website is + opened via the default browser, telling everybody that listens that you + use TrueCrypt. In the worst case, things like this can get people + tortured or killed. + + So: Cryptsetup will never open any network connections except the + local netlink socket it needs to talk to the kernel crypto API. + + In addition, the installation package should contain all documentation, + including this FAQ, so that you do not have to go to a web-site to read + it. (If your distro cuts the docu, please complain to them.) In + security software, any connection initiated to anywhere outside your + machine should always be the result of an explicit request for such a + connection by the user and cryptsetup will stay true to that principle. + + +6. Backup and Data Recovery * 6.1 Why do I need Backup? - First, disks die. The rate for well-treated (!) disk is about 5% - per year, which is high enough to worry about. There is some - indication that this may be even worse for some SSDs. This applies - both to LUKS and plain dm-crypt partitions. + First, disks die. The rate for well-treated (!) disk is about 5% per + year, which is high enough to worry about. There is some indication + that this may be even worse for some SSDs. This applies both to LUKS + and plain dm-crypt partitions. - Second, for LUKS, if anything damages the LUKS header or the - key-stripe area then decrypting the LUKS device can become - impossible. This is a frequent occurrence. For example an - accidental format as FAT or some software overwriting the first - sector where it suspects a partition boot sector typically makes a - LUKS partition permanently inaccessible. See more below on LUKS - header damage. + Second, for LUKS, if anything damages the LUKS header or the key-stripe + area then decrypting the LUKS device can become impossible. This is a + frequent occurrence. For example an accidental format as FAT or some + software overwriting the first sector where it suspects a partition boot + sector typically makes a LUKS1 partition permanently inaccessible. See + more below on LUKS header damage. - So, data-backup in some form is non-optional. For LUKS, you may - also want to store a header backup in some secure location. This - only needs an update if you change passphrases. + So, data-backup in some form is non-optional. For LUKS, you may also + want to store a header backup in some secure location. This only needs + an update if you change passphrases. * 6.2 How do I backup a LUKS header? - While you could just copy the appropriate number of bytes from the - start of the LUKS partition, the best way is to use command option - "luksHeaderBackup" of cryptsetup. This protects also against - errors when non-standard parameters have been used in LUKS - partition creation. Example: + While you could just copy the appropriate number of bytes from the start + of the LUKS partition, the best way is to use command option + "luksHeaderBackup" of cryptsetup. This protects also against errors + when non-standard parameters have been used in LUKS partition creation. + Example: + + cryptsetup luksHeaderBackup --header-backup-file - - cryptsetup luksHeaderBackup --header-backup-file - To restore, use the inverse command, i.e. - cryptsetup luksHeaderRestore --header-backup-file - - If you are unsure about a header to be restored, make a backup of - the current one first! You can also test the header-file without - restoring it by using the --header option for a detached header - like this: + cryptsetup luksHeaderRestore --header-backup-file + + If you are unsure about a header to be restored, make a backup of the + current one first! You can also test the header-file without restoring + it by using the --header option for a detached header like this: + + cryptsetup --header luksOpen - cryptsetup --header luksOpen - If that unlocks your keys-lot, you are good. Do not forget to close the device again. + Under some circumstances (damaged header), this fails. Then use the + following steps in case it is LUKS1: + + First determine the master-key size: + + cryptsetup luksDump + + gives a line of the form + + MK bits: + + with bits equal to 256 for the old defaults and 512 for the new + defaults. 256 bits equals a total header size of 1'052'672 Bytes and + 512 bits one of 2MiB. (See also Item 6.12) If luksDump fails, assume + 2MiB, but be aware that if you restore that, you may also restore the + first 1M or so of the filesystem. Do not change the filesystem if you + were unable to determine the header size! With that, restoring a + too-large header backup is still safe. + + Second, dump the header to file. There are many ways to do it, I + prefer the following: + + head -c 1052672 > header_backup.dmp + + or + + head -c 2M > header_backup.dmp + + for a 2MiB header. Verify the size of the dump-file to be sure. + + To restore such a backup, you can try luksHeaderRestore or do a more + basic + + cat header_backup.dmp > + - * 6.3 How do I test a LUKS header? + + * 6.3 How do I test for a LUKS header? Use - cryptsetup -v isLuks - - on the device. Without the "-v" it just signals its result via - exit-status. You can also use the more general test + cryptsetup -v isLuks - blkid -p - - which will also detect other types and give some more info. Omit + on the device. Without the "-v" it just signals its result via + exit-status. You can also use the more general test + + blkid -p + + which will also detect other types and give some more info. Omit "-p" for old versions of blkid that do not support it. - * 6.4 How do I backup a LUKS or dm-crypt partition? + * 6.4 How do I backup a LUKS or dm-crypt partition? - There are two options, a sector-image and a plain file or - filesystem backup of the contents of the partition. The sector - image is already encrypted, but cannot be compressed and contains - all empty space. The filesystem backup can be compressed, can - contain only part of the encrypted device, but needs to be - encrypted separately if so desired. + There are two options, a sector-image and a plain file or filesystem + backup of the contents of the partition. The sector image is already + encrypted, but cannot be compressed and contains all empty space. The + filesystem backup can be compressed, can contain only part of the + encrypted device, but needs to be encrypted separately if so desired. - A sector-image will contain the whole partition in encrypted form, - for LUKS the LUKS header, the keys-slots and the data area. It can - be done under Linux e.g. with dd_rescue (for a direct image copy) - and with "cat" or "dd". Example: + A sector-image will contain the whole partition in encrypted form, for + LUKS the LUKS header, the keys-slots and the data area. It can be done + under Linux e.g. with dd_rescue (for a direct image copy) and with + "cat" or "dd". Examples: + + cat /dev/sda10 > sda10.img + dd_rescue /dev/sda10 sda10.img + + You can also use any other backup software that is capable of making a + sector image of a partition. Note that compression is ineffective for + encrypted data, hence it does not make sense to use it. + + For a filesystem backup, you decrypt and mount the encrypted partition + and back it up as you would a normal filesystem. In this case the + backup is not encrypted, unless your encryption method does that. For + example you can encrypt a backup with "tar" as follows with GnuPG: + + tar cjf - | gpg --cipher-algo AES -c - > backup.tbz2.gpg - cat /dev/sda10 > sda10.img - dd_rescue /dev/sda10 sda10.img - - You can also use any other backup software that is capable of making - a sector image of a partition. Note that compression is - ineffective for encrypted data, hence it does not make sense to - use it. - - For a filesystem backup, you decrypt and mount the encrypted - partition and back it up as you would a normal filesystem. In this - case the backup is not encrypted, unless your encryption method - does that. For example you can encrypt a backup with "tar" as - follows with GnuPG: - - tar cjf - | gpg --cipher-algo AES -c - > backup.tbz2.gpg - And verify the backup like this if you are at "path": - cat backup.tbz2.gpg | gpg - | tar djf - - + cat backup.tbz2.gpg | gpg - | tar djf - + Note: Always verify backups, especially encrypted ones! - There is one problem with verifying like this: The kernel may still - have some files cached and in fact verify them against RAM or may - even verify RAM against RAM, which defeats the purpose of the - exercise. The following command empties the kernel caches: + There is one problem with verifying like this: The kernel may still have + some files cached and in fact verify them against RAM or may even verify + RAM against RAM, which defeats the purpose of the exercise. The + following command empties the kernel caches: + + echo 3 > /proc/sys/vm/drop_caches - echo 3 > /proc/sys/vm/drop_caches - Run it after backup and before verify. - In both cases GnuPG will ask you interactively for your symmetric - key. The verify will only output errors. Use "tar dvjf -" to get - all comparison results. To make sure no data is written to disk + In both cases GnuPG will ask you interactively for your symmetric key. + The verify will only output errors. Use "tar dvjf -" to get all + comparison results. To make sure no data is written to disk unencrypted, turn off swap if it is not encrypted before doing the backup. - Restore works like certification with the 'd' ('difference') - replaced by 'x' ('eXtract'). Refer to the man-page of tar for more - explanations and instructions. Note that with default options tar - will overwrite already existing files without warning. If you are - unsure about how to use tar, experiment with it in a location - where you cannot do damage. + Restore works like certification with the 'd' ('difference') replaced + by 'x' ('eXtract'). Refer to the man-page of tar for more explanations + and instructions. Note that with default options tar will overwrite + already existing files without warning. If you are unsure about how + to use tar, experiment with it in a location where you cannot do damage. - You can of course use different or no compression and you can use - an asymmetric key if you have one and have a backup of the secret - key that belongs to it. + You can of course use different or no compression and you can use an + asymmetric key if you have one and have a backup of the secret key that + belongs to it. - A second option for a filesystem-level backup that can be used when - the backup is also on local disk (e.g. an external USB drive) is - to use a LUKS container there and copy the files to be backed up - between both mounted containers. Also see next item. + A second option for a filesystem-level backup that can be used when the + backup is also on local disk (e.g. an external USB drive) is to use a + LUKS container there and copy the files to be backed up between both + mounted containers. Also see next item. - * 6.5 Do I need a backup of the full partition? Would the header and - key-slots not be enough? + * 6.5 Do I need a backup of the full partition? Would the header + and key-slots not be enough? - Backup protects you against two things: Disk loss or corruption - and user error. By far the most questions on the dm-crypt mailing - list about how to recover a damaged LUKS partition are related - to user error. For example, if you create a new filesystem on a - LUKS partition, chances are good that all data is lost - permanently. + Backup protects you against two things: Disk loss or corruption and user + error. By far the most questions on the dm-crypt mailing list about how + to recover a damaged LUKS partition are related to user error. For + example, if you create a new filesystem on a non-mapped LUKS container, + chances are good that all data is lost permanently. - For this case, a header+key-slot backup would often be enough. But - keep in mind that a well-treated (!) HDD has roughly a failure - risk of 5% per year. It is highly advisable to have a complete - backup to protect against this case. + For this case, a header+key-slot backup would often be enough. But keep + in mind that a well-treated (!) HDD has roughly a failure risk of 5% per + year. It is highly advisable to have a complete backup to protect + against this case. - * *6.6 What do I need to backup if I use "decrypt_derived"? + * 6.6 What do I need to backup if I use "decrypt_derived"? - This is a script in Debian, intended for mounting /tmp or swap with - a key derived from the master key of an already decrypted device. - If you use this for an device with data that should be persistent, - you need to make sure you either do not lose access to that master - key or have a backup of the data. If you derive from a LUKS - device, a header backup of that device would cover backing up the - master key. Keep in mind that this does not protect against disk - loss. + This is a script in Debian, intended for mounting /tmp or swap with a + key derived from the master key of an already decrypted device. If you + use this for an device with data that should be persistent, you need to + make sure you either do not lose access to that master key or have a + backup of the data. If you derive from a LUKS device, a header backup + of that device would cover backing up the master key. Keep in mind that + this does not protect against disk loss. Note: If you recreate the LUKS header of the device you derive from (using luksFormat), the master key changes even if you use the same - passphrase(s) and you will not be able to decrypt the derived - device with the new LUKS header. + passphrase(s) and you will not be able to decrypt the derived device + with the new LUKS header. - * 6.7 Does a backup compromise security? + * 6.7 Does a backup compromise security? - Depends on how you do it. However if you do not have one, you are - going to eventually lose your encrypted data. + Depends on how you do it. However if you do not have one, you are going + to eventually lose your encrypted data. - There are risks introduced by backups. For example if you - change/disable a key-slot in LUKS, a binary backup of the partition - will still have the old key-slot. To deal with this, you have to - be able to change the key-slot on the backup as well, securely - erase the backup or do a filesystem-level backup instead of a binary - one. + There are risks introduced by backups. For example if you + change/disable a key-slot in LUKS, a binary backup of the partition will + still have the old key-slot. To deal with this, you have to be able to + change the key-slot on the backup as well, securely erase the backup or + do a filesystem-level backup instead of a binary one. - If you use dm-crypt, backup is simpler: As there is no key - management, the main risk is that you cannot wipe the backup when - wiping the original. However wiping the original for dm-crypt - should consist of forgetting the passphrase and that you can do - without actual access to the backup. + If you use dm-crypt, backup is simpler: As there is no key management, + the main risk is that you cannot wipe the backup when wiping the + original. However wiping the original for dm-crypt should consist of + forgetting the passphrase and that you can do without actual access to + the backup. - In both cases, there is an additional (usually small) risk with - binary backups: An attacker can see how many sectors and which - ones have been changed since the backup. To prevent this, use a - filesystem level backup method that encrypts the whole backup in - one go, e.g. as described above with tar and GnuPG. + In both cases, there is an additional (usually small) risk with binary + backups: An attacker can see how many sectors and which ones have been + changed since the backup. To prevent this, use a filesystem level + backup method that encrypts the whole backup in one go, e.g. as + described above with tar and GnuPG. - My personal advice is to use one USB disk (low value data) or - three disks (high value data) in rotating order for backups, and - either use independent LUKS partitions on them, or use encrypted - backup with tar and GnuPG. + My personal advice is to use one USB disk (low value data) or three + disks (high value data) in rotating order for backups, and either use + independent LUKS partitions on them, or use encrypted backup with tar + and GnuPG. - If you do network-backup or tape-backup, I strongly recommend to - go the filesystem backup path with independent encryption, as you - typically cannot reliably delete data in these scenarios, - especially in a cloud setting. (Well, you can burn the tape if it - is under your control...) + If you do network-backup or tape-backup, I strongly recommend to go + the filesystem backup path with independent encryption, as you + typically cannot reliably delete data in these scenarios, especially + in a cloud setting. (Well, you can burn the tape if it is under your + control...) - * 6.8 What happens if I overwrite the start of a LUKS partition or - damage the LUKS header or key-slots? + * 6.8 What happens if I overwrite the start of a LUKS partition or + damage the LUKS header or key-slots? - There are two critical components for decryption: The salt values - in the key-slot descriptors of the header and the key-slots. If the - salt values are overwritten or changed, nothing (in the - cryptographically strong sense) can be done to access the data, - unless there is a backup of the LUKS header. If a key-slot is - damaged, the data can still be read with a different key-slot, if - there is a remaining undamaged and used key-slot. Note that in - order to make a key-slot unrecoverable in a cryptographically - strong sense, changing about 4-6 bits in random locations of its - 128kiB size is quite enough. + There are two critical components for decryption: The salt values in the + key-slot descriptors of the header and the key-slots. For LUKS2 they + are a bit better protected. but for LUKS1, these are right in the first + sector. If the salt values are overwritten or changed, nothing (in the + cryptographically strong sense) can be done to access the data, unless + there is a backup of the LUKS header. If a key-slot is damaged, the + data can still be read with a different key-slot, if there is a + remaining undamaged and used key-slot. Note that in order to make a + key-slot completely unrecoverable, changing about 4-6 bits in random + locations of its 128kiB size is quite enough. - * 6.9 What happens if I (quick) format a LUKS partition? + * 6.9 What happens if I (quick) format a LUKS partition? - I have not tried the different ways to do this, but very likely you - will have written a new boot-sector, which in turn overwrites the - LUKS header, including the salts, making your data permanently - irretrievable, unless you have a LUKS header backup. You may also - damage the key-slots in part or in full. See also last item. + I have not tried the different ways to do this, but very likely you will + have written a new boot-sector, which in turn overwrites the LUKS + header, including the salts, making your data permanently irretrievable, + unless you have a LUKS header backup. For LUKS2 this may still be + recoverable without that header backup, for LUKS1 it is not. You may + also damage the key-slots in part or in full. See also last item. - * 6.10 How do I recover the master key from a mapped LUKS container? + * 6.10 How do I recover the master key from a mapped LUKS1 container? - This is typically only needed if you managed to damage your LUKS - header, but the container is still mapped, i.e. "luksOpen"ed. It - also helps if you have a mapped container that you forgot or do not - know a passphrase for (e.g. on a long running server.) + Note: LUKS2 uses the kernel keyring to store keys and hence this + procedure does not work unless you have explicitly disabled the use of + the keyring with "--disable-keyring" on opening. + + This is typically only needed if you managed to damage your LUKS1 + header, but the container is still mapped, i.e. "luksOpen"ed. It also + helps if you have a mapped container that you forgot or do not know a + passphrase for (e.g. on a long running server.) WARNING: Things go wrong, do a full backup before trying this! - WARNING: This exposes the master key of the LUKS container. Note - that both ways to recreate a LUKS header with the old master key - described below will write the master key to disk. Unless you are - sure you have securely erased it afterwards, e.g. by writing it to - an encrypted partition, RAM disk or by erasing the filesystem you - wrote it to by a complete overwrite, you should change the master - key afterwards. Changing the master key requires a full data - backup, luksFormat and then restore of the backup. - - First, there is a script by Milan that automates the whole - process, except generating a new LUKS header with the old master - key (it prints the command for that though): + WARNING: This exposes the master key of the LUKS1 container. Note that + both ways to recreate a LUKS header with the old master key described + below will write the master key to disk. Unless you are sure you have + securely erased it afterwards, e.g. by writing it to an encrypted + partition, RAM disk or by erasing the filesystem you wrote it to by a + complete overwrite, you should change the master key afterwards. + Changing the master key requires a full data backup, luksFormat and then + restore of the backup. Alternatively the tool cryptsetup-reencrypt from + the cryptsetup package can be used to change the master key (see its + man-page), but a full backup is still highly recommended. + + First, there is a script by Milan that automates the whole process, + except generating a new LUKS1 header with the old master key (it prints + the command for that though): https://gitlab.com/cryptsetup/cryptsetup/blob/master/misc/luks-header-from-active You can also do this manually. Here is how: - - Get the master key from the device mapper. This is done by the - following command. Substitute c5 for whatever you mapped to: + - Get the master key from the device mapper. This is done by the + following command. Substitute c5 for whatever you mapped to: - # dmsetup table --target crypt --showkey /dev/mapper/c5 - Result: - 0 200704 crypt aes-cbc-essiv:sha256 - a1704d9715f73a1bb4db581dcacadaf405e700d591e93e2eaade13ba653d0d09 - 0 7:0 4096 - - The result is actually one line, wrapped here for clarity. The long + # dmsetup table --target crypt --showkey /dev/mapper/c5 + + Result: + 0 200704 crypt aes-cbc-essiv:sha256 + a1704d9715f73a1bb4db581dcacadaf405e700d591e93e2eaade13ba653d0d09 + 0 7:0 4096 + + The result is actually one line, wrapped here for clarity. The long hex string is the master key. - - Convert the master key to a binary file representation. You can - do this manually, e.g. with hexedit. You can also use the tool - "xxd" from vim like this: + - Convert the master key to a binary file representation. You can do + this manually, e.g. with hexedit. You can also use the tool "xxd" + from vim like this: + + echo "a1704d9....53d0d09" | xxd -r -p > - echo "a1704d9....53d0d09" | xxd -r -p > - - - Do a luksFormat to create a new LUKS header. - NOTE: If your header is intact and you just forgot the - passphrase, you can just set a new passphrase, see next - sub-item. + - Do a luksFormat to create a new LUKS1 header. + + NOTE: If your header is intact and you just forgot the passphrase, + you can just set a new passphrase, see next sub-item. Unmap the device before you do that (luksClose). Then do - cryptsetup luksFormat --master-key-file= - + cryptsetup luksFormat --master-key-file= + Note that if the container was created with other than the default settings of the cryptsetup version you are using, you need to give - additional parameters specifying the deviations. If in doubt, try - the script by Milan. It does recover the other parameters as well. + additional parameters specifying the deviations. If in doubt, try the + script by Milan. It does recover the other parameters as well. - Side note: This is the way the decrypt_derived script gets at the - master key. It just omits the conversion and hashes the master key - string. + Side note: This is the way the decrypt_derived script gets at the master + key. It just omits the conversion and hashes the master key string. - If the header is intact and you just forgot the passphrase, just set a new passphrase like this: cryptsetup luksAddKey --master-key-file= - + You may want to disable the old one afterwards. - * 6.11 What does the on-disk structure of dm-crypt look like? - - There is none. dm-crypt takes a block device and gives encrypted - access to each of its blocks with a key derived from the passphrase - given. If you use a cipher different than the default, you have to - specify that as a parameter to cryptsetup too. If you want to - change the password, you basically have to create a second - encrypted device with the new passphrase and copy your data over. - On the plus side, if you accidentally overwrite any part of a - dm-crypt device, the damage will be limited to the area you - overwrote. - - - * 6.12 What does the on-disk structure of LUKS look like? - - A LUKS partition consists of a header, followed by 8 key-slot - descriptors, followed by 8 key slots, followed by the encrypted - data area. - - Header and key-slot descriptors fill the first 592 bytes. The - key-slot size depends on the creation parameters, namely on the - number of anti-forensic stripes, key material offset and master - key size. - - With the default parameters, each key-slot is a bit less than - 128kiB in size. Due to sector alignment of the key-slot start, - that means the key block 0 is at offset 0x1000-0x20400, key - block 1 at offset 0x21000-0x40400, and key block 7 at offset - 0xc1000-0xe0400. The space to the next full sector address is - padded with zeros. Never used key-slots are filled with what the - disk originally contained there, a key-slot removed with - "luksRemoveKey" or "luksKillSlot" gets filled with 0xff. Due to - 2MiB default alignment, start of the data area for cryptsetup 1.3 - and later is at 2MiB, i.e. at 0x200000. For older versions, it is - at 0x101000, i.e. at 1'052'672 bytes, i.e. at 1MiB + 4096 bytes - from the start of the partition. Incidentally, "luksHeaderBackup" - for a LUKS container created with default parameters dumps exactly - the first 2MiB (or 1'052'672 bytes for headers created with - cryptsetup versions < 1.3) to file and "luksHeaderRestore" restores + * 6.11 What does the on-disk structure of dm-crypt look like? + + There is none. dm-crypt takes a block device and gives encrypted access + to each of its blocks with a key derived from the passphrase given. If + you use a cipher different than the default, you have to specify that as + a parameter to cryptsetup too. If you want to change the password, you + basically have to create a second encrypted device with the new + passphrase and copy your data over. On the plus side, if you + accidentally overwrite any part of a dm-crypt device, the damage will be + limited to the area you overwrote. + + + * 6.12 What does the on-disk structure of LUKS1 look like? + + Note: For LUKS2, refer to the LUKS2 document referenced in Item 1.2 + + A LUKS1 partition consists of a header, followed by 8 key-slot + descriptors, followed by 8 key slots, followed by the encrypted data + area. + + Header and key-slot descriptors fill the first 592 bytes. The key-slot + size depends on the creation parameters, namely on the number of + anti-forensic stripes, key material offset and master key size. + + With the default parameters, each key-slot is a bit less than 128kiB in + size. Due to sector alignment of the key-slot start, that means the key + block 0 is at offset 0x1000-0x20400, key block 1 at offset + 0x21000-0x40400, and key block 7 at offset 0xc1000-0xe0400. The space + to the next full sector address is padded with zeros. Never used + key-slots are filled with what the disk originally contained there, a + key-slot removed with "luksRemoveKey" or "luksKillSlot" gets filled with + 0xff. Due to 2MiB default alignment, start of the data area for + cryptsetup 1.3 and later is at 2MiB, i.e. at 0x200000. For older + versions, it is at 0x101000, i.e. at 1'052'672 bytes, i.e. at 1MiB + + 4096 bytes from the start of the partition. Incidentally, + "luksHeaderBackup" for a LUKS container created with default parameters + dumps exactly the first 2MiB (or 1'052'672 bytes for headers created + with cryptsetup versions < 1.3) to file and "luksHeaderRestore" restores them. - For non-default parameters, you have to figure out placement - yourself. "luksDump" helps. See also next item. For the most common - non-default settings, namely aes-xts-plain with 512 bit key, the - offsets are: 1st keyslot 0x1000-0x3f800, 2nd keyslot - 0x40000-0x7e000, 3rd keyslot 0x7e000-0xbd800, ..., and start of - bulk data at 0x200000. + For non-default parameters, you have to figure out placement yourself. + "luksDump" helps. See also next item. For the most common non-default + settings, namely aes-xts-plain with 512 bit key, the offsets are: 1st + keyslot 0x1000-0x3f800, 2nd keyslot 0x40000-0x7e000, 3rd keyslot + 0x7e000-0xbd800, ..., and start of bulk data at 0x200000. The exact specification of the format is here: - https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification + https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification + + For your convenience, here is the LUKS1 header with hex offsets. + NOTE: + The spec counts key-slots from 1 to 8, but the cryptsetup tool counts + from 0 to 7. The numbers here refer to the cryptsetup numbers. + - For your convenience, here is the LUKS header with hex offsets. - NOTE: The spec counts key-slots from 1 to 8, but the cryptsetup - tool counts from 0 to 7. The numbers here refer to the cryptsetup - numbers. +Refers to LUKS1 On-Disk Format Specification Version 1.2.3 + +LUKS1 header: -Refers to LUKS On-Disk Format Specification Version 1.2.1 -LUKS header: offset length name data type description ----------------------------------------------------------------------- 0x0000 0x06 magic byte[] 'L','U','K','S', 0xba, 0xbe @@ -2140,7 +2303,10 @@ offset length name data type description 496 48 0x0220 0x30 key-slot-7 key slot key slot 7 544 48 + + Key slot: + offset length name data type description ------------------------------------------------------------------------- 0x0000 0x04 active uint32_t key slot enabled/disabled @@ -2153,114 +2319,113 @@ offset length name data type description 40 4 (512 bytes/sector) 0x002c 0x04 stripes uint32_t number of anti-forensic 44 4 stripes - - * 6.13 What is the smallest possible LUKS container? - Note: From cryptsetup 1.3 onwards, alignment is set to 1MB. With - modern Linux partitioning tools that also align to 1MB, this will - result in alignment to 2k sectors and typical Flash/SSD sectors, - which is highly desirable for a number of reasons. Changing the - alignment is not recommended. - That said, with default parameters, the data area starts at - exactly 2MB offset (at 0x101000 for cryptsetup versions before - 1.3). The smallest data area you can have is one sector of 512 - bytes. Data areas of 0 bytes can be created, but fail on mapping. + * 6.13 What is the smallest possible LUKS1 container? + + Note: From cryptsetup 1.3 onwards, alignment is set to 1MB. With modern + Linux partitioning tools that also align to 1MB, this will result in + alignment to 2k sectors and typical Flash/SSD sectors, which is highly + desirable for a number of reasons. Changing the alignment is not + recommended. + + That said, with default parameters, the data area starts at exactly 2MB + offset (at 0x101000 for cryptsetup versions before 1.3). The smallest + data area you can have is one sector of 512 bytes. Data areas of 0 + bytes can be created, but fail on mapping. While you cannot put a filesystem into something this small, it may - still be used to contain, for example, key. Note that with current - formatting tools, a partition for a container this size will be - 3MiB anyways. If you put the LUKS container into a file (via - losetup and a loopback device), the file needs to be 2097664 bytes - in size, i.e. 2MiB + 512B. - - There two ways to influence the start of the data area are key-size - and alignment. - - For alignment, you can go down to 1 on the parameter. This will - still leave you with a data-area starting at 0x101000, i.e. - 1MiB+4096B (default parameters) as alignment will be rounded up to - the next multiple of 8 (i.e. 4096 bytes) If in doubt, do a dry-run - on a larger file and dump the LUKS header to get actual - information. - - For key-size, you can use 128 bit (e.g. AES-128 with CBC), 256 bit - (e.g. AES-256 with CBC) or 512 bit (e.g. AES-256 with XTS mode). - You can do 64 bit (e.g. blowfish-64 with CBC), but anything below - 128 bit has to be considered insecure today. + still be used to contain, for example, key. Note that with current + formatting tools, a partition for a container this size will be 3MiB + anyways. If you put the LUKS container into a file (via losetup and a + loopback device), the file needs to be 2097664 bytes in size, i.e. 2MiB + + 512B. + + The two ways to influence the start of the data area are key-size and + alignment. + + For alignment, you can go down to 1 on the parameter. This will still + leave you with a data-area starting at 0x101000, i.e. 1MiB+4096B + (default parameters) as alignment will be rounded up to the next + multiple of 8 (i.e. 4096 bytes) If in doubt, do a dry-run on a larger + file and dump the LUKS header to get actual information. + + For key-size, you can use 128 bit (e.g. AES-128 with CBC), 256 bit + (e.g. AES-256 with CBC) or 512 bit (e.g. AES-256 with XTS mode). You + can do 64 bit (e.g. blowfish-64 with CBC), but anything below 128 bit + has to be considered insecure today. Example 1 - AES 128 bit with CBC: cryptsetup luksFormat -s 128 --align-payload=8 - + This results in a data offset of 0x81000, i.e. 516KiB or 528384 - bytes. Add one 512 byte sector and the smallest LUKS container size + bytes. Add one 512 byte sector and the smallest LUKS container size with these parameters is 516KiB + 512B or 528896 bytes. Example 2 - Blowfish 64 bit with CBC (WARNING: insecure): cryptsetup luksFormat -c blowfish -s 64 --align-payload=8 /dev/loop0 - + This results in a data offset of 0x41000, i.e. 260kiB or 266240 - bytes, with a minimal LUKS container size of 260kiB + 512B or - 266752 bytes. + bytes, with a minimal LUKS1 container size of 260kiB + 512B or 266752 + bytes. - * 6.14 I think this is overly complicated. Is there an alternative? + * 6.14 I think this is overly complicated. Is there an alternative? - Not really. Encryption comes at a price. You can use plain - dm-crypt to simplify things a bit. It does not allow multiple - passphrases, but on the plus side, it has zero on disk description - and if you overwrite some part of a plain dm-crypt partition, - exactly the overwritten parts are lost (rounded up to sector - borders). + Not really. Encryption comes at a price. You can use plain dm-crypt to + simplify things a bit. It does not allow multiple passphrases, but on + the plus side, it has zero on disk description and if you overwrite some + part of a plain dm-crypt partition, exactly the overwritten parts are + lost (rounded up to full sectors). + * 6.15 Can I clone a LUKS container? - * 6.15 Can I clone a LUKS container? + You can, but it breaks security, because the cloned container has the + same header and hence the same master key. Even if you change the + passphrase(s), the master key stays the same. That means whoever has + access to one of the clones can decrypt them all, completely bypassing + the passphrases. - You can, but it breaks security, because the cloned container has - the same header and hence the same master key. You cannot change - the master key on a LUKS container, even if you change the - passphrase(s), the master key stays the same. That means whoever - has access to one of the clones can decrypt them all, completely - bypassing the passphrases. + While you can use cryptsetup-reencrypt to change the master key, + this is probably more effort than to create separate LUKS containers + in the first place. - The right way to do this is to first luksFormat the target - container, then to clone the contents of the source container, with - both containers mapped, i.e. decrypted. You can clone the decrypted - contents of a LUKS container in binary mode, although you may run - into secondary issues with GUIDs in filesystems, partition tables, - RAID-components and the like. These are just the normal problems - binary cloning causes. + The right way to do this is to first luksFormat the target container, + then to clone the contents of the source container, with both containers + mapped, i.e. decrypted. You can clone the decrypted contents of a LUKS + container in binary mode, although you may run into secondary issues + with GUIDs in filesystems, partition tables, RAID-components and the + like. These are just the normal problems binary cloning causes. Note that if you need to ship (e.g.) cloned LUKS containers with a default passphrase, that is fine as long as each container was - individually created (and hence has its own master key). In this - case, changing the default passphrase will make it secure again. + individually created (and hence has its own master key). In this case, + changing the default passphrase will make it secure again. -7. Interoperability with other Disk Encryption Tools +7. Interoperability with other Disk Encryption Tools - * 7.1 What is this section about? + * 7.1 What is this section about? - Cryptsetup for plain dm-crypt can be used to access a number of - on-disk formats created by tools like loop-aes patched into - losetup. This sometimes works and sometimes does not. This - section collects insights into what works, what does not and where - more information is required. + Cryptsetup for plain dm-crypt can be used to access a number of on-disk + formats created by tools like loop-aes patched into losetup. This + sometimes works and sometimes does not. This section collects insights + into what works, what does not and where more information is required. Additional information may be found in the mailing-list archives, - mentioned at the start of this FAQ document. If you have a - solution working that is not yet documented here and think a wider - audience may be interested, please email the FAQ maintainer. + mentioned at the start of this FAQ document. If you have a solution + working that is not yet documented here and think a wider audience may + be interested, please email the FAQ maintainer. - * 7.2 loop-aes: General observations. + * 7.2 loop-aes: General observations. - One problem is that there are different versions of losetup around. - loop-aes is a patch for losetup. Possible problems and deviations + One problem is that there are different versions of losetup around. + loop-aes is a patch for losetup. Possible problems and deviations from cryptsetup option syntax include: - Offsets specified in bytes (cryptsetup: 512 byte sectors) @@ -2273,49 +2438,53 @@ offset length name data type description - Passphrase hash algorithm needs specifying - Also note that because plain dm-crypt and loop-aes format does not - have metadata, and while the loopAES extension for cryptsetup tries - autodetection (see command loopaesOpen), it may not always work. - If you still have the old set-up, using a verbosity option (-v) - on mapping with the old tool or having a look into the system logs - after setup could give you the information you need. Below, there - are also some things that worked for somebody. + Also note that because plain dm-crypt and loop-aes format does not have + metadata, and while the loopAES extension for cryptsetup tries + autodetection (see command loopaesOpen), it may not always work. If you + still have the old set-up, using a verbosity option (-v) on mapping with + the old tool or having a look into the system logs after setup could + give you the information you need. Below, there are also some things + that worked for somebody. - * 7.3 loop-aes patched into losetup on Debian 5.x, kernel 2.6.32 + * 7.3 loop-aes patched into losetup on Debian 5.x, kernel 2.6.32 In this case, the main problem seems to be that this variant of - losetup takes the offset (-o option) in bytes, while cryptsetup - takes it in sectors of 512 bytes each. Example: The losetup command + losetup takes the offset (-o option) in bytes, while cryptsetup takes + it in sectors of 512 bytes each. + + Example: The losetup command + + losetup -e twofish -o 2560 /dev/loop0 /dev/sdb1 + mount /dev/loop0 mount-point - losetup -e twofish -o 2560 /dev/loop0 /dev/sdb1 - mount /dev/loop0 mount-point - translates to - cryptsetup create -c twofish -o 5 --skip 5 e1 /dev/sdb1 - mount /dev/mapper/e1 mount-point - + cryptsetup create -c twofish -o 5 --skip 5 e1 /dev/sdb1 + mount /dev/mapper/e1 mount-point - * 7.4 loop-aes with 160 bit key - This seems to be sometimes used with twofish and blowfish and - represents a 160 bit ripemed160 hash output padded to 196 bit key - length. It seems the corresponding options for cryptsetup are - --cipher twofish-cbc-null -s 192 -h ripemd160:20 - + * 7.4 loop-aes with 160 bit key - * 7.5 loop-aes v1 format OpenSUSE + This seems to be sometimes used with twofish and blowfish and represents + a 160 bit ripemed160 hash output padded to 196 bit key length. It seems + the corresponding options for cryptsetup are + + --cipher twofish-cbc-null -s 192 -h ripemd160:20 - Apparently this is done by older OpenSUSE distros and stopped - working from OpenSUSE 12.1 to 12.2. One user had success with the - following: - cryptsetup create -c aes -s 128 -h sha256 - - * 7.6 Kernel encrypted loop device (cryptoloop) + * 7.5 loop-aes v1 format OpenSUSE + + Apparently this is done by older OpenSUSE distros and stopped working + from OpenSUSE 12.1 to 12.2. One user had success with the following: + + cryptsetup create -c aes -s 128 -h sha256 + + + + * 7.6 Kernel encrypted loop device (cryptoloop) There are a number of different losetup implementations for using encrypted loop devices so getting this to work may need a bit of @@ -2327,176 +2496,526 @@ offset length name data type description Example for a compatible mapping: losetup -e twofish -N /dev/loop0 /image.img - + translates to cryptsetup create image_plain /image.img -c twofish-cbc-plain -H plain - + with the mapping being done to /dev/mapper/image_plain instead of to /dev/loop0. More details: - Cipher, mode and pasword hash (or no hash): + Cipher, mode and password hash (or no hash): -e cipher [-N] => -c cipher-cbc-plain -H plain [-s 256] -e cipher => -c cipher-cbc-plain -H ripemd160 [-s 256] - - Key size and offsets (losetup: bytes, cryptsetuop: sectors of 512 - bytes): + + + Key size and offsets (losetup: bytes, cryptsetuop: sectors of 512 bytes): -k 128 => -s 128 -o 2560 => -o 5 -p 5 # 2560/512 = 5 - + + There is no replacement for --pass-fd, it has to be emulated using keyfiles, see the cryptsetup man-page. -8. Issues with Specific Versions of cryptsetup +8. Issues with Specific Versions of cryptsetup - * 8.1 When using the create command for plain dm-crypt with - cryptsetup 1.1.x, the mapping is incompatible and my data is not - accessible anymore! + * 8.1 When using the create command for plain dm-crypt with + cryptsetup 1.1.x, the mapping is incompatible and my data is not + accessible anymore! With cryptsetup 1.1.x, the distro maintainer can define different - default encryption modes. You can check the compiled-in defaults - using "cryptsetup --help". Moreover, the plain device default - changed because the old IV mode was vulnerable to a watermarking - attack. + default encryption modes. You can check the compiled-in defaults using + "cryptsetup --help". Moreover, the plain device default changed because + the old IV mode was vulnerable to a watermarking attack. If you are using a plain device and you need a compatible mode, just - specify cipher, key size and hash algorithm explicitly. For - compatibility with cryptsetup 1.0.x defaults, simple use the - following: + specify cipher, key size and hash algorithm explicitly. For + compatibility with cryptsetup 1.0.x defaults, simple use the following: cryptsetup create -c aes-cbc-plain -s 256 -h ripemd160 - + LUKS stores cipher and mode in the metadata on disk, avoiding this problem. - * 8.2 cryptsetup on SLED 10 has problems... + * 8.2 cryptsetup on SLED 10 has problems... - SLED 10 is missing an essential kernel patch for dm-crypt, which - is broken in its kernel as a result. There may be a very old - version of cryptsetup (1.0.x) provided by SLED, which should also - not be used anymore as well. My advice would be to drop SLED 10. + SLED 10 is missing an essential kernel patch for dm-crypt, which is + broken in its kernel as a result. There may be a very old version of + cryptsetup (1.0.x) provided by SLED, which should also not be used + anymore as well. My advice would be to drop SLED 10. - * 8.3 Gcrypt after 1.5.3 breaks Whirlpool + * 8.3 Gcrypt 1.6.x and later break Whirlpool - It is the other way round: In gcrypt 1.5.3 and before Whirlpool is - broken and it was fixed in the next version. If you selected - whirlpool as hash on creation of a LUKS container, it does not work - anymore with the fixed library. This shows one serious risk of - using rarely used settings. + It is the other way round: In gcrypt 1.5.x, Whirlpool is broken and it + was fixed in 1.6.0 and later. If you selected whirlpool as hash on + creation of a LUKS container, it does not work anymore with the fixed + library. This shows one serious risk of using rarely used settings. - The only two ways to deal with this are either to decrypt with an - old gcrypt version that has the flaw or to use a compatibility - feature introduced in cryptsetup 1.6.4 and gcrypt 1.6.1 or later. - Versions of gcrypt between 1.5.4 and 1.6.0 cannot be used. + Note that at the time this FAQ item was written, 1.5.4 was the latest + 1.5.x version and it has the flaw, i.e. works with the old Whirlpool + version. Possibly later 1.5.x versions will work as well. If not, + please let me know. + + The only two ways to access older LUKS containers created with Whirlpool + are to either decrypt with an old gcrypt version that has the flaw or to + use a compatibility feature introduced in cryptsetup 1.6.4 and gcrypt + 1.6.1 or later. Version 1.6.0 cannot be used. Steps: - - Make a least a header backup or better, refresh your full - backup. (You have a full backup, right? See Item 6.1 and - following.) + - Make at least a header backup or better, refresh your full backup. + (You have a full backup, right? See Item 6.1 and following.) - Make sure you have cryptsetup 1.6.4 or later and check the gcrypt - version: + version: - cryptsetup luksDump --debug | grep backend - - If gcrypt is at version 1.5.3 or before: - - Reencrypt the LUKS header with a different hash. (Requires - entering all keyslot passphrases. If you do not have all, remove - the ones you do not have before.): + If gcrypt is at version 1.5.x or before: + + - Reencrypt the LUKS header with a different hash. (Requires entering + all keyslot passphrases. If you do not have all, remove the ones you + do not have before.): cryptsetup-reencrypt --keep-key --hash sha256 - + If gcrypt is at version 1.6.1 or later: - Patch the hash name in the LUKS header from "whirlpool" to - "whirlpool_gcryptbug". This activates the broken implementation. + "whirlpool_gcryptbug". This activates the broken implementation. The detailed header layout is in Item 6.12 of this FAQ and in the - LUKS on-disk format specification. One way to change the hash is + LUKS on-disk format specification. One way to change the hash is with the following command: echo -n -e 'whirlpool_gcryptbug\0' | dd of= bs=1 seek=72 conv=notrunc + + - You can now open the device again. It is highly advisable to change + the hash now with cryptsetup-reencrypt as described above. While you + can reencrypt to use the fixed whirlpool, that may not be a good idea + as almost nobody seems to use it and hence the long time until the + bug was discovered. + + +9. The Initrd question + + + * 9.1 My initrd is broken with cryptsetup + + That is not nice! However the initrd is supplied by your distribution, + not by the cryptsetup project and hence you should complain to them. We + cannot really do anything about it. + + + * 9.2 CVE-2016-4484 says cryptsetup is broken! + + Not really. It says the initrd in some Debian versions have a behavior + that under some very special and unusual conditions may be considered + a vulnerability. + + What happens is that you can trick the initrd to go to a rescue-shell if + you enter the LUKS password wrongly in a specific way. But falling back + to a rescue shell on initrd errors is a sensible default behavior in the + first place. It gives you about as much access as booting a rescue + system from CD or USB-Stick or as removing the disk would give you. So + this only applies when an attacker has physical access, but cannot boot + anything else or remove the disk. These will be rare circumstances + indeed, and if you rely on the default distribution initrd to keep you + safe under these circumstances, then you have bigger problems than this + somewhat expected behavior. + + The CVE was exagerrated and should not be assigned to upstream + cryptsetup in the first place (it is a distro specific initrd issue). + It was driven more by a try to make a splash for self-aggrandizement, + than by any actual security concerns. Ignore it. + + + * 9.3 How do I do my own initrd with cryptsetup? + + Note: The instructions here apply to an initrd in initramfs format, not + to an initrd in initrd format. The latter is a filesystem image, not a + cpio-archive, and seems to not be widely used anymore. - - You can now open the device again. It is highly advisable to - change the hash now with cryptsetup-reencrypt as described above. - While you can reencrypt to use the fixed whirlpool, that may not - be a good idea as almost nobody seems to use it and hence the long - time until the bug was discovered. + It depends on the distribution. Below, I give a very simple example and + step-by-step instructions for Debian. With a bit of work, it should be + possible to adapt this to other distributions. Note that the + description is pretty general, so if you want to do other things with an + initrd it provides a useful starting point for that too. + 01) Unpacking an existing initrd to use as template -9. References and Further Reading + A Linux initrd is in gzip'ed cpio format. To unpack it, use something + like this: + md tmp; cd tmp; cat ../initrd | gunzip | cpio -id - * Purpose of this Section + After this, you have the full initrd content in tmp/ - The purpose of this section is to collect references to all - materials that do not fit the FAQ but are relevant in some fashion. - This can be core topics like the LUKS spec or disk encryption, but - it can also be more tangential, like secure storage management or - cryptography used in LUKS. It should still have relevance to - cryptsetup and its applications. + 02) Inspecting the init-script - If you wan to see something added here, send email to the - maintainer (or the cryptsetup mailing list) giving an URL, a - description (1-3 lines preferred) and a section to put it in. You - can also propose new sections. + The init-script is the only thing the kernel cares about. All activity + starts there. Its traditional location is /sbin/init on disk, but /init + in an initrd. In an initrd unpacked as above it is tmp/init. - At this time I would like to limit the references to things that - are available on the web. + While init can be a binary despite usually being called "init script", + in Debian the main init on the root partition is a binary, but the init + in the initrd (and only that one is called by the kernel) is a script + and starts like this: + #!/bin/sh + .... - * Specifications + The "sh" used here is in tmp/bin/sh as just unpacked, and in Debian it + currently is a busybox. - - LUKS on-disk format spec: - https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification + 03) Creating your own initrd - * Code Examples + The two examples below should give you most of what is needed. This is + tested with LUKS1 and should work with LUKS2 as well. If not, please + let me know. - - Some code examples are in the source package under docs/examples + Here is a really minimal example. It does nothing but set up some + things and then drop to an interactive shell. It is perfect to try out + things that you want to go into the init-script. + + #!/bin/sh + export PATH=/sbin:/bin + [ -d /sys ] || mkdir /sys + [ -d /proc ] || mkdir /proc + [ -d /tmp ] || mkdir /tmp + mount -t sysfs -o nodev,noexec,nosuid sysfs /sys + mount -t proc -o nodev,noexec,nosuid proc /proc + echo "initrd is running, starting BusyBox..." + exec /bin/sh --login + + + Here is an example that opens the first LUKS-partition it finds with the + hard-coded password "test2" and then mounts it as root-filesystem. This + is intended to be used on an USB-stick that after boot goes into a safe, + as it contains the LUKS-passphrase in plain text and is not secure to be + left in the system. The script contains debug-output that should make it + easier to see what is going on. Note that the final hand-over to the init + on the encrypted root-partition is done by "exec switch_root /mnt/root + /sbin/init", after mounting the decrypted LUKS container with "mount + /dev/mapper/c1 /mnt/root". The second argument of switch_root is relative + to the first argument, i.e. the init started with this command is really + /mnt/sbin/init before switch_root runs. + + #!/bin/sh + export PATH=/sbin:/bin + [ -d /sys ] || mkdir /sys + [ -d /proc ] || mkdir /proc + [ -d /tmp ] || mkdir /tmp + mount -t sysfs -o nodev,noexec,nosuid sysfs /sys + mount -t proc -o nodev,noexec,nosuid proc /proc + echo "detecting LUKS containers in sda1-10, sdb1-10"; sleep 1 + for i in a b + do + for j in 1 2 3 4 5 6 7 8 9 10 + do + sleep 0.5 + d="/dev/sd"$i""$j + echo -n $d + cryptsetup isLuks $d >/dev/null 2>&1 + r=$? + echo -n " result: "$r"" + # 0 = is LUKS, 1 = is not LUKS, 4 = other error + if expr $r = 0 > /dev/null + then + echo " is LUKS, attempting unlock" + echo -n "test2" | cryptsetup luksOpen --key-file=- $d c1 + r=$? + echo " result of unlock attempt: "$r"" + sleep 2 + if expr $r = 0 > /dev/null + then + echo "*** LUKS partition unlocked, switching root *** + echo " (waiting 30 seconds before doing that)" + mount /dev/mapper/c1 /mnt/root + sleep 30 + exec switch_root /mnt/root /sbin/init + fi + else + echo " is not LUKS" + fi + done + done + echo "FAIL finding root on LUKS, loading BusyBox..."; sleep 5 + exec /bin/sh --login + + + 04) What if I want a binary in the initrd, but libraries are missing? + + That is a bit tricky. One option is to compile statically, but that + does not work for everything. Debian puts some libraries into lib/ and + lib64/ which are usually enough. If you need more, you can add the + libraries you need there. That may or may not need a configuration + change for the dynamic linker "ld" as well. Refer to standard Linux + documentation on how to add a library to a Linux system. A running + initrd is just a running Linux system after all, it is not special in + any way. + + 05) How do I repack the initrd? + + Simply repack the changed directory. While in tmp/, do + the following: + ``` + find . | cpio --create --format='newc' | gzip > ../new_initrd + ``` + Rename "new_initrd" to however you want it called (the name of + the initrd is a kernel-parameter) and move to /boot. That is it. + + +10. LUKS2 Questions + + + * 10.1 Is the cryptography of LUKS2 different? + + Mostly not. The header has changed in its structure, but the + crytpgraphy is the same. The one exception is that PBKDF2 has been + replaced by Argon2 to give better resilience against attacks attacks by + graphics cards and other hardware with lots of computing power but + limited local memory per computing element. + + + * 10.2 What new features does LUKS2 have? + + There are quite a few. I recommend reading the man-page and the on-disk + format specification, see Item 1.2. + + To list just some: + - A lot of the metadata is JSON, allowing for easier extension + - Max 32 key-slots per default + - Better protection for bad passphrases now available with Argon2 + - Authenticated encryption + - The LUKS2 header is less vulnerable to corruption and has a 2nd copy + + + * 10.3 Why does LUKS2 need so much memory? + + LUKS2 uses Argon2 instead of PBKDF2. That causes the increase in memory. + See next item. + + + * 10.4 Why use Argon2 in LUKS 2 instead of PBKDF2? + + LUKS tries to be secure with not-so-good passwords. Bad passwords need to + be protected in some way against an attacker that just tries all possible + combinations. (For good passwords, you can just wait for the attacker to + die of old age...) The situation with LUKS is not quite the same as with a + password stored in a database, but there are similarities. + + LUKS does not store passwords on disk. Instead, the passwords are used to + decrypt the master-key with it and that one is stored on disk in encrypted + form. If you have a good password, with, say, more than 80 bits of + entropy, you could just put the password through a single crypto-hash (to + turn it into something that can be used as a key) and that would be secure. + This is what plain dm-crypt does. + + If the password has lower entropy, you want to make this process cost some + effort, so that each try takes time and resources and slows the attacker + down. LUKS1 uses PBKDF2 for that, adding an iteration count and a salt. + The iteration count is per default set to that it takes 1 second per try on + the CPU of the device where the respective passphrase was set. The salt is + there to prevent precomputation. + + The problem with that is that if you use a graphics card, you can massively + speed up these computations as PBKDF2 needs very little memeory to compute + it. A graphics card is (grossly simplified) a mass of small CPUs with some + small very fast local memory per CPU and a large slow memory (the 4/6/8 GB + a current card may have). If you can keep a computation in the small, + CPU-local memory, you can gain a speed factor of 1000 or more when trying + passwords with PBKDF2. + + Argon2 was created to address this problem. It adds a "large memory + property" where computing the result with less memory than the memory + parameter requires is massively (exponentially) slowed down. That means, + if you set, for example, 4GB of memory, computing Argon2 on a graphics card + with around 100kB of memory per "CPU" makes no sense at all because it is + far too slow. An attacker has hence to use real CPUs and furthermore is + limited by main memory bandwith. + + Hence the large amount of memory used is a security feature and should not + be turned off or reduced. If you really (!) understand what you are doing + and can assure good passwords, you can either go back to PBKDF2 or set a + low amount of memory used for Argon2 when creating the header. + + + * 10.5 LUKS2 is insecure! It uses less memory than the Argon2 RFC say! + + Well, not really. The RFC recommends 6GiB of memory for use with disk + encryption. That is a bit insane and something clearly went wrong in the + standardization process here. First, that makes Argon2 unusable on any 32 + bit Linux and that is clearly a bad thing. Second, there are many small + Linux devices around that do not have 6GiB of RAM in the first place. For + example, the current Raspberry Pi has 1GB, 2GB or 4GB of RAM, and with the + RFC recommendations, none of these could compute Argon2 hashes. + + Hence LUKS2 uses a more real-world approach. Iteration is set to a + minimum of 4 because there are some theoretical attacks that work up to an + iteration count of 3. The thread parameter is set to 4. To achieve 2 + second/slot unlock time, LUKS2 adjusts the memory parameter down if + needed. In the other direction, it will respect available memory and not + exceed it. On a current PC, the memory parameter will be somewhere around + 1GB, which should quite generous. The minimum I was able to set in an + experiment with "-i 1" was 400kB of memory and that is too low to be + secure. A Raspberry Pi would probably end up somewhere around 50MB (have + not tried it) and that should still be plenty. + + That said, if you have a good, high-entropy passphrase, LUKS2 is secure + with any memory parameter. + + + * 10.6 How does re-encryption store data while it is running? + + All metadata necessary to perform a recovery of said segment (in case of + crash) is stored in the LUKS2 metadata area. No matter if the LUKS2 + reencryption was run in online or offline mode. + + + * 10.7 What do I do if re-encryption crashes? + + In case of a reencryption application crash, try to close the original + device via following command first: + + cryptsetup close . + + Cryptsetup assesses if it's safe to teardown the reencryption device stack + or not. It will also cut off I/O (via dm-error mapping) to current + hotzone segment (to make later recovery possible). If it can't be torn + down, i.e. due to a mounted fs, you must unmount the filesystem first. + Never try to tear down reencryption dm devices manually using e.g. + dmsetup tool, at least not unless cryptsetup says it's safe to do so. It + could damage the data beyond repair. - * Brute-forcing passphrases + * 10.8 Do I need to enter two passphrases to recover a crashed + re-encryption? - - - http://news.electricalchemy.net/2009/10/password-cracking-in-cloud-part-5.html + Cryptsetup (command line utility) expects the passphrases to be identical + for the keyslot containing old volume key and for the keyslot containing + new one. So the recovery happens during normal the "cryptsetup open" + operation or the equivalent during boot. - - - http://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes + Re-encryption recovery can be also performed in offline mode by + the "cryptsetup repair" command. - * Tools + * 10.9 What is an unbound keyslot and what is it used for? + Quite simply, an 'unbound key' is an independent 'key' stored in a luks2 + keyslot that cannot be used to unlock a LUKS2 data device. More specifically, + an 'unbound key' or 'unbound luks2 keyslot' contains a secret that is not + currently associated with any data/crypt segment (encrypted area) in the + LUKS2 'Segments' section (displayed by luksDump). - * SSD and Flash Disk Related + This is a bit of a more general idea. It basically allows to use a keyslot + as a container for a key to be used in other things than decrypting a + data segment. + As of April 2020, the following uses are defined: - * Disk Encryption + 1) LUKS2 re-encryption. The new volume key is stored in an unbound keyslot + which becomes a regular LUKS2 keyslot later when re-encryption is + finished. + + 2) Somewhat similar is the use with a wrapped key scheme (e.g. with the + paes cipher). In this case, the VK (Volume Key) stored in a keyslot + is an encrypted binary binary blob. The KEK (Key Encryption Key) for + that blob may be refreshed (Note that this KEK is not managed by + cryptsetup!) and the binary blob gets changed. The KEK refresh process + uses an 'unbound keyslot'. First the future effective VK is placed + in the unbound keyslot and later it gets turned into the new real VK + (and bound to the respective crypt segment). + + + * 10.10 What about the size of the LUKS2 header? + + While the LUKS1 header has a fixed size that is determined by the cipher + spec (see Item 6.12), LUKS2 is more variable. The default size is 16MB, + but it can be adjusted on creation by using the --luks2-metadata-size + and --luks2-keyslots-size options. Refer to the man-page for details. + While adjusting the size in an existing LUKS2 container is possible, + it is somewhat complicated and risky. My advice is to do a backup, + recreate the container with changed parameters and restore that backup. + + + * 10.11 Does LUKS2 store metadata anywhere except in the header? + + It does not. But note that if you use the experimental integrity support, + there will be an integrity header as well at the start of the data area + and things get a bit more complicated. All metadata will still be at the + start of the device, nothing gets stored somewhere in the middle or at + the end. + + +11. References and Further Reading + + * Purpose of this Section + + The purpose of this section is to collect references to all materials + that do not fit the FAQ but are relevant in some fashion. This can be + core topics like the LUKS spec or disk encryption, but it can also be + more tangential, like secure storage management or cryptography used in + LUKS. It should still have relevance to cryptsetup and its + applications. + If you want to see something added here, send email to the maintainer + (or the cryptsetup mailing list) giving an URL, a description (1-3 lines + preferred) and a section to put it in. You can also propose new + sections. - * Attacks Against Disk Encryption + At this time I would like to limit the references to things that are + available on the web. + * Specifications - * Risk Management as Relevant for Disk Encryption + - LUKS on-disk format spec: See Item 1.2 + + * Other Documentation + + - Arch Linux on LUKS, LVM and full-disk encryption: + https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system + + * Code Examples + + - Some code examples are in the source package under docs/examples + - LUKS AF Splitter in Ruby by John Lane: https://rubygems.org/gems/afsplitter - * Cryptography + * Brute-forcing passphrases + - http://news.electricalchemy.net/2009/10/password-cracking-in-cloud-part-5.html - * Secure Storage + - http://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes - A. Contributors In no particular order: + * Tools + + * SSD and Flash Disk Related + + * Disk Encryption + + * Attacks Against Disk Encryption + + * Risk Management as Relevant for Disk Encryption + + * Cryptography + + * Secure Storage + + +A. Contributors +In no particular order: - Arno Wagner - Milan Broz +___ diff --git a/INSTALL b/INSTALL index a4b3414..45ff9bb 100644 --- a/INSTALL +++ b/INSTALL @@ -44,7 +44,7 @@ The simplest way to compile this package is: `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. - Running `configure' takes awhile. While running, it prints some + Running `configure' takes a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. diff --git a/Makefile.am b/Makefile.am index d6a4c43..de0d2a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,13 +1,50 @@ EXTRA_DIST = COPYING.LGPL FAQ docs misc -SUBDIRS = \ - lib \ - src \ - man \ - python \ - tests \ - po +SUBDIRS = po tests +CLEANFILES = +DISTCLEAN_TARGETS = + +AM_CPPFLAGS = \ + -include config.h \ + -I$(top_srcdir)/lib \ + -DDATADIR=\""$(datadir)"\" \ + -DLOCALEDIR=\""$(datadir)/locale"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DPREFIX=\""$(prefix)"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DVERSION=\""$(VERSION)"\" +AM_CFLAGS = -Wall +AM_LDFLAGS = + +LDADD = $(LTLIBINTL) -lm + +tmpfilesddir = @DEFAULT_TMPFILESDIR@ + +noinst_LTLIBRARIES = +sbin_PROGRAMS = +man8_MANS = +tmpfilesd_DATA = + +include man/Makemodule.am + +include scripts/Makemodule.am + +if CRYPTO_INTERNAL_ARGON2 +include lib/crypto_backend/argon2/Makemodule.am +endif +include lib/crypto_backend/Makemodule.am +include lib/Makemodule.am + +include src/Makemodule.am ACLOCAL_AMFLAGS = -I m4 +DISTCHECK_CONFIGURE_FLAGS = \ + --with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \ + --enable-internal-argon2 --enable-internal-sse-argon2 + +distclean-local: + -find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f + rm -rf autom4te.cache + clean-local: - -rm -rf docs/doxygen_api_docs + -rm -rf docs/doxygen_api_docs libargon2.la diff --git a/Makefile.in b/Makefile.in index 64d2b0c..ab032a7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -13,8 +13,22 @@ # PARTICULAR PURPOSE. @SET_MAKE@ + + + + VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -77,30 +91,371 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +sbin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) $(am__EXEEXT_8) +@VERITYSETUP_TRUE@am__append_1 = man/veritysetup.8 +@REENCRYPT_TRUE@am__append_2 = man/cryptsetup-reencrypt.8 +@INTEGRITYSETUP_TRUE@am__append_3 = man/integritysetup.8 +@CRYPTSETUP_TMPFILE_TRUE@am__append_4 = scripts/cryptsetup.conf +@CRYPTO_INTERNAL_ARGON2_TRUE@am__append_5 = libargon2.la +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_TRUE@am__append_6 = lib/crypto_backend/argon2/blake2/blamka-round-opt.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_TRUE@ lib/crypto_backend/argon2/opt.c + +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_FALSE@am__append_7 = lib/crypto_backend/argon2/blake2/blamka-round-ref.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_FALSE@ lib/crypto_backend/argon2/ref.c + +@CRYPTO_INTERNAL_ARGON2_TRUE@am__append_8 = lib/crypto_backend/argon2/LICENSE \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/README +@CRYPTO_BACKEND_GCRYPT_TRUE@am__append_9 = lib/crypto_backend/crypto_gcrypt.c +@CRYPTO_BACKEND_OPENSSL_TRUE@am__append_10 = lib/crypto_backend/crypto_openssl.c +@CRYPTO_BACKEND_NSS_TRUE@am__append_11 = lib/crypto_backend/crypto_nss.c +@CRYPTO_BACKEND_KERNEL_TRUE@am__append_12 = lib/crypto_backend/crypto_kernel.c +@CRYPTO_BACKEND_NETTLE_TRUE@am__append_13 = lib/crypto_backend/crypto_nettle.c +@CRYPTO_INTERNAL_PBKDF2_TRUE@am__append_14 = lib/crypto_backend/pbkdf2_generic.c +@CRYPTSETUP_TRUE@am__append_15 = cryptsetup +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@am__append_16 = cryptsetup.static +@VERITYSETUP_TRUE@am__append_17 = veritysetup +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@am__append_18 = veritysetup.static +@INTEGRITYSETUP_TRUE@am__append_19 = integritysetup +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@am__append_20 = integritysetup.static +@REENCRYPT_TRUE@am__append_21 = cryptsetup-reencrypt +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@am__append_22 = cryptsetup-reencrypt.static subdir = . -DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ - $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/config.h.in ABOUT-NLS COPYING TODO compile \ - config.guess config.rpath config.sub depcomp install-sh \ - missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(include_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = lib/libcryptsetup.pc scripts/cryptsetup.conf CONFIG_CLEAN_VPATH_FILES = +@CRYPTSETUP_TRUE@am__EXEEXT_1 = cryptsetup$(EXEEXT) +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@am__EXEEXT_2 = cryptsetup.static$(EXEEXT) +@VERITYSETUP_TRUE@am__EXEEXT_3 = veritysetup$(EXEEXT) +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@am__EXEEXT_4 = veritysetup.static$(EXEEXT) +@INTEGRITYSETUP_TRUE@am__EXEEXT_5 = integritysetup$(EXEEXT) +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@am__EXEEXT_6 = integritysetup.static$(EXEEXT) +@REENCRYPT_TRUE@am__EXEEXT_7 = cryptsetup-reencrypt$(EXEEXT) +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@am__EXEEXT_8 = cryptsetup-reencrypt.static$(EXEEXT) +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(tmpfilesddir)" "$(DESTDIR)$(includedir)" +PROGRAMS = $(sbin_PROGRAMS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +libargon2_la_LIBADD = +am__libargon2_la_SOURCES_DIST = \ + lib/crypto_backend/argon2/blake2/blake2b.c \ + lib/crypto_backend/argon2/blake2/blake2.h \ + lib/crypto_backend/argon2/blake2/blake2-impl.h \ + lib/crypto_backend/argon2/argon2.c \ + lib/crypto_backend/argon2/argon2.h \ + lib/crypto_backend/argon2/core.c \ + lib/crypto_backend/argon2/core.h \ + lib/crypto_backend/argon2/encoding.c \ + lib/crypto_backend/argon2/encoding.h \ + lib/crypto_backend/argon2/thread.c \ + lib/crypto_backend/argon2/thread.h \ + lib/crypto_backend/argon2/blake2/blamka-round-opt.h \ + lib/crypto_backend/argon2/opt.c \ + lib/crypto_backend/argon2/blake2/blamka-round-ref.h \ + lib/crypto_backend/argon2/ref.c +am__dirstamp = $(am__leading_dot)dirstamp +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_TRUE@am__objects_1 = lib/crypto_backend/argon2/libargon2_la-opt.lo +@CRYPTO_INTERNAL_ARGON2_TRUE@@CRYPTO_INTERNAL_SSE_ARGON2_FALSE@am__objects_2 = lib/crypto_backend/argon2/libargon2_la-ref.lo +@CRYPTO_INTERNAL_ARGON2_TRUE@am_libargon2_la_OBJECTS = lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/libargon2_la-argon2.lo \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/libargon2_la-core.lo \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/libargon2_la-encoding.lo \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/libargon2_la-thread.lo \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ $(am__objects_1) $(am__objects_2) +libargon2_la_OBJECTS = $(am_libargon2_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libargon2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libargon2_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +@CRYPTO_INTERNAL_ARGON2_TRUE@am_libargon2_la_rpath = +am__libcrypto_backend_la_SOURCES_DIST = \ + lib/crypto_backend/crypto_backend.h \ + lib/crypto_backend/crypto_backend_internal.h \ + lib/crypto_backend/crypto_cipher_kernel.c \ + lib/crypto_backend/crypto_storage.c \ + lib/crypto_backend/pbkdf_check.c lib/crypto_backend/crc32.c \ + lib/crypto_backend/argon2_generic.c \ + lib/crypto_backend/cipher_generic.c \ + lib/crypto_backend/cipher_check.c \ + lib/crypto_backend/crypto_gcrypt.c \ + lib/crypto_backend/crypto_openssl.c \ + lib/crypto_backend/crypto_nss.c \ + lib/crypto_backend/crypto_kernel.c \ + lib/crypto_backend/crypto_nettle.c \ + lib/crypto_backend/pbkdf2_generic.c +@CRYPTO_BACKEND_GCRYPT_TRUE@am__objects_3 = lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo +@CRYPTO_BACKEND_OPENSSL_TRUE@am__objects_4 = lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo +@CRYPTO_BACKEND_NSS_TRUE@am__objects_5 = lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo +@CRYPTO_BACKEND_KERNEL_TRUE@am__objects_6 = lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo +@CRYPTO_BACKEND_NETTLE_TRUE@am__objects_7 = lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo +@CRYPTO_INTERNAL_PBKDF2_TRUE@am__objects_8 = lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo +am_libcrypto_backend_la_OBJECTS = lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo \ + lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo \ + lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo \ + lib/crypto_backend/libcrypto_backend_la-crc32.lo \ + lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo \ + lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo \ + lib/crypto_backend/libcrypto_backend_la-cipher_check.lo \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) \ + $(am__objects_6) $(am__objects_7) $(am__objects_8) +libcrypto_backend_la_OBJECTS = $(am_libcrypto_backend_la_OBJECTS) +libcrypto_backend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcrypto_backend_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__DEPENDENCIES_1 = +am_libcryptsetup_la_OBJECTS = lib/libcryptsetup_la-setup.lo \ + lib/libcryptsetup_la-utils.lo \ + lib/libcryptsetup_la-utils_benchmark.lo \ + lib/libcryptsetup_la-utils_crypt.lo \ + lib/libcryptsetup_la-utils_loop.lo \ + lib/libcryptsetup_la-utils_devpath.lo \ + lib/libcryptsetup_la-utils_wipe.lo \ + lib/libcryptsetup_la-utils_fips.lo \ + lib/libcryptsetup_la-utils_device.lo \ + lib/libcryptsetup_la-utils_keyring.lo \ + lib/libcryptsetup_la-utils_device_locking.lo \ + lib/libcryptsetup_la-utils_pbkdf.lo \ + lib/libcryptsetup_la-utils_safe_memory.lo \ + lib/libcryptsetup_la-utils_storage_wrappers.lo \ + lib/libcryptsetup_la-libdevmapper.lo \ + lib/libcryptsetup_la-volumekey.lo \ + lib/libcryptsetup_la-random.lo \ + lib/libcryptsetup_la-crypt_plain.lo \ + lib/libcryptsetup_la-base64.lo \ + lib/integrity/libcryptsetup_la-integrity.lo \ + lib/loopaes/libcryptsetup_la-loopaes.lo \ + lib/tcrypt/libcryptsetup_la-tcrypt.lo \ + lib/luks1/libcryptsetup_la-af.lo \ + lib/luks1/libcryptsetup_la-keyencryption.lo \ + lib/luks1/libcryptsetup_la-keymanage.lo \ + lib/verity/libcryptsetup_la-verity_hash.lo \ + lib/verity/libcryptsetup_la-verity_fec.lo \ + lib/verity/libcryptsetup_la-verity.lo \ + lib/verity/libcryptsetup_la-rs_encode_char.lo \ + lib/verity/libcryptsetup_la-rs_decode_char.lo \ + lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo \ + lib/luks2/libcryptsetup_la-luks2_json_format.lo \ + lib/luks2/libcryptsetup_la-luks2_json_metadata.lo \ + lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo \ + lib/luks2/libcryptsetup_la-luks2_digest.lo \ + lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo \ + lib/luks2/libcryptsetup_la-luks2_keyslot.lo \ + lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo \ + lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo \ + lib/luks2/libcryptsetup_la-luks2_reencrypt.lo \ + lib/luks2/libcryptsetup_la-luks2_segment.lo \ + lib/luks2/libcryptsetup_la-luks2_token_keyring.lo \ + lib/luks2/libcryptsetup_la-luks2_token.lo \ + lib/libcryptsetup_la-utils_blkid.lo \ + lib/bitlk/libcryptsetup_la-bitlk.lo +libcryptsetup_la_OBJECTS = $(am_libcryptsetup_la_OBJECTS) +libcryptsetup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcryptsetup_la_CFLAGS) $(CFLAGS) \ + $(libcryptsetup_la_LDFLAGS) $(LDFLAGS) -o $@ +libutils_io_la_LIBADD = +am_libutils_io_la_OBJECTS = lib/libutils_io_la-utils_io.lo +libutils_io_la_OBJECTS = $(am_libutils_io_la_OBJECTS) +libutils_io_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libutils_io_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +am__cryptsetup_SOURCES_DIST = lib/utils_crypt.c lib/utils_loop.c \ + lib/utils_io.c lib/utils_blkid.c src/utils_tools.c \ + src/utils_password.c src/utils_luks2.c src/utils_blockdev.c \ + src/cryptsetup.c src/cryptsetup.h +@CRYPTSETUP_TRUE@am_cryptsetup_OBJECTS = lib/utils_crypt.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_password.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_luks2.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_blockdev.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/cryptsetup.$(OBJEXT) +cryptsetup_OBJECTS = $(am_cryptsetup_OBJECTS) +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +@CRYPTSETUP_TRUE@cryptsetup_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@CRYPTSETUP_TRUE@ libcryptsetup.la +am__cryptsetup_reencrypt_SOURCES_DIST = lib/utils_crypt.c \ + lib/utils_io.c lib/utils_blkid.c src/utils_tools.c \ + lib/utils_loop.c src/utils_password.c \ + src/cryptsetup_reencrypt.c src/cryptsetup.h +@REENCRYPT_TRUE@am_cryptsetup_reencrypt_OBJECTS = \ +@REENCRYPT_TRUE@ lib/utils_crypt.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_io.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/utils_tools.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_loop.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/utils_password.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/cryptsetup_reencrypt.$(OBJEXT) +cryptsetup_reencrypt_OBJECTS = $(am_cryptsetup_reencrypt_OBJECTS) +@REENCRYPT_TRUE@cryptsetup_reencrypt_DEPENDENCIES = \ +@REENCRYPT_TRUE@ $(am__DEPENDENCIES_2) libcryptsetup.la +am__cryptsetup_reencrypt_static_SOURCES_DIST = lib/utils_crypt.c \ + lib/utils_io.c lib/utils_blkid.c src/utils_tools.c \ + lib/utils_loop.c src/utils_password.c \ + src/cryptsetup_reencrypt.c src/cryptsetup.h +@REENCRYPT_TRUE@am__objects_9 = lib/utils_crypt.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_io.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/utils_tools.$(OBJEXT) \ +@REENCRYPT_TRUE@ lib/utils_loop.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/utils_password.$(OBJEXT) \ +@REENCRYPT_TRUE@ src/cryptsetup_reencrypt.$(OBJEXT) +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@am_cryptsetup_reencrypt_static_OBJECTS = \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ $(am__objects_9) +cryptsetup_reencrypt_static_OBJECTS = \ + $(am_cryptsetup_reencrypt_static_OBJECTS) +@REENCRYPT_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) \ +@REENCRYPT_TRUE@ libcryptsetup.la +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_reencrypt_static_DEPENDENCIES = \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ $(am__DEPENDENCIES_3) +cryptsetup_reencrypt_static_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cryptsetup_reencrypt_static_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__cryptsetup_static_SOURCES_DIST = lib/utils_crypt.c \ + lib/utils_loop.c lib/utils_io.c lib/utils_blkid.c \ + src/utils_tools.c src/utils_password.c src/utils_luks2.c \ + src/utils_blockdev.c src/cryptsetup.c src/cryptsetup.h +@CRYPTSETUP_TRUE@am__objects_10 = lib/utils_crypt.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_password.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_luks2.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/utils_blockdev.$(OBJEXT) \ +@CRYPTSETUP_TRUE@ src/cryptsetup.$(OBJEXT) +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@am_cryptsetup_static_OBJECTS = \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(am__objects_10) +cryptsetup_static_OBJECTS = $(am_cryptsetup_static_OBJECTS) +@CRYPTSETUP_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \ +@CRYPTSETUP_TRUE@ libcryptsetup.la +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_static_DEPENDENCIES = \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(am__DEPENDENCIES_4) +cryptsetup_static_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(cryptsetup_static_LDFLAGS) $(LDFLAGS) \ + -o $@ +am__integritysetup_SOURCES_DIST = lib/utils_crypt.c lib/utils_loop.c \ + lib/utils_io.c lib/utils_blkid.c src/utils_tools.c \ + src/integritysetup.c src/cryptsetup.h +@INTEGRITYSETUP_TRUE@am_integritysetup_OBJECTS = \ +@INTEGRITYSETUP_TRUE@ lib/utils_crypt.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ src/integritysetup.$(OBJEXT) +integritysetup_OBJECTS = $(am_integritysetup_OBJECTS) +@INTEGRITYSETUP_TRUE@integritysetup_DEPENDENCIES = \ +@INTEGRITYSETUP_TRUE@ $(am__DEPENDENCIES_2) libcryptsetup.la +am__integritysetup_static_SOURCES_DIST = lib/utils_crypt.c \ + lib/utils_loop.c lib/utils_io.c lib/utils_blkid.c \ + src/utils_tools.c src/integritysetup.c src/cryptsetup.h +@INTEGRITYSETUP_TRUE@am__objects_11 = lib/utils_crypt.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@INTEGRITYSETUP_TRUE@ src/integritysetup.$(OBJEXT) +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@am_integritysetup_static_OBJECTS = \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(am__objects_11) +integritysetup_static_OBJECTS = $(am_integritysetup_static_OBJECTS) +@INTEGRITYSETUP_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_2) \ +@INTEGRITYSETUP_TRUE@ libcryptsetup.la +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_DEPENDENCIES = \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(am__DEPENDENCIES_5) +integritysetup_static_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(integritysetup_static_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__veritysetup_SOURCES_DIST = lib/utils_crypt.c lib/utils_loop.c \ + lib/utils_io.c lib/utils_blkid.c src/utils_tools.c \ + src/utils_password.c src/veritysetup.c src/cryptsetup.h +@VERITYSETUP_TRUE@am_veritysetup_OBJECTS = lib/utils_crypt.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/utils_password.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/veritysetup.$(OBJEXT) +veritysetup_OBJECTS = $(am_veritysetup_OBJECTS) +@VERITYSETUP_TRUE@veritysetup_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@VERITYSETUP_TRUE@ libcryptsetup.la +am__veritysetup_static_SOURCES_DIST = lib/utils_crypt.c \ + lib/utils_loop.c lib/utils_io.c lib/utils_blkid.c \ + src/utils_tools.c src/utils_password.c src/veritysetup.c \ + src/cryptsetup.h +@VERITYSETUP_TRUE@am__objects_12 = lib/utils_crypt.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_loop.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_io.$(OBJEXT) \ +@VERITYSETUP_TRUE@ lib/utils_blkid.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/utils_tools.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/utils_password.$(OBJEXT) \ +@VERITYSETUP_TRUE@ src/veritysetup.$(OBJEXT) +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@am_veritysetup_static_OBJECTS = \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ $(am__objects_12) +veritysetup_static_OBJECTS = $(am_veritysetup_static_OBJECTS) +@VERITYSETUP_TRUE@am__DEPENDENCIES_6 = $(am__DEPENDENCIES_2) \ +@VERITYSETUP_TRUE@ libcryptsetup.la +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@veritysetup_static_DEPENDENCIES = \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ $(am__DEPENDENCIES_6) +veritysetup_static_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(veritysetup_static_LDFLAGS) \ + $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -113,8 +468,120 @@ AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = -SOURCES = -DIST_SOURCES = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = lib/$(DEPDIR)/libcryptsetup_la-base64.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-random.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-setup.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_device.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo \ + lib/$(DEPDIR)/libcryptsetup_la-volumekey.Plo \ + lib/$(DEPDIR)/libutils_io_la-utils_io.Plo \ + lib/$(DEPDIR)/utils_blkid.Po lib/$(DEPDIR)/utils_crypt.Po \ + lib/$(DEPDIR)/utils_io.Po lib/$(DEPDIR)/utils_loop.Po \ + lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo \ + lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Plo \ + lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Plo \ + lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Plo \ + lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Plo \ + lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Plo \ + lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Plo \ + lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Plo \ + lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo \ + lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo \ + lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Plo \ + lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Plo \ + lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Plo \ + lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Plo \ + lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Plo \ + lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Plo \ + src/$(DEPDIR)/cryptsetup.Po \ + src/$(DEPDIR)/cryptsetup_reencrypt.Po \ + src/$(DEPDIR)/integritysetup.Po \ + src/$(DEPDIR)/utils_blockdev.Po src/$(DEPDIR)/utils_luks2.Po \ + src/$(DEPDIR)/utils_password.Po src/$(DEPDIR)/utils_tools.Po \ + src/$(DEPDIR)/veritysetup.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libargon2_la_SOURCES) $(libcrypto_backend_la_SOURCES) \ + $(libcryptsetup_la_SOURCES) $(libutils_io_la_SOURCES) \ + $(cryptsetup_SOURCES) $(cryptsetup_reencrypt_SOURCES) \ + $(cryptsetup_reencrypt_static_SOURCES) \ + $(cryptsetup_static_SOURCES) $(integritysetup_SOURCES) \ + $(integritysetup_static_SOURCES) $(veritysetup_SOURCES) \ + $(veritysetup_static_SOURCES) +DIST_SOURCES = $(am__libargon2_la_SOURCES_DIST) \ + $(am__libcrypto_backend_la_SOURCES_DIST) \ + $(libcryptsetup_la_SOURCES) $(libutils_io_la_SOURCES) \ + $(am__cryptsetup_SOURCES_DIST) \ + $(am__cryptsetup_reencrypt_SOURCES_DIST) \ + $(am__cryptsetup_reencrypt_static_SOURCES_DIST) \ + $(am__cryptsetup_static_SOURCES_DIST) \ + $(am__integritysetup_SOURCES_DIST) \ + $(am__integritysetup_static_SOURCES_DIST) \ + $(am__veritysetup_SOURCES_DIST) \ + $(am__veritysetup_static_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -128,6 +595,11 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man8_MANS) +DATA = $(pkgconfig_DATA) $(tmpfilesd_DATA) +HEADERS = $(include_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ @@ -135,9 +607,9 @@ am__recursive_targets = \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.h.in + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -158,6 +630,17 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/lib/Makemodule.am \ + $(srcdir)/lib/crypto_backend/Makemodule.am \ + $(srcdir)/lib/crypto_backend/argon2/Makemodule.am \ + $(srcdir)/man/Makemodule.am $(srcdir)/scripts/Makemodule.am \ + $(srcdir)/src/Makemodule.am \ + $(top_srcdir)/lib/libcryptsetup.pc.in \ + $(top_srcdir)/scripts/cryptsetup.conf.in ABOUT-NLS AUTHORS \ + COPYING ChangeLog INSTALL NEWS README TODO compile \ + config.guess config.rpath config.sub depcomp install-sh \ + ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -208,6 +691,8 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BLKID_CFLAGS = @BLKID_CFLAGS@ +BLKID_LIBS = @BLKID_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -217,6 +702,9 @@ CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ CRYPTO_LIBS = @CRYPTO_LIBS@ CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ CYGPATH_W = @CYGPATH_W@ +DEFAULT_LUKS2_LOCK_DIR_PERMS = @DEFAULT_LUKS2_LOCK_DIR_PERMS@ +DEFAULT_LUKS2_LOCK_PATH = @DEFAULT_LUKS2_LOCK_PATH@ +DEFAULT_TMPFILESDIR = @DEFAULT_TMPFILESDIR@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ @@ -232,6 +720,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ @@ -242,8 +731,12 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBARGON2_CFLAGS = @LIBARGON2_CFLAGS@ +LIBARGON2_LIBS = @LIBARGON2_LIBS@ LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ @@ -259,6 +752,7 @@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -284,6 +778,7 @@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PASSWDQC_LIBS = @PASSWDQC_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ @@ -293,13 +788,6 @@ POSUB = @POSUB@ PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ PWQUALITY_LIBS = @PWQUALITY_LIBS@ PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -310,6 +798,7 @@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -351,38 +840,304 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemd_tmpfilesdir = @systemd_tmpfilesdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = COPYING.LGPL FAQ docs misc -SUBDIRS = \ - lib \ - src \ - man \ - python \ - tests \ - po +EXTRA_DIST = COPYING.LGPL FAQ docs misc man/cryptsetup.8 \ + man/integritysetup.8 man/veritysetup.8 \ + man/cryptsetup-reencrypt.8 $(am__append_8) \ + lib/libcryptsetup.pc.in lib/libcryptsetup.sym +SUBDIRS = po tests +CLEANFILES = +DISTCLEAN_TARGETS = scripts/cryptsetup.conf +AM_CPPFLAGS = \ + -include config.h \ + -I$(top_srcdir)/lib \ + -DDATADIR=\""$(datadir)"\" \ + -DLOCALEDIR=\""$(datadir)/locale"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DPREFIX=\""$(prefix)"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DVERSION=\""$(VERSION)"\" + +AM_CFLAGS = -Wall +AM_LDFLAGS = +LDADD = $(LTLIBINTL) -lm +tmpfilesddir = @DEFAULT_TMPFILESDIR@ +noinst_LTLIBRARIES = $(am__append_5) libcrypto_backend.la \ + libutils_io.la +man8_MANS = man/cryptsetup.8 $(am__append_1) $(am__append_2) \ + $(am__append_3) +tmpfilesd_DATA = $(am__append_4) +@CRYPTO_INTERNAL_ARGON2_TRUE@libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3 +@CRYPTO_INTERNAL_ARGON2_TRUE@libargon2_la_CPPFLAGS = $(AM_CPPFLAGS) \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ -I lib/crypto_backend/argon2 \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ -I lib/crypto_backend/argon2/blake2 + +@CRYPTO_INTERNAL_ARGON2_TRUE@libargon2_la_SOURCES = lib/crypto_backend/argon2/blake2/blake2b.c \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/blake2/blake2.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/blake2/blake2-impl.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/argon2.c \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/argon2.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/core.c \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/core.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/encoding.c \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/encoding.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/thread.c \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ lib/crypto_backend/argon2/thread.h \ +@CRYPTO_INTERNAL_ARGON2_TRUE@ $(am__append_6) $(am__append_7) +libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@ +libcrypto_backend_la_SOURCES = lib/crypto_backend/crypto_backend.h \ + lib/crypto_backend/crypto_backend_internal.h \ + lib/crypto_backend/crypto_cipher_kernel.c \ + lib/crypto_backend/crypto_storage.c \ + lib/crypto_backend/pbkdf_check.c lib/crypto_backend/crc32.c \ + lib/crypto_backend/argon2_generic.c \ + lib/crypto_backend/cipher_generic.c \ + lib/crypto_backend/cipher_check.c $(am__append_9) \ + $(am__append_10) $(am__append_11) $(am__append_12) \ + $(am__append_13) $(am__append_14) +@CRYPTO_INTERNAL_ARGON2_TRUE@libcrypto_backend_la_DEPENDENCIES = libargon2.la +@CRYPTO_INTERNAL_ARGON2_TRUE@libcrypto_backend_la_LIBADD = libargon2.la +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lib/libcryptsetup.pc +lib_LTLIBRARIES = libcryptsetup.la +include_HEADERS = lib/libcryptsetup.h +libutils_io_la_CFLAGS = $(AM_CFLAGS) +libutils_io_la_SOURCES = \ + lib/utils_io.c \ + lib/utils_io.h + +libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) \ + -I $(top_srcdir)/lib/crypto_backend \ + -I $(top_srcdir)/lib/luks1 \ + -I $(top_srcdir)/lib/luks2 \ + -I $(top_srcdir)/lib/loopaes \ + -I $(top_srcdir)/lib/verity \ + -I $(top_srcdir)/lib/tcrypt \ + -I $(top_srcdir)/lib/integrity \ + -I $(top_srcdir)/lib/bitlk + +libcryptsetup_la_DEPENDENCIES = libutils_io.la libcrypto_backend.la lib/libcryptsetup.sym +libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ + -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \ + -version-info @LIBCRYPTSETUP_VERSION_INFO@ + +libcryptsetup_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@ +libcryptsetup_la_LIBADD = \ + @UUID_LIBS@ \ + @DEVMAPPER_LIBS@ \ + @CRYPTO_LIBS@ \ + @LIBARGON2_LIBS@ \ + @JSON_C_LIBS@ \ + @BLKID_LIBS@ \ + $(LTLIBICONV) \ + libcrypto_backend.la \ + libutils_io.la + +libcryptsetup_la_SOURCES = \ + lib/setup.c \ + lib/internal.h \ + lib/bitops.h \ + lib/nls.h \ + lib/libcryptsetup.h \ + lib/utils.c \ + lib/utils_benchmark.c \ + lib/utils_crypt.c \ + lib/utils_crypt.h \ + lib/utils_loop.c \ + lib/utils_loop.h \ + lib/utils_devpath.c \ + lib/utils_wipe.c \ + lib/utils_fips.c \ + lib/utils_fips.h \ + lib/utils_device.c \ + lib/utils_keyring.c \ + lib/utils_keyring.h \ + lib/utils_device_locking.c \ + lib/utils_device_locking.h \ + lib/utils_pbkdf.c \ + lib/utils_safe_memory.c \ + lib/utils_storage_wrappers.c \ + lib/utils_storage_wrappers.h \ + lib/libdevmapper.c \ + lib/utils_dm.h \ + lib/volumekey.c \ + lib/random.c \ + lib/crypt_plain.c \ + lib/base64.h \ + lib/base64.c \ + lib/integrity/integrity.h \ + lib/integrity/integrity.c \ + lib/loopaes/loopaes.h \ + lib/loopaes/loopaes.c \ + lib/tcrypt/tcrypt.h \ + lib/tcrypt/tcrypt.c \ + lib/luks1/af.h \ + lib/luks1/af.c \ + lib/luks1/keyencryption.c \ + lib/luks1/keymanage.c \ + lib/luks1/luks.h \ + lib/verity/verity_hash.c \ + lib/verity/verity_fec.c \ + lib/verity/verity.c \ + lib/verity/verity.h \ + lib/verity/rs_encode_char.c \ + lib/verity/rs_decode_char.c \ + lib/verity/rs.h \ + lib/luks2/luks2_disk_metadata.c \ + lib/luks2/luks2_json_format.c \ + lib/luks2/luks2_json_metadata.c \ + lib/luks2/luks2_luks1_convert.c \ + lib/luks2/luks2_digest.c \ + lib/luks2/luks2_digest_pbkdf2.c \ + lib/luks2/luks2_keyslot.c \ + lib/luks2/luks2_keyslot_luks2.c \ + lib/luks2/luks2_keyslot_reenc.c \ + lib/luks2/luks2_reencrypt.c \ + lib/luks2/luks2_segment.c \ + lib/luks2/luks2_token_keyring.c \ + lib/luks2/luks2_token.c \ + lib/luks2/luks2_internal.h \ + lib/luks2/luks2.h \ + lib/utils_blkid.c \ + lib/utils_blkid.h \ + lib/bitlk/bitlk.h \ + lib/bitlk/bitlk.c + + +# cryptsetup +@CRYPTSETUP_TRUE@cryptsetup_SOURCES = \ +@CRYPTSETUP_TRUE@ lib/utils_crypt.c \ +@CRYPTSETUP_TRUE@ lib/utils_loop.c \ +@CRYPTSETUP_TRUE@ lib/utils_io.c \ +@CRYPTSETUP_TRUE@ lib/utils_blkid.c \ +@CRYPTSETUP_TRUE@ src/utils_tools.c \ +@CRYPTSETUP_TRUE@ src/utils_password.c \ +@CRYPTSETUP_TRUE@ src/utils_luks2.c \ +@CRYPTSETUP_TRUE@ src/utils_blockdev.c \ +@CRYPTSETUP_TRUE@ src/cryptsetup.c \ +@CRYPTSETUP_TRUE@ src/cryptsetup.h + +@CRYPTSETUP_TRUE@cryptsetup_LDADD = $(LDADD) \ +@CRYPTSETUP_TRUE@ libcryptsetup.la \ +@CRYPTSETUP_TRUE@ @POPT_LIBS@ \ +@CRYPTSETUP_TRUE@ @PWQUALITY_LIBS@ \ +@CRYPTSETUP_TRUE@ @PASSWDQC_LIBS@ \ +@CRYPTSETUP_TRUE@ @UUID_LIBS@ \ +@CRYPTSETUP_TRUE@ @BLKID_LIBS@ + +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_static_SOURCES = $(cryptsetup_SOURCES) +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_static_LDADD = \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(cryptsetup_LDADD) \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ @CRYPTO_STATIC_LIBS@ \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ @PWQUALITY_STATIC_LIBS@ \ +@CRYPTSETUP_TRUE@@STATIC_TOOLS_TRUE@ @DEVMAPPER_STATIC_LIBS@ + + +# veritysetup +@VERITYSETUP_TRUE@veritysetup_SOURCES = \ +@VERITYSETUP_TRUE@ lib/utils_crypt.c \ +@VERITYSETUP_TRUE@ lib/utils_loop.c \ +@VERITYSETUP_TRUE@ lib/utils_io.c \ +@VERITYSETUP_TRUE@ lib/utils_blkid.c \ +@VERITYSETUP_TRUE@ src/utils_tools.c \ +@VERITYSETUP_TRUE@ src/utils_password.c \ +@VERITYSETUP_TRUE@ src/veritysetup.c \ +@VERITYSETUP_TRUE@ src/cryptsetup.h + +@VERITYSETUP_TRUE@veritysetup_LDADD = $(LDADD) \ +@VERITYSETUP_TRUE@ libcryptsetup.la \ +@VERITYSETUP_TRUE@ @POPT_LIBS@ \ +@VERITYSETUP_TRUE@ @PWQUALITY_LIBS@ \ +@VERITYSETUP_TRUE@ @PASSWDQC_LIBS@ \ +@VERITYSETUP_TRUE@ @BLKID_LIBS@ + +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@veritysetup_static_SOURCES = $(veritysetup_SOURCES) +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@veritysetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@veritysetup_static_LDADD = \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ $(veritysetup_LDADD) \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ @CRYPTO_STATIC_LIBS@ \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ @DEVMAPPER_STATIC_LIBS@ \ +@STATIC_TOOLS_TRUE@@VERITYSETUP_TRUE@ @UUID_LIBS@ + + +# integritysetup +@INTEGRITYSETUP_TRUE@integritysetup_SOURCES = \ +@INTEGRITYSETUP_TRUE@ lib/utils_crypt.c \ +@INTEGRITYSETUP_TRUE@ lib/utils_loop.c \ +@INTEGRITYSETUP_TRUE@ lib/utils_io.c \ +@INTEGRITYSETUP_TRUE@ lib/utils_blkid.c \ +@INTEGRITYSETUP_TRUE@ src/utils_tools.c \ +@INTEGRITYSETUP_TRUE@ src/integritysetup.c \ +@INTEGRITYSETUP_TRUE@ src/cryptsetup.h + +@INTEGRITYSETUP_TRUE@integritysetup_LDADD = $(LDADD) \ +@INTEGRITYSETUP_TRUE@ libcryptsetup.la \ +@INTEGRITYSETUP_TRUE@ @POPT_LIBS@ \ +@INTEGRITYSETUP_TRUE@ @UUID_LIBS@ \ +@INTEGRITYSETUP_TRUE@ @BLKID_LIBS@ + +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_SOURCES = $(integritysetup_SOURCES) +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@integritysetup_static_LDADD = \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ $(integritysetup_LDADD) \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ @CRYPTO_STATIC_LIBS@ \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ @DEVMAPPER_STATIC_LIBS@ \ +@INTEGRITYSETUP_TRUE@@STATIC_TOOLS_TRUE@ @UUID_LIBS@ + + +# reencrypt +@REENCRYPT_TRUE@cryptsetup_reencrypt_SOURCES = \ +@REENCRYPT_TRUE@ lib/utils_crypt.c \ +@REENCRYPT_TRUE@ lib/utils_io.c \ +@REENCRYPT_TRUE@ lib/utils_blkid.c \ +@REENCRYPT_TRUE@ src/utils_tools.c \ +@REENCRYPT_TRUE@ lib/utils_loop.c \ +@REENCRYPT_TRUE@ src/utils_password.c \ +@REENCRYPT_TRUE@ src/cryptsetup_reencrypt.c \ +@REENCRYPT_TRUE@ src/cryptsetup.h + +@REENCRYPT_TRUE@cryptsetup_reencrypt_LDADD = $(LDADD) \ +@REENCRYPT_TRUE@ libcryptsetup.la \ +@REENCRYPT_TRUE@ @POPT_LIBS@ \ +@REENCRYPT_TRUE@ @PWQUALITY_LIBS@ \ +@REENCRYPT_TRUE@ @PASSWDQC_LIBS@ \ +@REENCRYPT_TRUE@ @UUID_LIBS@ \ +@REENCRYPT_TRUE@ @BLKID_LIBS@ + +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_reencrypt_static_SOURCES = $(cryptsetup_reencrypt_SOURCES) +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_reencrypt_static_LDFLAGS = $(AM_LDFLAGS) -all-static +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@cryptsetup_reencrypt_static_LDADD = \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ $(cryptsetup_reencrypt_LDADD) \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ @CRYPTO_STATIC_LIBS@ \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ @PWQUALITY_STATIC_LIBS@ \ +@REENCRYPT_TRUE@@STATIC_TOOLS_TRUE@ @DEVMAPPER_STATIC_LIBS@ ACLOCAL_AMFLAGS = -I m4 +DISTCHECK_CONFIGURE_FLAGS = \ + --with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \ + --enable-internal-argon2 --enable-internal-sse-argon2 + all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: +.SUFFIXES: .c .lo .o .obj am--refresh: Makefile @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/man/Makemodule.am $(srcdir)/scripts/Makemodule.am $(srcdir)/lib/crypto_backend/argon2/Makemodule.am $(srcdir)/lib/crypto_backend/Makemodule.am $(srcdir)/lib/Makemodule.am $(srcdir)/src/Makemodule.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -395,16 +1150,16 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; +$(srcdir)/man/Makemodule.am $(srcdir)/scripts/Makemodule.am $(srcdir)/lib/crypto_backend/argon2/Makemodule.am $(srcdir)/lib/crypto_backend/Makemodule.am $(srcdir)/lib/Makemodule.am $(srcdir)/src/Makemodule.am $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck @@ -429,15 +1184,1125 @@ $(srcdir)/config.h.in: $(am__configure_deps) distclean-hdr: -rm -f config.h stamp-h1 +lib/libcryptsetup.pc: $(top_builddir)/config.status $(top_srcdir)/lib/libcryptsetup.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +scripts/cryptsetup.conf: $(top_builddir)/config.status $(top_srcdir)/scripts/cryptsetup.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +lib/crypto_backend/argon2/blake2/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend/argon2/blake2 + @: > lib/crypto_backend/argon2/blake2/$(am__dirstamp) +lib/crypto_backend/argon2/blake2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend/argon2/blake2/$(DEPDIR) + @: > lib/crypto_backend/argon2/blake2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo: \ + lib/crypto_backend/argon2/blake2/$(am__dirstamp) \ + lib/crypto_backend/argon2/blake2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend/argon2 + @: > lib/crypto_backend/argon2/$(am__dirstamp) +lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend/argon2/$(DEPDIR) + @: > lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-argon2.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-core.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-encoding.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-thread.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-opt.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/argon2/libargon2_la-ref.lo: \ + lib/crypto_backend/argon2/$(am__dirstamp) \ + lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) + +libargon2.la: $(libargon2_la_OBJECTS) $(libargon2_la_DEPENDENCIES) $(EXTRA_libargon2_la_DEPENDENCIES) + $(AM_V_CCLD)$(libargon2_la_LINK) $(am_libargon2_la_rpath) $(libargon2_la_OBJECTS) $(libargon2_la_LIBADD) $(LIBS) +lib/crypto_backend/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend + @: > lib/crypto_backend/$(am__dirstamp) +lib/crypto_backend/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/crypto_backend/$(DEPDIR) + @: > lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crc32.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-cipher_check.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) +lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo: \ + lib/crypto_backend/$(am__dirstamp) \ + lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) + +libcrypto_backend.la: $(libcrypto_backend_la_OBJECTS) $(libcrypto_backend_la_DEPENDENCIES) $(EXTRA_libcrypto_backend_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcrypto_backend_la_LINK) $(libcrypto_backend_la_OBJECTS) $(libcrypto_backend_la_LIBADD) $(LIBS) +lib/$(am__dirstamp): + @$(MKDIR_P) lib + @: > lib/$(am__dirstamp) +lib/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/$(DEPDIR) + @: > lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-setup.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_benchmark.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_crypt.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_loop.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_devpath.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_wipe.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_fips.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_device.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_keyring.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_device_locking.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_pbkdf.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_safe_memory.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_storage_wrappers.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-libdevmapper.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-volumekey.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-random.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-crypt_plain.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-base64.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/integrity/$(am__dirstamp): + @$(MKDIR_P) lib/integrity + @: > lib/integrity/$(am__dirstamp) +lib/integrity/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/integrity/$(DEPDIR) + @: > lib/integrity/$(DEPDIR)/$(am__dirstamp) +lib/integrity/libcryptsetup_la-integrity.lo: \ + lib/integrity/$(am__dirstamp) \ + lib/integrity/$(DEPDIR)/$(am__dirstamp) +lib/loopaes/$(am__dirstamp): + @$(MKDIR_P) lib/loopaes + @: > lib/loopaes/$(am__dirstamp) +lib/loopaes/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/loopaes/$(DEPDIR) + @: > lib/loopaes/$(DEPDIR)/$(am__dirstamp) +lib/loopaes/libcryptsetup_la-loopaes.lo: lib/loopaes/$(am__dirstamp) \ + lib/loopaes/$(DEPDIR)/$(am__dirstamp) +lib/tcrypt/$(am__dirstamp): + @$(MKDIR_P) lib/tcrypt + @: > lib/tcrypt/$(am__dirstamp) +lib/tcrypt/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/tcrypt/$(DEPDIR) + @: > lib/tcrypt/$(DEPDIR)/$(am__dirstamp) +lib/tcrypt/libcryptsetup_la-tcrypt.lo: lib/tcrypt/$(am__dirstamp) \ + lib/tcrypt/$(DEPDIR)/$(am__dirstamp) +lib/luks1/$(am__dirstamp): + @$(MKDIR_P) lib/luks1 + @: > lib/luks1/$(am__dirstamp) +lib/luks1/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/luks1/$(DEPDIR) + @: > lib/luks1/$(DEPDIR)/$(am__dirstamp) +lib/luks1/libcryptsetup_la-af.lo: lib/luks1/$(am__dirstamp) \ + lib/luks1/$(DEPDIR)/$(am__dirstamp) +lib/luks1/libcryptsetup_la-keyencryption.lo: \ + lib/luks1/$(am__dirstamp) lib/luks1/$(DEPDIR)/$(am__dirstamp) +lib/luks1/libcryptsetup_la-keymanage.lo: lib/luks1/$(am__dirstamp) \ + lib/luks1/$(DEPDIR)/$(am__dirstamp) +lib/verity/$(am__dirstamp): + @$(MKDIR_P) lib/verity + @: > lib/verity/$(am__dirstamp) +lib/verity/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/verity/$(DEPDIR) + @: > lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/verity/libcryptsetup_la-verity_hash.lo: \ + lib/verity/$(am__dirstamp) \ + lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/verity/libcryptsetup_la-verity_fec.lo: lib/verity/$(am__dirstamp) \ + lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/verity/libcryptsetup_la-verity.lo: lib/verity/$(am__dirstamp) \ + lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/verity/libcryptsetup_la-rs_encode_char.lo: \ + lib/verity/$(am__dirstamp) \ + lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/verity/libcryptsetup_la-rs_decode_char.lo: \ + lib/verity/$(am__dirstamp) \ + lib/verity/$(DEPDIR)/$(am__dirstamp) +lib/luks2/$(am__dirstamp): + @$(MKDIR_P) lib/luks2 + @: > lib/luks2/$(am__dirstamp) +lib/luks2/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/luks2/$(DEPDIR) + @: > lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_json_format.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_json_metadata.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_digest.lo: lib/luks2/$(am__dirstamp) \ + lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_keyslot.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_reencrypt.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_segment.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_token_keyring.lo: \ + lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/luks2/libcryptsetup_la-luks2_token.lo: lib/luks2/$(am__dirstamp) \ + lib/luks2/$(DEPDIR)/$(am__dirstamp) +lib/libcryptsetup_la-utils_blkid.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/bitlk/$(am__dirstamp): + @$(MKDIR_P) lib/bitlk + @: > lib/bitlk/$(am__dirstamp) +lib/bitlk/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) lib/bitlk/$(DEPDIR) + @: > lib/bitlk/$(DEPDIR)/$(am__dirstamp) +lib/bitlk/libcryptsetup_la-bitlk.lo: lib/bitlk/$(am__dirstamp) \ + lib/bitlk/$(DEPDIR)/$(am__dirstamp) + +libcryptsetup.la: $(libcryptsetup_la_OBJECTS) $(libcryptsetup_la_DEPENDENCIES) $(EXTRA_libcryptsetup_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcryptsetup_la_LINK) -rpath $(libdir) $(libcryptsetup_la_OBJECTS) $(libcryptsetup_la_LIBADD) $(LIBS) +lib/libutils_io_la-utils_io.lo: lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) + +libutils_io.la: $(libutils_io_la_OBJECTS) $(libutils_io_la_DEPENDENCIES) $(EXTRA_libutils_io_la_DEPENDENCIES) + $(AM_V_CCLD)$(libutils_io_la_LINK) $(libutils_io_la_OBJECTS) $(libutils_io_la_LIBADD) $(LIBS) +lib/utils_crypt.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/utils_loop.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/utils_io.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +lib/utils_blkid.$(OBJEXT): lib/$(am__dirstamp) \ + lib/$(DEPDIR)/$(am__dirstamp) +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/utils_tools.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/utils_password.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/utils_luks2.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/utils_blockdev.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/cryptsetup.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +cryptsetup$(EXEEXT): $(cryptsetup_OBJECTS) $(cryptsetup_DEPENDENCIES) $(EXTRA_cryptsetup_DEPENDENCIES) + @rm -f cryptsetup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cryptsetup_OBJECTS) $(cryptsetup_LDADD) $(LIBS) +src/cryptsetup_reencrypt.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +cryptsetup-reencrypt$(EXEEXT): $(cryptsetup_reencrypt_OBJECTS) $(cryptsetup_reencrypt_DEPENDENCIES) $(EXTRA_cryptsetup_reencrypt_DEPENDENCIES) + @rm -f cryptsetup-reencrypt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cryptsetup_reencrypt_OBJECTS) $(cryptsetup_reencrypt_LDADD) $(LIBS) + +cryptsetup-reencrypt.static$(EXEEXT): $(cryptsetup_reencrypt_static_OBJECTS) $(cryptsetup_reencrypt_static_DEPENDENCIES) $(EXTRA_cryptsetup_reencrypt_static_DEPENDENCIES) + @rm -f cryptsetup-reencrypt.static$(EXEEXT) + $(AM_V_CCLD)$(cryptsetup_reencrypt_static_LINK) $(cryptsetup_reencrypt_static_OBJECTS) $(cryptsetup_reencrypt_static_LDADD) $(LIBS) + +cryptsetup.static$(EXEEXT): $(cryptsetup_static_OBJECTS) $(cryptsetup_static_DEPENDENCIES) $(EXTRA_cryptsetup_static_DEPENDENCIES) + @rm -f cryptsetup.static$(EXEEXT) + $(AM_V_CCLD)$(cryptsetup_static_LINK) $(cryptsetup_static_OBJECTS) $(cryptsetup_static_LDADD) $(LIBS) +src/integritysetup.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +integritysetup$(EXEEXT): $(integritysetup_OBJECTS) $(integritysetup_DEPENDENCIES) $(EXTRA_integritysetup_DEPENDENCIES) + @rm -f integritysetup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(integritysetup_OBJECTS) $(integritysetup_LDADD) $(LIBS) + +integritysetup.static$(EXEEXT): $(integritysetup_static_OBJECTS) $(integritysetup_static_DEPENDENCIES) $(EXTRA_integritysetup_static_DEPENDENCIES) + @rm -f integritysetup.static$(EXEEXT) + $(AM_V_CCLD)$(integritysetup_static_LINK) $(integritysetup_static_OBJECTS) $(integritysetup_static_LDADD) $(LIBS) +src/veritysetup.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +veritysetup$(EXEEXT): $(veritysetup_OBJECTS) $(veritysetup_DEPENDENCIES) $(EXTRA_veritysetup_DEPENDENCIES) + @rm -f veritysetup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(veritysetup_OBJECTS) $(veritysetup_LDADD) $(LIBS) + +veritysetup.static$(EXEEXT): $(veritysetup_static_OBJECTS) $(veritysetup_static_DEPENDENCIES) $(EXTRA_veritysetup_static_DEPENDENCIES) + @rm -f veritysetup.static$(EXEEXT) + $(AM_V_CCLD)$(veritysetup_static_LINK) $(veritysetup_static_OBJECTS) $(veritysetup_static_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f lib/*.$(OBJEXT) + -rm -f lib/*.lo + -rm -f lib/bitlk/*.$(OBJEXT) + -rm -f lib/bitlk/*.lo + -rm -f lib/crypto_backend/*.$(OBJEXT) + -rm -f lib/crypto_backend/*.lo + -rm -f lib/crypto_backend/argon2/*.$(OBJEXT) + -rm -f lib/crypto_backend/argon2/*.lo + -rm -f lib/crypto_backend/argon2/blake2/*.$(OBJEXT) + -rm -f lib/crypto_backend/argon2/blake2/*.lo + -rm -f lib/integrity/*.$(OBJEXT) + -rm -f lib/integrity/*.lo + -rm -f lib/loopaes/*.$(OBJEXT) + -rm -f lib/loopaes/*.lo + -rm -f lib/luks1/*.$(OBJEXT) + -rm -f lib/luks1/*.lo + -rm -f lib/luks2/*.$(OBJEXT) + -rm -f lib/luks2/*.lo + -rm -f lib/tcrypt/*.$(OBJEXT) + -rm -f lib/tcrypt/*.lo + -rm -f lib/verity/*.$(OBJEXT) + -rm -f lib/verity/*.lo + -rm -f src/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-base64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-random.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-setup.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_device.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libcryptsetup_la-volumekey.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/libutils_io_la-utils_io.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/utils_blkid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/utils_crypt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/utils_io.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/utils_loop.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cryptsetup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cryptsetup_reencrypt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/integritysetup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/utils_blockdev.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/utils_luks2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/utils_password.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/utils_tools.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/veritysetup.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo: lib/crypto_backend/argon2/blake2/blake2b.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo -MD -MP -MF lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Tpo -c -o lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo `test -f 'lib/crypto_backend/argon2/blake2/blake2b.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/blake2/blake2b.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Tpo lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/blake2/blake2b.c' object='lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/blake2/libargon2_la-blake2b.lo `test -f 'lib/crypto_backend/argon2/blake2/blake2b.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/blake2/blake2b.c + +lib/crypto_backend/argon2/libargon2_la-argon2.lo: lib/crypto_backend/argon2/argon2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-argon2.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-argon2.lo `test -f 'lib/crypto_backend/argon2/argon2.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/argon2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/argon2.c' object='lib/crypto_backend/argon2/libargon2_la-argon2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-argon2.lo `test -f 'lib/crypto_backend/argon2/argon2.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/argon2.c + +lib/crypto_backend/argon2/libargon2_la-core.lo: lib/crypto_backend/argon2/core.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-core.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-core.lo `test -f 'lib/crypto_backend/argon2/core.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/core.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/core.c' object='lib/crypto_backend/argon2/libargon2_la-core.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-core.lo `test -f 'lib/crypto_backend/argon2/core.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/core.c + +lib/crypto_backend/argon2/libargon2_la-encoding.lo: lib/crypto_backend/argon2/encoding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-encoding.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-encoding.lo `test -f 'lib/crypto_backend/argon2/encoding.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/encoding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/encoding.c' object='lib/crypto_backend/argon2/libargon2_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-encoding.lo `test -f 'lib/crypto_backend/argon2/encoding.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/encoding.c + +lib/crypto_backend/argon2/libargon2_la-thread.lo: lib/crypto_backend/argon2/thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-thread.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-thread.lo `test -f 'lib/crypto_backend/argon2/thread.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/thread.c' object='lib/crypto_backend/argon2/libargon2_la-thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-thread.lo `test -f 'lib/crypto_backend/argon2/thread.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/thread.c + +lib/crypto_backend/argon2/libargon2_la-opt.lo: lib/crypto_backend/argon2/opt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-opt.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-opt.lo `test -f 'lib/crypto_backend/argon2/opt.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/opt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/opt.c' object='lib/crypto_backend/argon2/libargon2_la-opt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-opt.lo `test -f 'lib/crypto_backend/argon2/opt.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/opt.c + +lib/crypto_backend/argon2/libargon2_la-ref.lo: lib/crypto_backend/argon2/ref.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/argon2/libargon2_la-ref.lo -MD -MP -MF lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Tpo -c -o lib/crypto_backend/argon2/libargon2_la-ref.lo `test -f 'lib/crypto_backend/argon2/ref.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/ref.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Tpo lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2/ref.c' object='lib/crypto_backend/argon2/libargon2_la-ref.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libargon2_la_CPPFLAGS) $(CPPFLAGS) $(libargon2_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/argon2/libargon2_la-ref.lo `test -f 'lib/crypto_backend/argon2/ref.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2/ref.c + +lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo: lib/crypto_backend/crypto_cipher_kernel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo `test -f 'lib/crypto_backend/crypto_cipher_kernel.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_cipher_kernel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_cipher_kernel.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_cipher_kernel.lo `test -f 'lib/crypto_backend/crypto_cipher_kernel.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_cipher_kernel.c + +lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo: lib/crypto_backend/crypto_storage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo `test -f 'lib/crypto_backend/crypto_storage.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_storage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_storage.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_storage.lo `test -f 'lib/crypto_backend/crypto_storage.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_storage.c + +lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo: lib/crypto_backend/pbkdf_check.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo `test -f 'lib/crypto_backend/pbkdf_check.c' || echo '$(srcdir)/'`lib/crypto_backend/pbkdf_check.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/pbkdf_check.c' object='lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-pbkdf_check.lo `test -f 'lib/crypto_backend/pbkdf_check.c' || echo '$(srcdir)/'`lib/crypto_backend/pbkdf_check.c + +lib/crypto_backend/libcrypto_backend_la-crc32.lo: lib/crypto_backend/crc32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crc32.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crc32.lo `test -f 'lib/crypto_backend/crc32.c' || echo '$(srcdir)/'`lib/crypto_backend/crc32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crc32.c' object='lib/crypto_backend/libcrypto_backend_la-crc32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crc32.lo `test -f 'lib/crypto_backend/crc32.c' || echo '$(srcdir)/'`lib/crypto_backend/crc32.c + +lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo: lib/crypto_backend/argon2_generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo `test -f 'lib/crypto_backend/argon2_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2_generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/argon2_generic.c' object='lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-argon2_generic.lo `test -f 'lib/crypto_backend/argon2_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/argon2_generic.c + +lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo: lib/crypto_backend/cipher_generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo `test -f 'lib/crypto_backend/cipher_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/cipher_generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/cipher_generic.c' object='lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-cipher_generic.lo `test -f 'lib/crypto_backend/cipher_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/cipher_generic.c + +lib/crypto_backend/libcrypto_backend_la-cipher_check.lo: lib/crypto_backend/cipher_check.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-cipher_check.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-cipher_check.lo `test -f 'lib/crypto_backend/cipher_check.c' || echo '$(srcdir)/'`lib/crypto_backend/cipher_check.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/cipher_check.c' object='lib/crypto_backend/libcrypto_backend_la-cipher_check.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-cipher_check.lo `test -f 'lib/crypto_backend/cipher_check.c' || echo '$(srcdir)/'`lib/crypto_backend/cipher_check.c + +lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo: lib/crypto_backend/crypto_gcrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo `test -f 'lib/crypto_backend/crypto_gcrypt.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_gcrypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_gcrypt.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_gcrypt.lo `test -f 'lib/crypto_backend/crypto_gcrypt.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_gcrypt.c + +lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo: lib/crypto_backend/crypto_openssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo `test -f 'lib/crypto_backend/crypto_openssl.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_openssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_openssl.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_openssl.lo `test -f 'lib/crypto_backend/crypto_openssl.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_openssl.c + +lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo: lib/crypto_backend/crypto_nss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo `test -f 'lib/crypto_backend/crypto_nss.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_nss.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_nss.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_nss.lo `test -f 'lib/crypto_backend/crypto_nss.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_nss.c + +lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo: lib/crypto_backend/crypto_kernel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo `test -f 'lib/crypto_backend/crypto_kernel.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_kernel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_kernel.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_kernel.lo `test -f 'lib/crypto_backend/crypto_kernel.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_kernel.c + +lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo: lib/crypto_backend/crypto_nettle.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo `test -f 'lib/crypto_backend/crypto_nettle.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_nettle.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/crypto_nettle.c' object='lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-crypto_nettle.lo `test -f 'lib/crypto_backend/crypto_nettle.c' || echo '$(srcdir)/'`lib/crypto_backend/crypto_nettle.c + +lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo: lib/crypto_backend/pbkdf2_generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo -MD -MP -MF lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Tpo -c -o lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo `test -f 'lib/crypto_backend/pbkdf2_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/pbkdf2_generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Tpo lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypto_backend/pbkdf2_generic.c' object='lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o lib/crypto_backend/libcrypto_backend_la-pbkdf2_generic.lo `test -f 'lib/crypto_backend/pbkdf2_generic.c' || echo '$(srcdir)/'`lib/crypto_backend/pbkdf2_generic.c + +lib/libcryptsetup_la-setup.lo: lib/setup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-setup.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-setup.Tpo -c -o lib/libcryptsetup_la-setup.lo `test -f 'lib/setup.c' || echo '$(srcdir)/'`lib/setup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-setup.Tpo lib/$(DEPDIR)/libcryptsetup_la-setup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/setup.c' object='lib/libcryptsetup_la-setup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-setup.lo `test -f 'lib/setup.c' || echo '$(srcdir)/'`lib/setup.c + +lib/libcryptsetup_la-utils.lo: lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils.Tpo -c -o lib/libcryptsetup_la-utils.lo `test -f 'lib/utils.c' || echo '$(srcdir)/'`lib/utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils.c' object='lib/libcryptsetup_la-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils.lo `test -f 'lib/utils.c' || echo '$(srcdir)/'`lib/utils.c + +lib/libcryptsetup_la-utils_benchmark.lo: lib/utils_benchmark.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_benchmark.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Tpo -c -o lib/libcryptsetup_la-utils_benchmark.lo `test -f 'lib/utils_benchmark.c' || echo '$(srcdir)/'`lib/utils_benchmark.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_benchmark.c' object='lib/libcryptsetup_la-utils_benchmark.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_benchmark.lo `test -f 'lib/utils_benchmark.c' || echo '$(srcdir)/'`lib/utils_benchmark.c + +lib/libcryptsetup_la-utils_crypt.lo: lib/utils_crypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_crypt.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Tpo -c -o lib/libcryptsetup_la-utils_crypt.lo `test -f 'lib/utils_crypt.c' || echo '$(srcdir)/'`lib/utils_crypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_crypt.c' object='lib/libcryptsetup_la-utils_crypt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_crypt.lo `test -f 'lib/utils_crypt.c' || echo '$(srcdir)/'`lib/utils_crypt.c + +lib/libcryptsetup_la-utils_loop.lo: lib/utils_loop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_loop.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Tpo -c -o lib/libcryptsetup_la-utils_loop.lo `test -f 'lib/utils_loop.c' || echo '$(srcdir)/'`lib/utils_loop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_loop.c' object='lib/libcryptsetup_la-utils_loop.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_loop.lo `test -f 'lib/utils_loop.c' || echo '$(srcdir)/'`lib/utils_loop.c + +lib/libcryptsetup_la-utils_devpath.lo: lib/utils_devpath.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_devpath.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Tpo -c -o lib/libcryptsetup_la-utils_devpath.lo `test -f 'lib/utils_devpath.c' || echo '$(srcdir)/'`lib/utils_devpath.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_devpath.c' object='lib/libcryptsetup_la-utils_devpath.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_devpath.lo `test -f 'lib/utils_devpath.c' || echo '$(srcdir)/'`lib/utils_devpath.c + +lib/libcryptsetup_la-utils_wipe.lo: lib/utils_wipe.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_wipe.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Tpo -c -o lib/libcryptsetup_la-utils_wipe.lo `test -f 'lib/utils_wipe.c' || echo '$(srcdir)/'`lib/utils_wipe.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_wipe.c' object='lib/libcryptsetup_la-utils_wipe.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_wipe.lo `test -f 'lib/utils_wipe.c' || echo '$(srcdir)/'`lib/utils_wipe.c + +lib/libcryptsetup_la-utils_fips.lo: lib/utils_fips.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_fips.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Tpo -c -o lib/libcryptsetup_la-utils_fips.lo `test -f 'lib/utils_fips.c' || echo '$(srcdir)/'`lib/utils_fips.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_fips.c' object='lib/libcryptsetup_la-utils_fips.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_fips.lo `test -f 'lib/utils_fips.c' || echo '$(srcdir)/'`lib/utils_fips.c + +lib/libcryptsetup_la-utils_device.lo: lib/utils_device.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_device.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_device.Tpo -c -o lib/libcryptsetup_la-utils_device.lo `test -f 'lib/utils_device.c' || echo '$(srcdir)/'`lib/utils_device.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_device.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_device.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_device.c' object='lib/libcryptsetup_la-utils_device.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_device.lo `test -f 'lib/utils_device.c' || echo '$(srcdir)/'`lib/utils_device.c + +lib/libcryptsetup_la-utils_keyring.lo: lib/utils_keyring.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_keyring.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Tpo -c -o lib/libcryptsetup_la-utils_keyring.lo `test -f 'lib/utils_keyring.c' || echo '$(srcdir)/'`lib/utils_keyring.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_keyring.c' object='lib/libcryptsetup_la-utils_keyring.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_keyring.lo `test -f 'lib/utils_keyring.c' || echo '$(srcdir)/'`lib/utils_keyring.c + +lib/libcryptsetup_la-utils_device_locking.lo: lib/utils_device_locking.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_device_locking.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Tpo -c -o lib/libcryptsetup_la-utils_device_locking.lo `test -f 'lib/utils_device_locking.c' || echo '$(srcdir)/'`lib/utils_device_locking.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_device_locking.c' object='lib/libcryptsetup_la-utils_device_locking.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_device_locking.lo `test -f 'lib/utils_device_locking.c' || echo '$(srcdir)/'`lib/utils_device_locking.c + +lib/libcryptsetup_la-utils_pbkdf.lo: lib/utils_pbkdf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_pbkdf.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Tpo -c -o lib/libcryptsetup_la-utils_pbkdf.lo `test -f 'lib/utils_pbkdf.c' || echo '$(srcdir)/'`lib/utils_pbkdf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_pbkdf.c' object='lib/libcryptsetup_la-utils_pbkdf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_pbkdf.lo `test -f 'lib/utils_pbkdf.c' || echo '$(srcdir)/'`lib/utils_pbkdf.c + +lib/libcryptsetup_la-utils_safe_memory.lo: lib/utils_safe_memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_safe_memory.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Tpo -c -o lib/libcryptsetup_la-utils_safe_memory.lo `test -f 'lib/utils_safe_memory.c' || echo '$(srcdir)/'`lib/utils_safe_memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_safe_memory.c' object='lib/libcryptsetup_la-utils_safe_memory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_safe_memory.lo `test -f 'lib/utils_safe_memory.c' || echo '$(srcdir)/'`lib/utils_safe_memory.c + +lib/libcryptsetup_la-utils_storage_wrappers.lo: lib/utils_storage_wrappers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_storage_wrappers.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Tpo -c -o lib/libcryptsetup_la-utils_storage_wrappers.lo `test -f 'lib/utils_storage_wrappers.c' || echo '$(srcdir)/'`lib/utils_storage_wrappers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_storage_wrappers.c' object='lib/libcryptsetup_la-utils_storage_wrappers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_storage_wrappers.lo `test -f 'lib/utils_storage_wrappers.c' || echo '$(srcdir)/'`lib/utils_storage_wrappers.c + +lib/libcryptsetup_la-libdevmapper.lo: lib/libdevmapper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-libdevmapper.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Tpo -c -o lib/libcryptsetup_la-libdevmapper.lo `test -f 'lib/libdevmapper.c' || echo '$(srcdir)/'`lib/libdevmapper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Tpo lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/libdevmapper.c' object='lib/libcryptsetup_la-libdevmapper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-libdevmapper.lo `test -f 'lib/libdevmapper.c' || echo '$(srcdir)/'`lib/libdevmapper.c + +lib/libcryptsetup_la-volumekey.lo: lib/volumekey.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-volumekey.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-volumekey.Tpo -c -o lib/libcryptsetup_la-volumekey.lo `test -f 'lib/volumekey.c' || echo '$(srcdir)/'`lib/volumekey.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-volumekey.Tpo lib/$(DEPDIR)/libcryptsetup_la-volumekey.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/volumekey.c' object='lib/libcryptsetup_la-volumekey.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-volumekey.lo `test -f 'lib/volumekey.c' || echo '$(srcdir)/'`lib/volumekey.c + +lib/libcryptsetup_la-random.lo: lib/random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-random.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-random.Tpo -c -o lib/libcryptsetup_la-random.lo `test -f 'lib/random.c' || echo '$(srcdir)/'`lib/random.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-random.Tpo lib/$(DEPDIR)/libcryptsetup_la-random.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/random.c' object='lib/libcryptsetup_la-random.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-random.lo `test -f 'lib/random.c' || echo '$(srcdir)/'`lib/random.c + +lib/libcryptsetup_la-crypt_plain.lo: lib/crypt_plain.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-crypt_plain.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Tpo -c -o lib/libcryptsetup_la-crypt_plain.lo `test -f 'lib/crypt_plain.c' || echo '$(srcdir)/'`lib/crypt_plain.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Tpo lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/crypt_plain.c' object='lib/libcryptsetup_la-crypt_plain.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-crypt_plain.lo `test -f 'lib/crypt_plain.c' || echo '$(srcdir)/'`lib/crypt_plain.c + +lib/libcryptsetup_la-base64.lo: lib/base64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-base64.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-base64.Tpo -c -o lib/libcryptsetup_la-base64.lo `test -f 'lib/base64.c' || echo '$(srcdir)/'`lib/base64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-base64.Tpo lib/$(DEPDIR)/libcryptsetup_la-base64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/base64.c' object='lib/libcryptsetup_la-base64.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-base64.lo `test -f 'lib/base64.c' || echo '$(srcdir)/'`lib/base64.c + +lib/integrity/libcryptsetup_la-integrity.lo: lib/integrity/integrity.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/integrity/libcryptsetup_la-integrity.lo -MD -MP -MF lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Tpo -c -o lib/integrity/libcryptsetup_la-integrity.lo `test -f 'lib/integrity/integrity.c' || echo '$(srcdir)/'`lib/integrity/integrity.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Tpo lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/integrity/integrity.c' object='lib/integrity/libcryptsetup_la-integrity.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/integrity/libcryptsetup_la-integrity.lo `test -f 'lib/integrity/integrity.c' || echo '$(srcdir)/'`lib/integrity/integrity.c + +lib/loopaes/libcryptsetup_la-loopaes.lo: lib/loopaes/loopaes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/loopaes/libcryptsetup_la-loopaes.lo -MD -MP -MF lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Tpo -c -o lib/loopaes/libcryptsetup_la-loopaes.lo `test -f 'lib/loopaes/loopaes.c' || echo '$(srcdir)/'`lib/loopaes/loopaes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Tpo lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/loopaes/loopaes.c' object='lib/loopaes/libcryptsetup_la-loopaes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/loopaes/libcryptsetup_la-loopaes.lo `test -f 'lib/loopaes/loopaes.c' || echo '$(srcdir)/'`lib/loopaes/loopaes.c + +lib/tcrypt/libcryptsetup_la-tcrypt.lo: lib/tcrypt/tcrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/tcrypt/libcryptsetup_la-tcrypt.lo -MD -MP -MF lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Tpo -c -o lib/tcrypt/libcryptsetup_la-tcrypt.lo `test -f 'lib/tcrypt/tcrypt.c' || echo '$(srcdir)/'`lib/tcrypt/tcrypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Tpo lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/tcrypt/tcrypt.c' object='lib/tcrypt/libcryptsetup_la-tcrypt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/tcrypt/libcryptsetup_la-tcrypt.lo `test -f 'lib/tcrypt/tcrypt.c' || echo '$(srcdir)/'`lib/tcrypt/tcrypt.c + +lib/luks1/libcryptsetup_la-af.lo: lib/luks1/af.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks1/libcryptsetup_la-af.lo -MD -MP -MF lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Tpo -c -o lib/luks1/libcryptsetup_la-af.lo `test -f 'lib/luks1/af.c' || echo '$(srcdir)/'`lib/luks1/af.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Tpo lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks1/af.c' object='lib/luks1/libcryptsetup_la-af.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks1/libcryptsetup_la-af.lo `test -f 'lib/luks1/af.c' || echo '$(srcdir)/'`lib/luks1/af.c + +lib/luks1/libcryptsetup_la-keyencryption.lo: lib/luks1/keyencryption.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks1/libcryptsetup_la-keyencryption.lo -MD -MP -MF lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Tpo -c -o lib/luks1/libcryptsetup_la-keyencryption.lo `test -f 'lib/luks1/keyencryption.c' || echo '$(srcdir)/'`lib/luks1/keyencryption.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Tpo lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks1/keyencryption.c' object='lib/luks1/libcryptsetup_la-keyencryption.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks1/libcryptsetup_la-keyencryption.lo `test -f 'lib/luks1/keyencryption.c' || echo '$(srcdir)/'`lib/luks1/keyencryption.c + +lib/luks1/libcryptsetup_la-keymanage.lo: lib/luks1/keymanage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks1/libcryptsetup_la-keymanage.lo -MD -MP -MF lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Tpo -c -o lib/luks1/libcryptsetup_la-keymanage.lo `test -f 'lib/luks1/keymanage.c' || echo '$(srcdir)/'`lib/luks1/keymanage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Tpo lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks1/keymanage.c' object='lib/luks1/libcryptsetup_la-keymanage.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks1/libcryptsetup_la-keymanage.lo `test -f 'lib/luks1/keymanage.c' || echo '$(srcdir)/'`lib/luks1/keymanage.c + +lib/verity/libcryptsetup_la-verity_hash.lo: lib/verity/verity_hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/verity/libcryptsetup_la-verity_hash.lo -MD -MP -MF lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Tpo -c -o lib/verity/libcryptsetup_la-verity_hash.lo `test -f 'lib/verity/verity_hash.c' || echo '$(srcdir)/'`lib/verity/verity_hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Tpo lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/verity/verity_hash.c' object='lib/verity/libcryptsetup_la-verity_hash.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/verity/libcryptsetup_la-verity_hash.lo `test -f 'lib/verity/verity_hash.c' || echo '$(srcdir)/'`lib/verity/verity_hash.c + +lib/verity/libcryptsetup_la-verity_fec.lo: lib/verity/verity_fec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/verity/libcryptsetup_la-verity_fec.lo -MD -MP -MF lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Tpo -c -o lib/verity/libcryptsetup_la-verity_fec.lo `test -f 'lib/verity/verity_fec.c' || echo '$(srcdir)/'`lib/verity/verity_fec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Tpo lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/verity/verity_fec.c' object='lib/verity/libcryptsetup_la-verity_fec.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/verity/libcryptsetup_la-verity_fec.lo `test -f 'lib/verity/verity_fec.c' || echo '$(srcdir)/'`lib/verity/verity_fec.c + +lib/verity/libcryptsetup_la-verity.lo: lib/verity/verity.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/verity/libcryptsetup_la-verity.lo -MD -MP -MF lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Tpo -c -o lib/verity/libcryptsetup_la-verity.lo `test -f 'lib/verity/verity.c' || echo '$(srcdir)/'`lib/verity/verity.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Tpo lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/verity/verity.c' object='lib/verity/libcryptsetup_la-verity.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/verity/libcryptsetup_la-verity.lo `test -f 'lib/verity/verity.c' || echo '$(srcdir)/'`lib/verity/verity.c + +lib/verity/libcryptsetup_la-rs_encode_char.lo: lib/verity/rs_encode_char.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/verity/libcryptsetup_la-rs_encode_char.lo -MD -MP -MF lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Tpo -c -o lib/verity/libcryptsetup_la-rs_encode_char.lo `test -f 'lib/verity/rs_encode_char.c' || echo '$(srcdir)/'`lib/verity/rs_encode_char.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Tpo lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/verity/rs_encode_char.c' object='lib/verity/libcryptsetup_la-rs_encode_char.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/verity/libcryptsetup_la-rs_encode_char.lo `test -f 'lib/verity/rs_encode_char.c' || echo '$(srcdir)/'`lib/verity/rs_encode_char.c + +lib/verity/libcryptsetup_la-rs_decode_char.lo: lib/verity/rs_decode_char.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/verity/libcryptsetup_la-rs_decode_char.lo -MD -MP -MF lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Tpo -c -o lib/verity/libcryptsetup_la-rs_decode_char.lo `test -f 'lib/verity/rs_decode_char.c' || echo '$(srcdir)/'`lib/verity/rs_decode_char.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Tpo lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/verity/rs_decode_char.c' object='lib/verity/libcryptsetup_la-rs_decode_char.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/verity/libcryptsetup_la-rs_decode_char.lo `test -f 'lib/verity/rs_decode_char.c' || echo '$(srcdir)/'`lib/verity/rs_decode_char.c + +lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo: lib/luks2/luks2_disk_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo `test -f 'lib/luks2/luks2_disk_metadata.c' || echo '$(srcdir)/'`lib/luks2/luks2_disk_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_disk_metadata.c' object='lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_disk_metadata.lo `test -f 'lib/luks2/luks2_disk_metadata.c' || echo '$(srcdir)/'`lib/luks2/luks2_disk_metadata.c + +lib/luks2/libcryptsetup_la-luks2_json_format.lo: lib/luks2/luks2_json_format.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_json_format.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_json_format.lo `test -f 'lib/luks2/luks2_json_format.c' || echo '$(srcdir)/'`lib/luks2/luks2_json_format.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_json_format.c' object='lib/luks2/libcryptsetup_la-luks2_json_format.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_json_format.lo `test -f 'lib/luks2/luks2_json_format.c' || echo '$(srcdir)/'`lib/luks2/luks2_json_format.c + +lib/luks2/libcryptsetup_la-luks2_json_metadata.lo: lib/luks2/luks2_json_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_json_metadata.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_json_metadata.lo `test -f 'lib/luks2/luks2_json_metadata.c' || echo '$(srcdir)/'`lib/luks2/luks2_json_metadata.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_json_metadata.c' object='lib/luks2/libcryptsetup_la-luks2_json_metadata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_json_metadata.lo `test -f 'lib/luks2/luks2_json_metadata.c' || echo '$(srcdir)/'`lib/luks2/luks2_json_metadata.c + +lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo: lib/luks2/luks2_luks1_convert.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo `test -f 'lib/luks2/luks2_luks1_convert.c' || echo '$(srcdir)/'`lib/luks2/luks2_luks1_convert.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_luks1_convert.c' object='lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_luks1_convert.lo `test -f 'lib/luks2/luks2_luks1_convert.c' || echo '$(srcdir)/'`lib/luks2/luks2_luks1_convert.c + +lib/luks2/libcryptsetup_la-luks2_digest.lo: lib/luks2/luks2_digest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_digest.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_digest.lo `test -f 'lib/luks2/luks2_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_digest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_digest.c' object='lib/luks2/libcryptsetup_la-luks2_digest.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_digest.lo `test -f 'lib/luks2/luks2_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_digest.c + +lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo: lib/luks2/luks2_digest_pbkdf2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo `test -f 'lib/luks2/luks2_digest_pbkdf2.c' || echo '$(srcdir)/'`lib/luks2/luks2_digest_pbkdf2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_digest_pbkdf2.c' object='lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_digest_pbkdf2.lo `test -f 'lib/luks2/luks2_digest_pbkdf2.c' || echo '$(srcdir)/'`lib/luks2/luks2_digest_pbkdf2.c + +lib/luks2/libcryptsetup_la-luks2_keyslot.lo: lib/luks2/luks2_keyslot.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_keyslot.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_keyslot.lo `test -f 'lib/luks2/luks2_keyslot.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_keyslot.c' object='lib/luks2/libcryptsetup_la-luks2_keyslot.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_keyslot.lo `test -f 'lib/luks2/luks2_keyslot.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot.c + +lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo: lib/luks2/luks2_keyslot_luks2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo `test -f 'lib/luks2/luks2_keyslot_luks2.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot_luks2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_keyslot_luks2.c' object='lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo `test -f 'lib/luks2/luks2_keyslot_luks2.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot_luks2.c + +lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo: lib/luks2/luks2_keyslot_reenc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo `test -f 'lib/luks2/luks2_keyslot_reenc.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot_reenc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_keyslot_reenc.c' object='lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo `test -f 'lib/luks2/luks2_keyslot_reenc.c' || echo '$(srcdir)/'`lib/luks2/luks2_keyslot_reenc.c + +lib/luks2/libcryptsetup_la-luks2_reencrypt.lo: lib/luks2/luks2_reencrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_reencrypt.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt.lo `test -f 'lib/luks2/luks2_reencrypt.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_reencrypt.c' object='lib/luks2/libcryptsetup_la-luks2_reencrypt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt.lo `test -f 'lib/luks2/luks2_reencrypt.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt.c + +lib/luks2/libcryptsetup_la-luks2_segment.lo: lib/luks2/luks2_segment.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_segment.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_segment.lo `test -f 'lib/luks2/luks2_segment.c' || echo '$(srcdir)/'`lib/luks2/luks2_segment.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_segment.c' object='lib/luks2/libcryptsetup_la-luks2_segment.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_segment.lo `test -f 'lib/luks2/luks2_segment.c' || echo '$(srcdir)/'`lib/luks2/luks2_segment.c + +lib/luks2/libcryptsetup_la-luks2_token_keyring.lo: lib/luks2/luks2_token_keyring.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_token_keyring.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_token_keyring.lo `test -f 'lib/luks2/luks2_token_keyring.c' || echo '$(srcdir)/'`lib/luks2/luks2_token_keyring.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_token_keyring.c' object='lib/luks2/libcryptsetup_la-luks2_token_keyring.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_token_keyring.lo `test -f 'lib/luks2/luks2_token_keyring.c' || echo '$(srcdir)/'`lib/luks2/luks2_token_keyring.c + +lib/luks2/libcryptsetup_la-luks2_token.lo: lib/luks2/luks2_token.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_token.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_token.lo `test -f 'lib/luks2/luks2_token.c' || echo '$(srcdir)/'`lib/luks2/luks2_token.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_token.c' object='lib/luks2/libcryptsetup_la-luks2_token.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_token.lo `test -f 'lib/luks2/luks2_token.c' || echo '$(srcdir)/'`lib/luks2/luks2_token.c + +lib/libcryptsetup_la-utils_blkid.lo: lib/utils_blkid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/libcryptsetup_la-utils_blkid.lo -MD -MP -MF lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Tpo -c -o lib/libcryptsetup_la-utils_blkid.lo `test -f 'lib/utils_blkid.c' || echo '$(srcdir)/'`lib/utils_blkid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Tpo lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_blkid.c' object='lib/libcryptsetup_la-utils_blkid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/libcryptsetup_la-utils_blkid.lo `test -f 'lib/utils_blkid.c' || echo '$(srcdir)/'`lib/utils_blkid.c + +lib/bitlk/libcryptsetup_la-bitlk.lo: lib/bitlk/bitlk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/bitlk/libcryptsetup_la-bitlk.lo -MD -MP -MF lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Tpo -c -o lib/bitlk/libcryptsetup_la-bitlk.lo `test -f 'lib/bitlk/bitlk.c' || echo '$(srcdir)/'`lib/bitlk/bitlk.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Tpo lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/bitlk/bitlk.c' object='lib/bitlk/libcryptsetup_la-bitlk.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/bitlk/libcryptsetup_la-bitlk.lo `test -f 'lib/bitlk/bitlk.c' || echo '$(srcdir)/'`lib/bitlk/bitlk.c + +lib/libutils_io_la-utils_io.lo: lib/utils_io.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutils_io_la_CFLAGS) $(CFLAGS) -MT lib/libutils_io_la-utils_io.lo -MD -MP -MF lib/$(DEPDIR)/libutils_io_la-utils_io.Tpo -c -o lib/libutils_io_la-utils_io.lo `test -f 'lib/utils_io.c' || echo '$(srcdir)/'`lib/utils_io.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/libutils_io_la-utils_io.Tpo lib/$(DEPDIR)/libutils_io_la-utils_io.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/utils_io.c' object='lib/libutils_io_la-utils_io.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutils_io_la_CFLAGS) $(CFLAGS) -c -o lib/libutils_io_la-utils_io.lo `test -f 'lib/utils_io.c' || echo '$(srcdir)/'`lib/utils_io.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs + -rm -rf lib/.libs lib/_libs + -rm -rf lib/bitlk/.libs lib/bitlk/_libs + -rm -rf lib/crypto_backend/.libs lib/crypto_backend/_libs + -rm -rf lib/crypto_backend/argon2/.libs lib/crypto_backend/argon2/_libs + -rm -rf lib/crypto_backend/argon2/blake2/.libs lib/crypto_backend/argon2/blake2/_libs + -rm -rf lib/integrity/.libs lib/integrity/_libs + -rm -rf lib/loopaes/.libs lib/loopaes/_libs + -rm -rf lib/luks1/.libs lib/luks1/_libs + -rm -rf lib/luks2/.libs lib/luks2/_libs + -rm -rf lib/tcrypt/.libs lib/tcrypt/_libs + -rm -rf lib/verity/.libs lib/verity/_libs distclean-libtool: -rm -f libtool config.lt +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-tmpfilesdDATA: $(tmpfilesd_DATA) + @$(NORMAL_INSTALL) + @list='$(tmpfilesd_DATA)'; test -n "$(tmpfilesddir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(tmpfilesddir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(tmpfilesddir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(tmpfilesddir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(tmpfilesddir)" || exit $$?; \ + done + +uninstall-tmpfilesdDATA: + @$(NORMAL_UNINSTALL) + @list='$(tmpfilesd_DATA)'; test -n "$(tmpfilesddir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(tmpfilesddir)'; $(am__uninstall_files_from_dir) +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. @@ -545,7 +2410,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -610,7 +2478,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -624,18 +2492,22 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -653,7 +2525,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -663,23 +2535,25 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -734,9 +2608,13 @@ distcleancheck: distclean exit 1; } >&2 check-am: all-am check: check-recursive -all-am: Makefile config.h +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) \ + config.h installdirs: installdirs-recursive installdirs-am: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(tmpfilesddir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive @@ -759,23 +2637,127 @@ install-strip: mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f lib/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/$(am__dirstamp) + -rm -f lib/bitlk/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/bitlk/$(am__dirstamp) + -rm -f lib/crypto_backend/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/crypto_backend/$(am__dirstamp) + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/crypto_backend/argon2/$(am__dirstamp) + -rm -f lib/crypto_backend/argon2/blake2/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/crypto_backend/argon2/blake2/$(am__dirstamp) + -rm -f lib/integrity/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/integrity/$(am__dirstamp) + -rm -f lib/loopaes/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/loopaes/$(am__dirstamp) + -rm -f lib/luks1/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/luks1/$(am__dirstamp) + -rm -f lib/luks2/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/luks2/$(am__dirstamp) + -rm -f lib/tcrypt/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/tcrypt/$(am__dirstamp) + -rm -f lib/verity/$(DEPDIR)/$(am__dirstamp) + -rm -f lib/verity/$(am__dirstamp) + -rm -f src/$(DEPDIR)/$(am__dirstamp) + -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive -clean-am: clean-generic clean-libtool clean-local mostlyclean-am +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ + clean-noinstLTLIBRARIES clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f lib/$(DEPDIR)/libcryptsetup_la-base64.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-random.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-setup.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_device.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-volumekey.Plo + -rm -f lib/$(DEPDIR)/libutils_io_la-utils_io.Plo + -rm -f lib/$(DEPDIR)/utils_blkid.Po + -rm -f lib/$(DEPDIR)/utils_crypt.Po + -rm -f lib/$(DEPDIR)/utils_io.Po + -rm -f lib/$(DEPDIR)/utils_loop.Po + -rm -f lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Plo + -rm -f lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Plo + -rm -f lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Plo + -rm -f lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo + -rm -f lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Plo + -rm -f src/$(DEPDIR)/cryptsetup.Po + -rm -f src/$(DEPDIR)/cryptsetup_reencrypt.Po + -rm -f src/$(DEPDIR)/integritysetup.Po + -rm -f src/$(DEPDIR)/utils_blockdev.Po + -rm -f src/$(DEPDIR)/utils_luks2.Po + -rm -f src/$(DEPDIR)/utils_password.Po + -rm -f src/$(DEPDIR)/utils_tools.Po + -rm -f src/$(DEPDIR)/veritysetup.Po -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-hdr \ - distclean-libtool distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-local distclean-tags dvi: dvi-recursive @@ -789,13 +2771,14 @@ info: info-recursive info-am: -install-data-am: +install-data-am: install-includeHEADERS install-man \ + install-pkgconfigDATA install-tmpfilesdDATA install-dvi: install-dvi-recursive install-dvi-am: -install-exec-am: +install-exec-am: install-libLTLIBRARIES install-sbinPROGRAMS install-html: install-html-recursive @@ -805,7 +2788,7 @@ install-info: install-info-recursive install-info-am: -install-man: +install-man: install-man8 install-pdf: install-pdf-recursive @@ -820,12 +2803,91 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache + -rm -f lib/$(DEPDIR)/libcryptsetup_la-base64.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-random.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-setup.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_blkid.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_device.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_device_locking.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_fips.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_keyring.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_loop.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_pbkdf.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_safe_memory.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_storage_wrappers.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo + -rm -f lib/$(DEPDIR)/libcryptsetup_la-volumekey.Plo + -rm -f lib/$(DEPDIR)/libutils_io_la-utils_io.Plo + -rm -f lib/$(DEPDIR)/utils_blkid.Po + -rm -f lib/$(DEPDIR)/utils_crypt.Po + -rm -f lib/$(DEPDIR)/utils_io.Po + -rm -f lib/$(DEPDIR)/utils_loop.Po + -rm -f lib/bitlk/$(DEPDIR)/libcryptsetup_la-bitlk.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-argon2_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_check.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-cipher_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crc32.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo + -rm -f lib/crypto_backend/$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-argon2.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-core.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-encoding.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-opt.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-ref.Plo + -rm -f lib/crypto_backend/argon2/$(DEPDIR)/libargon2_la-thread.Plo + -rm -f lib/crypto_backend/argon2/blake2/$(DEPDIR)/libargon2_la-blake2b.Plo + -rm -f lib/integrity/$(DEPDIR)/libcryptsetup_la-integrity.Plo + -rm -f lib/loopaes/$(DEPDIR)/libcryptsetup_la-loopaes.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-af.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-keyencryption.Plo + -rm -f lib/luks1/$(DEPDIR)/libcryptsetup_la-keymanage.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_digest_pbkdf2.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_disk_metadata.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_format.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_json_metadata.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_luks2.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo + -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo + -rm -f lib/tcrypt/$(DEPDIR)/libcryptsetup_la-tcrypt.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-rs_decode_char.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-rs_encode_char.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity_fec.Plo + -rm -f lib/verity/$(DEPDIR)/libcryptsetup_la-verity_hash.Plo + -rm -f src/$(DEPDIR)/cryptsetup.Po + -rm -f src/$(DEPDIR)/cryptsetup_reencrypt.Po + -rm -f src/$(DEPDIR)/integritysetup.Po + -rm -f src/$(DEPDIR)/utils_blockdev.Po + -rm -f src/$(DEPDIR)/utils_luks2.Po + -rm -f src/$(DEPDIR)/utils_password.Po + -rm -f src/$(DEPDIR)/utils_tools.Po + -rm -f src/$(DEPDIR)/veritysetup.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive -mostlyclean-am: mostlyclean-generic mostlyclean-libtool +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf: pdf-recursive @@ -835,30 +2897,47 @@ ps: ps-recursive ps-am: -uninstall-am: +uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \ + uninstall-man uninstall-pkgconfigDATA uninstall-sbinPROGRAMS \ + uninstall-tmpfilesdDATA + +uninstall-man: uninstall-man8 .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ - am--refresh check check-am clean clean-cscope clean-generic \ - clean-libtool clean-local cscope cscopelist-am ctags ctags-am \ - dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \ - dist-tarZ dist-xz dist-zip distcheck distclean \ + am--depfiles am--refresh check check-am clean clean-cscope \ + clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ + clean-noinstLTLIBRARIES clean-sbinPROGRAMS cscope \ + cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + dist-zstd distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-libtool \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs installdirs-am \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am + distclean-local distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-man8 install-pdf install-pdf-am install-pkgconfigDATA \ + install-ps install-ps-am install-sbinPROGRAMS install-strip \ + install-tmpfilesdDATA installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-includeHEADERS uninstall-libLTLIBRARIES \ + uninstall-man uninstall-man8 uninstall-pkgconfigDATA \ + uninstall-sbinPROGRAMS uninstall-tmpfilesdDATA + +.PRECIOUS: Makefile + +distclean-local: + -find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f + rm -rf autom4te.cache clean-local: - -rm -rf docs/doxygen_api_docs + -rm -rf docs/doxygen_api_docs libargon2.la # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/TODO b/TODO index b5a66e1..58e5cc9 100644 --- a/TODO +++ b/TODO @@ -1,8 +1 @@ -Version 1.7: -- Export wipe device functions -- Support K/M suffixes for align payload (new switch?). -- TRIM for keyslots -- Do we need crypt_data_path() - path to data device (if differs)? -- Resync ETA time is not accurate, calculate it better (last minute window?). -- Extend existing LUKS header to use another KDF? (https://password-hashing.net/) -- Fix all crazy automake warnings (or switch to Cmake). +Please see issues tracked at https://gitlab.com/cryptsetup/cryptsetup/issues. diff --git a/aclocal.m4 b/aclocal.m4 index 5185896..b5fedd0 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.14.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,16 +20,18 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -dnl Autoconf macros for libgcrypt -dnl Copyright (C) 2002, 2004, 2011 Free Software Foundation, Inc. -dnl -dnl This file is free software; as a special exception the author gives -dnl unlimited permission to copy and/or distribute it, with or without -dnl modifications, as long as this notice is preserved. -dnl -dnl This file is distributed in the hope that it will be useful, but -dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# libgcrypt.m4 - Autoconf macros to detect libgcrypt +# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Last-changed: 2018-11-13 dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, @@ -42,19 +44,49 @@ dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using dnl this features allows to prevent build against newer versions of libgcrypt dnl with a changed API. dnl +dnl If a prefix option is not used, the config script is first +dnl searched in $SYSROOT/bin and then along $PATH. If the used +dnl config script does not match the host specification the script +dnl is added to the gpg_config_script_warn variable. +dnl AC_DEFUN([AM_PATH_LIBGCRYPT], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_WITH(libgcrypt-prefix, AC_HELP_STRING([--with-libgcrypt-prefix=PFX], [prefix where LIBGCRYPT is installed (optional)]), libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") - if test x$libgcrypt_config_prefix != x ; then - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + if test x"${LIBGCRYPT_CONFIG}" = x ; then + if test x"${libgcrypt_config_prefix}" != x ; then + LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config" fi fi - AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no) + use_gpgrt_config="" + if test x"${LIBGCRYPT_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then + if $GPGRT_CONFIG libgcrypt --exists; then + LIBGCRYPT_CONFIG="$GPGRT_CONFIG libgcrypt" + AC_MSG_NOTICE([Use gpgrt-config as libgcrypt-config]) + use_gpgrt_config=yes + fi + fi + if test -z "$use_gpgrt_config"; then + if test x"${LIBGCRYPT_CONFIG}" = x ; then + case "${SYSROOT}" in + /*) + if test -x "${SYSROOT}/bin/libgcrypt-config" ; then + LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config" + fi + ;; + '') + ;; + *) + AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) + ;; + esac + fi + AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) + fi + tmp=ifelse([$1], ,1:1.2.0,$1) if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` @@ -73,7 +105,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT], sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + if test -z "$use_gpgrt_config"; then + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + else + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --modversion` + fi major=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ @@ -105,7 +141,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT], # If we have a recent libgcrypt, we should also check that the # API is compatible if test "$req_libgcrypt_api" -gt 0 ; then - tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test -z "$use_gpgrt_config"; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$LIBGCRYPT_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi if test "$tmp" -gt 0 ; then AC_MSG_CHECKING([LIBGCRYPT API version]) if test "$req_libgcrypt_api" -eq "$tmp" ; then @@ -121,17 +161,22 @@ AC_DEFUN([AM_PATH_LIBGCRYPT], LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` ifelse([$2], , :, [$2]) - libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + if test -z "$use_gpgrt_config"; then + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + else + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --variable=host 2>/dev/null || echo none` + fi if test x"$libgcrypt_config_host" != xnone ; then if test x"$libgcrypt_config_host" != x"$host" ; then AC_MSG_WARN([[ *** -*** The config script $LIBGCRYPT_CONFIG was +*** The config script "$LIBGCRYPT_CONFIG" was *** built for $libgcrypt_config_host and thus may not match the *** used host $host. *** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. +*** to specify a matching config script or use \$SYSROOT. ***]]) + gpg_config_script_warn="$gpg_config_script_warn libgcrypt" fi fi else @@ -143,32 +188,63 @@ AC_DEFUN([AM_PATH_LIBGCRYPT], AC_SUBST(LIBGCRYPT_LIBS) ]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -190,18 +266,19 @@ if test -n "$PKG_CONFIG"; then PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -211,8 +288,10 @@ m4_ifvaln([$3], [else $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -224,10 +303,11 @@ m4_define([_PKG_CONFIG], else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -235,26 +315,24 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -264,11 +342,11 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -285,7 +363,7 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -301,16 +379,40 @@ else AC_MSG_RESULT([yes]) $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC -# PKG_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable pkgconfigdir as the location where a module -# should install pkg-config .pc files. By default the directory is -# $libdir/pkgconfig, but the default can be changed by passing -# DIRECTORY. The user can override through the --with-pkgconfigdir -# parameter. + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -321,16 +423,18 @@ AC_ARG_WITH([pkgconfigdir], AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_INSTALLDIR +])dnl PKG_INSTALLDIR -# PKG_NOARCH_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable noarch_pkgconfigdir as the location where a -# module should install arch-independent pkg-config .pc files. By -# default the directory is $datadir/pkgconfig, but the default can be -# changed by passing DIRECTORY. The user can override through the -# --with-noarch-pkgconfigdir parameter. +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -341,13 +445,15 @@ AC_ARG_WITH([noarch-pkgconfigdir], AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_NOARCH_INSTALLDIR +])dnl PKG_NOARCH_INSTALLDIR -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# ------------------------------------------- -# Retrieves the value of the pkg-config variable for the given module. +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl @@ -356,9 +462,9 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl -])# PKG_CHECK_VAR +])dnl PKG_CHECK_VAR -# Copyright (C) 2002-2013 Free Software Foundation, Inc. +# Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -370,10 +476,10 @@ AS_VAR_IF([$1], [""], [$5], [$4])dnl # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.14' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.14.1], [], +m4_if([$1], [1.16.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -389,14 +495,14 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.14.1])dnl +[AM_AUTOMAKE_VERSION([1.16.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -448,7 +554,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -479,7 +585,7 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -670,13 +776,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], @@ -684,49 +789,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -735,18 +834,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -833,11 +931,11 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -901,7 +999,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -911,6 +1009,9 @@ END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not @@ -940,7 +1041,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -951,7 +1052,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -961,7 +1062,7 @@ if test x"${install_sh}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2013 Free Software Foundation, Inc. +# Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -982,7 +1083,7 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -990,49 +1091,42 @@ AC_SUBST([am__leading_dot])]) # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1069,41 +1163,9 @@ else fi ]) -# Copyright (C) 2003-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check for 'mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl FIXME we are no longer going to remove this! adjust warning -dnl FIXME message accordingly. -AC_DIAGNOSE([obsolete], -[$0: this macro is deprecated, and will soon be removed. -You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, -and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1132,7 +1194,7 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1179,242 +1241,7 @@ AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# --------------------------------------------------------------------------- -# Adds support for distributing Python modules and packages. To -# install modules, copy them to $(pythondir), using the python_PYTHON -# automake variable. To install a package with the same name as the -# automake package, install to $(pkgpythondir), or use the -# pkgpython_PYTHON automake variable. -# -# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as -# locations to install python extension modules (shared libraries). -# Another macro is required to find the appropriate flags to compile -# extension modules. -# -# If your package is configured with a different prefix to python, -# users will have to add the install directory to the PYTHONPATH -# environment variable, or create a .pth file (see the python -# documentation for details). -# -# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will -# cause an error if the version of python installed on the system -# doesn't meet the requirement. MINIMUM-VERSION should consist of -# numbers and dots only. -AC_DEFUN([AM_PATH_PYTHON], - [ - dnl Find a Python interpreter. Python versions prior to 2.0 are not - dnl supported. (2.0 was released on October 16, 2000). - m4_define_default([_AM_PYTHON_INTERPRETER_LIST], -[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl - python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) - - AC_ARG_VAR([PYTHON], [the Python interpreter]) - - m4_if([$1],[],[ - dnl No version check is needed. - # Find any Python interpreter. - if test -z "$PYTHON"; then - AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) - fi - am_display_PYTHON=python - ], [ - dnl A version check is needed. - if test -n "$PYTHON"; then - # If the user set $PYTHON, use it and don't search something else. - AC_MSG_CHECKING([whether $PYTHON version is >= $1]) - AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_ERROR([Python interpreter is too old])]) - am_display_PYTHON=$PYTHON - else - # Otherwise, try each interpreter until we find one that satisfies - # VERSION. - AC_CACHE_CHECK([for a Python interpreter with version >= $1], - [am_cv_pathless_PYTHON],[ - for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do - test "$am_cv_pathless_PYTHON" = none && break - AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) - done]) - # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. - if test "$am_cv_pathless_PYTHON" = none; then - PYTHON=: - else - AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) - fi - am_display_PYTHON=$am_cv_pathless_PYTHON - fi - ]) - - if test "$PYTHON" = :; then - dnl Run any user-specified action, or abort. - m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) - else - - dnl Query Python for its version number. Getting [:3] seems to be - dnl the best way to do this; it's what "site.py" does in the standard - dnl library. - - AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], - [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) - AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) - - dnl Use the values of $prefix and $exec_prefix for the corresponding - dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made - dnl distinct variables so they can be overridden if need be. However, - dnl general consensus is that you shouldn't need this ability. - - AC_SUBST([PYTHON_PREFIX], ['${prefix}']) - AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) - - dnl At times (like when building shared libraries) you may want - dnl to know which OS platform Python thinks this is. - - AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], - [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) - AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) - - # Just factor out some code duplication. - am_python_setup_sysconfig="\ -import sys -# Prefer sysconfig over distutils.sysconfig, for better compatibility -# with python 3.x. See automake bug#10227. -try: - import sysconfig -except ImportError: - can_use_sysconfig = 0 -else: - can_use_sysconfig = 1 -# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: -# -try: - from platform import python_implementation - if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': - can_use_sysconfig = 0 -except ImportError: - pass" - - dnl Set up 4 directories: - - dnl pythondir -- where to install python scripts. This is the - dnl site-packages directory, not the python standard library - dnl directory like in previous automake betas. This behavior - dnl is more consistent with lispdir.m4 for example. - dnl Query distutils for this directory. - AC_CACHE_CHECK([for $am_display_PYTHON script directory], - [am_cv_python_pythondir], - [if test "x$prefix" = xNONE - then - am_py_prefix=$ac_default_prefix - else - am_py_prefix=$prefix - fi - am_cv_python_pythondir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - case $am_cv_python_pythondir in - $am_py_prefix*) - am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` - am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` - ;; - *) - case $am_py_prefix in - /usr|/System*) ;; - *) - am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac - ]) - AC_SUBST([pythondir], [$am_cv_python_pythondir]) - - dnl pkgpythondir -- $PACKAGE directory under pythondir. Was - dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is - dnl more consistent with the rest of automake. - - AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) - - dnl pyexecdir -- directory for installing python extension modules - dnl (shared libraries) - dnl Query distutils for this directory. - AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], - [am_cv_python_pyexecdir], - [if test "x$exec_prefix" = xNONE - then - am_py_exec_prefix=$am_py_prefix - else - am_py_exec_prefix=$exec_prefix - fi - am_cv_python_pyexecdir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - case $am_cv_python_pyexecdir in - $am_py_exec_prefix*) - am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` - am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` - ;; - *) - case $am_py_exec_prefix in - /usr|/System*) ;; - *) - am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac - ]) - AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) - - dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) - - AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) - - dnl Run any user-specified action. - $2 - fi - -]) - - -# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) -# --------------------------------------------------------------------------- -# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. -# Run ACTION-IF-FALSE otherwise. -# This test uses sys.hexversion instead of the string equivalent (first -# word of sys.version), in order to cope with versions such as 2.2c1. -# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). -AC_DEFUN([AM_PYTHON_CHECK_VERSION], - [prog="import sys -# split strings by '.' and convert to numeric. Append some zeros -# because we need at least 4 digits for the hex conversion. -# map returns an iterator in Python 3.0 and a list in 2.x -minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] -minverhex = 0 -# xrange is not present in Python 3.0 and range returns an iterator -for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] -sys.exit(sys.hexversion < minverhex)" - AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1433,7 +1260,7 @@ AC_DEFUN([AM_RUN_LOG], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1514,7 +1341,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1574,7 +1401,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1602,7 +1429,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2013 Free Software Foundation, Inc. +# Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1621,7 +1448,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2013 Free Software Foundation, Inc. +# Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1754,6 +1581,7 @@ AC_SUBST([am__untar]) m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) +m4_include([m4/intlmacosx.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) diff --git a/compile b/compile index 531136b..23fcba0 100755 --- a/compile +++ b/compile @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ func_file_conv () MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ func_file_conv () mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) @@ -255,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config.h.in b/config.h.in index 408e256..0e70551 100644 --- a/config.h.in +++ b/config.h.in @@ -27,6 +27,33 @@ /* cipher mode for LUKS1 */ #undef DEFAULT_LUKS1_MODE +/* Argon2 PBKDF iteration time for LUKS2 (in ms) */ +#undef DEFAULT_LUKS2_ITER_TIME + +/* fallback cipher for LUKS2 keyslot (if data encryption is incompatible) */ +#undef DEFAULT_LUKS2_KEYSLOT_CIPHER + +/* fallback key size for LUKS2 keyslot (if data encryption is incompatible) */ +#undef DEFAULT_LUKS2_KEYSLOT_KEYBITS + +/* default luks2 locking directory permissions */ +#undef DEFAULT_LUKS2_LOCK_DIR_PERMS + +/* path to directory for LUKSv2 locks */ +#undef DEFAULT_LUKS2_LOCK_PATH + +/* Argon2 PBKDF memory cost for LUKS2 (in kB) */ +#undef DEFAULT_LUKS2_MEMORY_KB + +/* Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available) */ +#undef DEFAULT_LUKS2_PARALLEL_THREADS + +/* Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2 */ +#undef DEFAULT_LUKS2_PBKDF + +/* default LUKS format version */ +#undef DEFAULT_LUKS_FORMAT + /* maximum keyfile size (in characters) */ #undef DEFAULT_PASSPHRASE_SIZE_MAX @@ -45,9 +72,15 @@ /* default RNG type for key generator */ #undef DEFAULT_RNG +/* override default path to directory with systemd temporary files */ +#undef DEFAULT_TMPFILESDIR + /* data block size for verity mode */ #undef DEFAULT_VERITY_DATA_BLOCK +/* parity bytes for verity FEC */ +#undef DEFAULT_VERITY_FEC_ROOTS + /* hash function for verity mode */ #undef DEFAULT_VERITY_HASH @@ -63,24 +96,45 @@ /* Enable FIPS mode restrictions */ #undef ENABLE_FIPS +/* XTS mode - double default LUKS keysize if needed */ +#undef ENABLE_LUKS_ADJUST_XTS_KEYSIZE + /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS -/* Enable password quality checking */ +/* Enable password quality checking using passwdqc library */ +#undef ENABLE_PASSWDQC + +/* Enable password quality checking using pwquality library */ #undef ENABLE_PWQUALITY /* Requested gcrypt version */ #undef GCRYPT_REQ_VERSION +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGON2_H + +/* Define to 1 to use blkid for detection of disk signatures. */ +#undef HAVE_BLKID + +/* Define to 1 if you have the header file. */ +#undef HAVE_BLKID_BLKID_H + +/* Define to 1 to use blkid_probe_step_back. */ +#undef HAVE_BLKID_STEP_BACK + +/* Define to 1 to use blkid_do_wipe. */ +#undef HAVE_BLKID_WIPE + /* Define to 1 if you have the header file. */ #undef HAVE_BYTESWAP_H -/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYCURRENT -/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE @@ -94,6 +148,50 @@ */ #undef HAVE_DCGETTEXT +/* Define to 1 if you have the declaration of `blkid_do_probe', and to 0 if + you don't. */ +#undef HAVE_DECL_BLKID_DO_PROBE + +/* Define to 1 if you have the declaration of `blkid_do_safeprobe', and to 0 + if you don't. */ +#undef HAVE_DECL_BLKID_DO_SAFEPROBE + +/* Define to 1 if you have the declaration of + `blkid_probe_filter_superblocks_type', and to 0 if you don't. */ +#undef HAVE_DECL_BLKID_PROBE_FILTER_SUPERBLOCKS_TYPE + +/* Define to 1 if you have the declaration of `blkid_probe_lookup_value ', and + to 0 if you don't. */ +#undef HAVE_DECL_BLKID_PROBE_LOOKUP_VALUE__________ + +/* Define to 1 if you have the declaration of `blkid_probe_set_device', and to + 0 if you don't. */ +#undef HAVE_DECL_BLKID_PROBE_SET_DEVICE + +/* Define to 1 if you have the declaration of `blkid_reset_probe', and to 0 if + you don't. */ +#undef HAVE_DECL_BLKID_RESET_PROBE + +/* Define to 1 if you have the declaration of `dm_device_get_name', and to 0 + if you don't. */ +#undef HAVE_DECL_DM_DEVICE_GET_NAME + +/* Define to 1 if you have the declaration of `DM_DEVICE_GET_TARGET_VERSION', + and to 0 if you don't. */ +#undef HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION + +/* Define to 1 if you have the declaration of `dm_device_has_holders', and to + 0 if you don't. */ +#undef HAVE_DECL_DM_DEVICE_HAS_HOLDERS + +/* Define to 1 if you have the declaration of `dm_device_has_mounted_fs', and + to 0 if you don't. */ +#undef HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS + +/* Define to 1 if you have the declaration of `dm_task_deferred_remove', and + to 0 if you don't. */ +#undef HAVE_DECL_DM_TASK_DEFERRED_REMOVE + /* Define to 1 if you have the declaration of `dm_task_retry_remove', and to 0 if you don't. */ #undef HAVE_DECL_DM_TASK_RETRY_REMOVE @@ -106,10 +204,26 @@ `DM_UDEV_DISABLE_DISK_RULES_FLAG', and to 0 if you don't. */ #undef HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG +/* Define to 1 if you have the declaration of `GCRY_CIPHER_MODE_XTS', and to 0 + if you don't. */ +#undef HAVE_DECL_GCRY_CIPHER_MODE_XTS + +/* Define to 1 if you have the declaration of `json_object_deep_copy', and to + 0 if you don't. */ +#undef HAVE_DECL_JSON_OBJECT_DEEP_COPY + +/* Define to 1 if you have the declaration of `json_object_object_add_ex', and + to 0 if you don't. */ +#undef HAVE_DECL_JSON_OBJECT_OBJECT_ADD_EX + /* Define to 1 if you have the declaration of `NSS_GetVersion', and to 0 if you don't. */ #undef HAVE_DECL_NSS_GETVERSION +/* Define to 1 if you have the declaration of `O_CLOEXEC', and to 0 if you + don't. */ +#undef HAVE_DECL_O_CLOEXEC + /* Define to 1 if you have the declaration of `strerror_r', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR_R @@ -124,6 +238,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H +/* Define to 1 if you have the `explicit_bzero' function. */ +#undef HAVE_EXPLICIT_BZERO + /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H @@ -133,12 +250,15 @@ /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT -/* Define if you have the iconv() function. */ +/* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if the system has the type `key_serial_t'. */ +#undef HAVE_KEY_SERIAL_T + /* Define to 1 if you have the `devmapper' library (-ldevmapper). */ #undef HAVE_LIBDEVMAPPER @@ -163,6 +283,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_IF_ALG_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_KEYCTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H @@ -178,6 +301,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETTLE_SHA_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETTLE_VERSION_H + +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN @@ -210,9 +339,15 @@ */ #undef HAVE_SYS_NDIR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSMACROS_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H @@ -222,10 +357,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UUID_UUID_H -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Enable kernel keyring service support */ +#undef KERNEL_KEYRING + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR +/* Defined to 0 if not provided */ +#undef O_CLOEXEC + /* Name of package */ #undef PACKAGE @@ -247,12 +390,18 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* passwdqc library config file */ +#undef PASSWDQC_CONFIG_FILE + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if strerror_r returns char *. */ #undef STRERROR_R_CHAR_P +/* Use internal Argon2 */ +#undef USE_INTERNAL_ARGON2 + /* Use internal PBKDF2 */ #undef USE_INTERNAL_PBKDF2 @@ -325,3 +474,17 @@ /* Define to `long int' if does not define. */ #undef off_t + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#undef restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif diff --git a/config.rpath b/config.rpath index c492a93..c38b914 100755 --- a/config.rpath +++ b/config.rpath @@ -2,7 +2,7 @@ # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # -# Copyright 1996-2006 Free Software Foundation, Inc. +# Copyright 1996-2013 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # @@ -25,7 +25,7 @@ # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so @@ -47,7 +47,7 @@ for cc_temp in $CC""; do done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` -# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. +# Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then @@ -57,14 +57,7 @@ else aix*) wl='-Wl,' ;; - darwin*) - case $cc_basename in - xlc*) - wl='-Wl,' - ;; - esac - ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' @@ -72,24 +65,37 @@ else irix5* | irix6* | nonstopux*) wl='-Wl,' ;; - newsos6) - ;; - linux*) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in - icc* | ecc*) + ecc*) wl='-Wl,' ;; - pgcc | pgf77 | pgf90) + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; *Sun\ C*) wl='-Wl,' ;; @@ -97,22 +103,36 @@ else ;; esac ;; + newsos6) + ;; + *nto* | *qnx*) + ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; - sco3.2v5*) + rdos*) ;; solaris*) - wl='-Wl,' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac ;; sunos4*) wl='-Qoption ld ' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; unicos*) wl='-Wl,' ;; @@ -121,7 +141,7 @@ else esac fi -# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= @@ -129,7 +149,7 @@ hardcode_direct=no hardcode_minus_L=no case "$host_os" in - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. @@ -155,22 +175,21 @@ if test "$with_gnu_ld" = yes; then # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in - aix3* | aix4* | aix5*) + aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we cannot use - # them. - ld_shlibs=no + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then @@ -179,7 +198,7 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' @@ -189,11 +208,13 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - interix3*) + haiku*) + ;; + interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; - linux*) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else @@ -251,7 +272,7 @@ else hardcode_direct=unsupported fi ;; - aix4* | aix5*) + aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -261,7 +282,7 @@ else # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -280,7 +301,7 @@ else strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - hardcode_direct=yes + : else # We have old collect2 hardcode_direct=unsupported @@ -316,14 +337,18 @@ else fi ;; amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac ;; bsdi[45]*) ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is @@ -333,24 +358,15 @@ else ;; darwin* | rhapsody*) hardcode_direct=no - if test "$GCC" = yes ; then + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then : else - case $cc_basename in - xlc*) - ;; - *) - ld_shlibs=no - ;; - esac + ld_shlibs=no fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; - freebsd1*) - ld_shlibs=no - ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -359,7 +375,7 @@ else hardcode_direct=yes hardcode_minus_L=yes ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; @@ -411,19 +427,25 @@ else hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; + *nto* | *qnx*) + ;; openbsd*) - hardcode_direct=yes - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi else - case "$host_os" in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + ld_shlibs=no fi ;; os2*) @@ -471,7 +493,7 @@ else ld_shlibs=yes fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' @@ -487,34 +509,58 @@ else fi # Check dynamic linker characteristics -# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) + library_names_spec='$libname.a' ;; - aix4* | aix5*) + aix[4-9]*) + library_names_spec='$libname$shrext' ;; amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac ;; beos*) + library_names_spec='$libname$shrext' ;; bsdi[45]*) + library_names_spec='$libname$shrext' ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib + library_names_spec='$libname$shrext' ;; dgux*) - ;; - freebsd1*) - ;; - kfreebsd*-gnu) + library_names_spec='$libname$shrext' ;; freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac ;; gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in @@ -528,10 +574,13 @@ case "$host_os" in shrext=.sl ;; esac + library_names_spec='$libname$shrext' ;; - interix3*) + interix[3-9]*) + library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= @@ -548,41 +597,62 @@ case "$host_os" in ;; linux*oldld* | linux*aout* | linux*coff*) ;; - linux*) + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' ;; knetbsd*-gnu) + library_names_spec='$libname$shrext' ;; netbsd*) + library_names_spec='$libname$shrext' ;; newsos6) + library_names_spec='$libname$shrext' ;; - nto-qnx*) + *nto* | *qnx*) + library_names_spec='$libname$shrext' ;; openbsd*) + library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll + library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) ;; solaris*) + library_names_spec='$libname$shrext' ;; sunos4*) + library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' ;; sysv4*MP*) + library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' ;; uts4*) + library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -25,7 +25,7 @@ timestamp='2014-09-11' # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -33,7 +33,7 @@ timestamp='2014-09-11' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,12 +53,11 @@ timestamp='2014-09-11' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -68,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -95,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -113,24 +112,24 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -179,44 +178,44 @@ case $os in ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -228,10 +227,7 @@ case $os in os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -255,15 +251,16 @@ case $basic_machine in | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -299,13 +296,14 @@ case $basic_machine in | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -313,7 +311,8 @@ case $basic_machine in | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ + | visium \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -327,11 +326,14 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -360,7 +362,7 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -372,17 +374,18 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -423,13 +426,15 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -437,6 +442,8 @@ case $basic_machine in | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -450,7 +457,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -484,7 +491,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -513,6 +520,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -526,7 +536,7 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -534,13 +544,13 @@ case $basic_machine in os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -629,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -722,9 +740,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -737,26 +752,26 @@ case $basic_machine in basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -774,17 +789,17 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -816,10 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -838,7 +853,7 @@ case $basic_machine in os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -880,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -925,6 +940,12 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -957,7 +978,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -973,7 +994,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -988,16 +1009,16 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -1007,23 +1028,23 @@ case $basic_machine in ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1077,17 +1098,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1106,7 +1120,7 @@ case $basic_machine in os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1228,6 +1242,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1236,20 +1253,12 @@ case $basic_machine in basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1278,10 +1287,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1291,9 +1296,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1313,7 +1315,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1321,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1335,8 +1337,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1347,45 +1349,48 @@ case $os in -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1402,12 +1407,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1416,10 +1421,10 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1430,12 +1435,6 @@ case $os in -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1460,7 +1459,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1482,7 +1481,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1497,32 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1612,12 +1617,12 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1657,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1672,9 +1677,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1784,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure b/configure index 0067979..145be42 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for cryptsetup 1.6.7. +# Generated by GNU Autoconf 2.69 for cryptsetup 2.3.3. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='cryptsetup' PACKAGE_TARNAME='cryptsetup' -PACKAGE_VERSION='1.6.7' -PACKAGE_STRING='cryptsetup 1.6.7' +PACKAGE_VERSION='2.3.3' +PACKAGE_STRING='cryptsetup 2.3.3' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -630,31 +630,40 @@ ac_includes_default="\ # include #endif" +gt_needs= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -PYTHON_CRYPTSETUP_FALSE -PYTHON_CRYPTSETUP_TRUE -PYTHON_LIBS -PYTHON_INCLUDES -pkgpyexecdir -pyexecdir -pkgpythondir -pythondir -PYTHON_PLATFORM -PYTHON_EXEC_PREFIX -PYTHON_PREFIX -PYTHON_VERSION -PYTHON +DEFAULT_LUKS2_LOCK_DIR_PERMS +DEFAULT_LUKS2_LOCK_PATH +CRYPTSETUP_TMPFILE_FALSE +CRYPTSETUP_TMPFILE_TRUE +DEFAULT_TMPFILESDIR LIBCRYPTSETUP_VERSION_INFO LIBCRYPTSETUP_VERSION CRYPTO_STATIC_LIBS CRYPTO_LIBS CRYPTO_CFLAGS +PASSWDQC_LIBS PWQUALITY_STATIC_LIBS +systemd_tmpfilesdir DEVMAPPER_STATIC_LIBS DEVMAPPER_STATIC_CFLAGS +HAVE_BLKID_STEP_BACK_FALSE +HAVE_BLKID_STEP_BACK_TRUE +HAVE_BLKID_WIPE_FALSE +HAVE_BLKID_WIPE_TRUE +HAVE_BLKID_FALSE +HAVE_BLKID_TRUE +BLKID_LIBS +BLKID_CFLAGS +CRYPTO_INTERNAL_SSE_ARGON2_FALSE +CRYPTO_INTERNAL_SSE_ARGON2_TRUE +CRYPTO_INTERNAL_ARGON2_FALSE +CRYPTO_INTERNAL_ARGON2_TRUE +LIBARGON2_LIBS +LIBARGON2_CFLAGS CRYPTO_INTERNAL_PBKDF2_FALSE CRYPTO_INTERNAL_PBKDF2_TRUE CRYPTO_BACKEND_NETTLE_FALSE @@ -676,12 +685,18 @@ OPENSSL_CFLAGS LIBGCRYPT_LIBS LIBGCRYPT_CFLAGS LIBGCRYPT_CONFIG +JSON_C_LIBS +JSON_C_CFLAGS DEVMAPPER_LIBS DEVMAPPER_CFLAGS +INTEGRITYSETUP_FALSE +INTEGRITYSETUP_TRUE REENCRYPT_FALSE REENCRYPT_TRUE VERITYSETUP_FALSE VERITYSETUP_TRUE +CRYPTSETUP_FALSE +CRYPTSETUP_TRUE STATIC_TOOLS_FALSE STATIC_TOOLS_TRUE PWQUALITY_LIBS @@ -691,9 +706,8 @@ POSUB LTLIBINTL LIBINTL INTLLIBS -LTLIBICONV -LIBICONV INTL_MACOSX_LIBS +XGETTEXT_EXTRA_OPTIONS MSGMERGE XGETTEXT_015 XGETTEXT @@ -701,11 +715,17 @@ GMSGFMT_015 MSGFMT_015 GMSGFMT MSGFMT +GETTEXT_MACRO_VERSION USE_NLS UUID_LIBS +KERNEL_KEYRING_FALSE +KERNEL_KEYRING_TRUE +LTLIBICONV +LIBICONV PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG +LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO @@ -735,7 +755,6 @@ am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -799,6 +818,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -817,7 +837,8 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -827,28 +848,35 @@ enable_static enable_shared with_pic enable_fast_install +with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock -enable_largefile -enable_nls enable_rpath with_libiconv_prefix +enable_keyring +enable_largefile +enable_nls with_libintl_prefix enable_fips enable_pwquality +enable_passwdqc enable_static_cryptsetup +enable_cryptsetup enable_veritysetup enable_cryptsetup_reencrypt +enable_integritysetup enable_selinux enable_udev with_crypto_backend enable_kernel_crypto enable_gcrypt_pbkdf2 with_libgcrypt_prefix +enable_internal_argon2 +enable_libargon2 +enable_internal_sse_argon2 +enable_blkid enable_dev_random -enable_python -with_python_version with_plain_hash with_plain_cipher with_plain_mode @@ -857,7 +885,14 @@ with_luks1_hash with_luks1_cipher with_luks1_mode with_luks1_keybits +enable_luks_adjust_xts_keysize +with_luks2_pbkdf with_luks1_iter_time +with_luks2_iter_time +with_luks2_memory_kb +with_luks2_parallel_threads +with_luks2_keyslot_cipher +with_luks2_keyslot_keybits with_loopaes_cipher with_loopaes_keybits with_keyfile_size_maxkb @@ -866,6 +901,11 @@ with_verity_hash with_verity_data_block with_verity_hash_block with_verity_salt_size +with_verity_fec_roots +with_tmpfilesdir +with_luks2_lock_path +with_luks2_lock_dir_perms +with_default_luks_format ' ac_precious_vars='build_alias host_alias @@ -876,6 +916,7 @@ LDFLAGS LIBS CPPFLAGS CPP +LT_SYS_LIBRARY_PATH PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR @@ -883,15 +924,21 @@ PWQUALITY_CFLAGS PWQUALITY_LIBS DEVMAPPER_CFLAGS DEVMAPPER_LIBS +JSON_C_CFLAGS +JSON_C_LIBS OPENSSL_CFLAGS OPENSSL_LIBS OPENSSL_STATIC_CFLAGS OPENSSL_STATIC_LIBS NSS_CFLAGS NSS_LIBS +LIBARGON2_CFLAGS +LIBARGON2_LIBS +BLKID_CFLAGS +BLKID_LIBS DEVMAPPER_STATIC_CFLAGS DEVMAPPER_STATIC_LIBS -PYTHON' +systemd_tmpfilesdir' # Initialize some variables set by options. @@ -930,6 +977,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1182,6 +1230,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1319,7 +1376,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1432,7 +1489,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures cryptsetup 1.6.7 to adapt to many kinds of systems. +\`configure' configures cryptsetup 2.3.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1472,6 +1529,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1502,7 +1560,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of cryptsetup 1.6.7:";; + short | recursive ) echo "Configuration of cryptsetup 2.3.3:";; esac cat <<\_ACEOF @@ -1521,57 +1579,92 @@ Optional Features: --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) + --disable-rpath do not hardcode runtime library paths + --disable-keyring disable kernel keyring support and builtin kernel + keyring token --disable-largefile omit support for large files --disable-nls do not use Native Language Support - --disable-rpath do not hardcode runtime library paths --enable-fips enable FIPS mode restrictions - --enable-pwquality enable password quality checking + --enable-pwquality enable password quality checking using pwquality + library + --enable-passwdqc[=CONFIG_PATH] + enable password quality checking using passwdqc + library (optionally with CONFIG_PATH) --enable-static-cryptsetup - enable build of static cryptsetup binary + enable build of static version of tools + --disable-cryptsetup disable cryptsetup support --disable-veritysetup disable veritysetup support - --enable-cryptsetup-reencrypt - enable cryptsetup-reencrypt tool + --disable-cryptsetup-reencrypt + disable cryptsetup-reencrypt tool + --disable-integritysetup + disable integritysetup support --disable-selinux disable selinux support [default=auto] --disable-udev disable udev support --disable-kernel_crypto disable kernel userspace crypto (no benchmark and tcrypt) - --enable-gcrypt-pbkdf2 force enable internal gcrypt PBKDF2 - --enable-dev-random use blocking /dev/random by default for key - generator (otherwise use /dev/urandom) - --enable-python enable Python bindings + --enable-gcrypt-pbkdf2 force enable internal gcrypt PBKDF2 + --disable-internal-argon2 + disable internal implementation of Argon2 PBKDF + --enable-libargon2 enable external libargon2 (PHC) library (disables + internal bundled version) + --enable-internal-sse-argon2 + enable internal SSE implementation of Argon2 PBKDF + --disable-blkid disable use of blkid for device signature detection + and wiping + --enable-dev-random use /dev/random by default for key generation + (otherwise use /dev/urandom) + --disable-luks-adjust-xts-keysize + XTS mode requires two keys, double default LUKS + keysize if needed Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot=DIR Search for dependent libraries within DIR - (or the compiler's sysroot if not specified). - --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir --with-crypto_backend=BACKEND crypto backend (gcrypt/openssl/nss/kernel/nettle) - [gcrypt] + [openssl] --with-libgcrypt-prefix=PFX prefix where LIBGCRYPT is installed (optional) - --with-python_version=VERSION - required Python version [2.6] --with-plain-hash default password hashing function for plain mode [ripemd160] --with-plain-cipher default cipher for plain mode [aes] --with-plain-mode default cipher mode for plain mode [cbc-essiv:sha256] --with-plain-keybits default key length in bits for plain mode [256] - --with-luks1-hash default hash function for LUKS1 header [sha1] + --with-luks1-hash default hash function for LUKS1 header [sha256] --with-luks1-cipher default cipher for LUKS1 [aes] --with-luks1-mode default cipher mode for LUKS1 [xts-plain64] --with-luks1-keybits default key length in bits for LUKS1 [256] + --with-luks2-pbkdf default Default PBKDF algorithm (pbkdf2 or + argon2i/argon2id) for LUKS2 [argon2i] --with-luks1-iter-time default PBKDF2 iteration time for LUKS1 (in ms) - [1000] + [2000] + --with-luks2-iter-time default Argon2 PBKDF iteration time for LUKS2 (in + ms) [2000] + --with-luks2-memory-kb default Argon2 PBKDF memory cost for LUKS2 (in kB) + [1048576] + --with-luks2-parallel-threads + default Argon2 PBKDF max parallel cost for LUKS2 (if + CPUs available) [4] + --with-luks2-keyslot-cipher + default fallback cipher for LUKS2 keyslot (if data + encryption is incompatible) [aes-xts-plain64] + --with-luks2-keyslot-keybits + default fallback key size for LUKS2 keyslot (if data + encryption is incompatible) [512] --with-loopaes-cipher default cipher for loop-AES mode [aes] --with-loopaes-keybits default key length in bits for loop-AES mode [256] --with-keyfile-size-maxkb @@ -1584,6 +1677,16 @@ Optional Packages: --with-verity-hash-block default hash block size for verity mode [4096] --with-verity-salt-size default salt size for verity mode [32] + --with-verity-fec-roots default parity bytes for verity FEC [2] + --with-tmpfilesdir default override default path to directory with + systemd temporary files [] + --with-luks2-lock-path default path to directory for LUKSv2 locks + [/run/cryptsetup] + --with-luks2-lock-dir-perms + default default luks2 locking directory permissions + [0700] + --with-default-luks-format=FORMAT + default LUKS format version (LUKS1/LUKS2) [LUKS2] Some influential environment variables: CC C compiler command @@ -1594,6 +1697,8 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path @@ -1607,6 +1712,9 @@ Some influential environment variables: C compiler flags for DEVMAPPER, overriding pkg-config DEVMAPPER_LIBS linker flags for DEVMAPPER, overriding pkg-config + JSON_C_CFLAGS + C compiler flags for JSON_C, overriding pkg-config + JSON_C_LIBS linker flags for JSON_C, overriding pkg-config OPENSSL_CFLAGS C compiler flags for OPENSSL, overriding pkg-config OPENSSL_LIBS @@ -1617,11 +1725,19 @@ Some influential environment variables: linker flags for OPENSSL_STATIC, overriding pkg-config NSS_CFLAGS C compiler flags for NSS, overriding pkg-config NSS_LIBS linker flags for NSS, overriding pkg-config + LIBARGON2_CFLAGS + C compiler flags for LIBARGON2, overriding pkg-config + LIBARGON2_LIBS + linker flags for LIBARGON2, overriding pkg-config + BLKID_CFLAGS + C compiler flags for BLKID, overriding pkg-config + BLKID_LIBS linker flags for BLKID, overriding pkg-config DEVMAPPER_STATIC_CFLAGS C compiler flags for DEVMAPPER_STATIC, overriding pkg-config DEVMAPPER_STATIC_LIBS linker flags for DEVMAPPER_STATIC, overriding pkg-config - PYTHON the Python interpreter + systemd_tmpfilesdir + value of tmpfilesdir for systemd, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1689,7 +1805,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -cryptsetup configure 1.6.7 +cryptsetup configure 2.3.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2051,6 +2167,52 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -2104,57 +2266,11 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type - -# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES -# --------------------------------------------- -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. -ac_fn_c_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - as_decl_name=`echo $2|sed 's/ *(.*//'` - as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by cryptsetup $as_me 1.6.7, which was +It was created by cryptsetup $as_me 2.3.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2434,6 +2550,7 @@ $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi +gt_needs="$gt_needs need-ngettext" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -2504,7 +2621,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-) -LIBCRYPTSETUP_VERSION_INFO=11:0:7 +LIBCRYPTSETUP_VERSION_INFO=18:0:6 # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : @@ -2555,8 +2672,8 @@ ac_config_headers="$ac_config_headers config.h:config.h.in" # http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html # For old automake use this -#AM_INIT_AUTOMAKE(dist-xz) -am__api_version='1.14' +#AM_INIT_AUTOMAKE(dist-xz subdir-objects) +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2777,7 +2894,7 @@ else $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -3032,7 +3149,7 @@ fi # Define the identity of the package. PACKAGE='cryptsetup' - VERSION='1.6.7' + VERSION='2.3.3' cat >>confdefs.h <<_ACEOF @@ -3062,12 +3179,12 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -3114,7 +3231,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -3206,45 +3323,45 @@ DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : @@ -5605,14 +5722,14 @@ if test "${enable_static+set}" = set; then : *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -5635,8 +5752,8 @@ esac -macro_version='2.4.2' -macro_revision='1.3337' +macro_version='2.4.6' +macro_revision='2.4.6' @@ -5650,7 +5767,7 @@ macro_revision='1.3337' -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. @@ -5699,7 +5816,7 @@ func_echo_all () $ECHO "" } -case "$ECHO" in +case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 @@ -5892,19 +6009,19 @@ test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -5918,7 +6035,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -5929,7 +6046,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else @@ -5940,32 +6057,32 @@ if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } @@ -6008,33 +6125,38 @@ if ${lt_cv_path_NM+:} false; then : else if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -6045,15 +6167,15 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : @@ -6159,9 +6281,9 @@ esac fi fi - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -6169,8 +6291,8 @@ fi esac fi - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -6221,7 +6343,7 @@ if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -6261,7 +6383,7 @@ else lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -6312,22 +6434,22 @@ else *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -6345,7 +6467,7 @@ else fi -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else @@ -6363,30 +6485,6 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else @@ -6509,13 +6607,13 @@ esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) - if test "$GCC" != yes; then + if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi @@ -6643,13 +6741,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) @@ -6676,8 +6774,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -6773,8 +6870,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' @@ -6827,6 +6924,9 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac fi @@ -6984,8 +7084,8 @@ else case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -6997,7 +7097,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac @@ -7114,7 +7214,7 @@ esac fi : ${AR=ar} -: ${AR_FLAGS=cru} +: ${AR_FLAGS=cr} @@ -7151,7 +7251,7 @@ if ac_fn_c_try_compile "$LINENO"; then : ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 @@ -7159,7 +7259,7 @@ if ac_fn_c_try_compile "$LINENO"; then : ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi @@ -7172,7 +7272,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -7389,7 +7489,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -7479,7 +7579,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; @@ -7512,14 +7612,44 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -7537,21 +7667,24 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -7582,11 +7715,8 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "$nlist"; then + $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 + if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -7599,11 +7729,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else @@ -7629,7 +7759,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -7649,13 +7779,13 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then + test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -7676,7 +7806,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -7729,6 +7859,16 @@ fi + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } @@ -7741,9 +7881,9 @@ fi lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -7753,8 +7893,8 @@ case ${with_sysroot} in #( no|'') ;; #( *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 -$as_echo "${with_sysroot}" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac @@ -7766,18 +7906,99 @@ $as_echo "${lt_sysroot:-no}" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7786,24 +8007,25 @@ ia64-*-hpux*) test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -7832,9 +8054,50 @@ ia64-*-hpux*) rm -rf conftest* ;; +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7857,10 +8120,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ;; esac ;; - powerpc64le-*) + powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*) + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -7879,10 +8142,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*) + powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*) + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -7900,7 +8163,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } @@ -7940,13 +8203,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7958,7 +8222,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -7967,7 +8231,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -7983,7 +8247,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. @@ -8094,7 +8358,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test "x$lt_cv_path_mainfest_tool" != xyes; then +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi @@ -8597,7 +8861,7 @@ if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -8615,7 +8879,7 @@ else cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -8654,7 +8918,7 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 @@ -8671,8 +8935,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cru libconftest.a conftest.o" >&5 - $AR cru libconftest.a conftest.o 2>&5 + echo "$AR cr libconftest.a conftest.o" >&5 + $AR cr libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF @@ -8683,7 +8947,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 @@ -8696,32 +8960,32 @@ fi $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -8729,6 +8993,41 @@ $as_echo "$lt_cv_ld_force_load" >&6; } ;; esac +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default @@ -8765,14 +9064,14 @@ if test "${enable_shared+set}" = set; then : *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8797,14 +9096,14 @@ if test "${with_pic+set}" = set; then : *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8812,8 +9111,6 @@ else fi -test -z "$pic_mode" && pic_mode=default - @@ -8829,14 +9126,14 @@ if test "${enable_fast_install+set}" = set; then : *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8850,11 +9147,63 @@ fi + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -8903,7 +9252,7 @@ test -z "$LN_S" && LN_S="ln -s" -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi @@ -8942,7 +9291,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -8953,14 +9302,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -8969,15 +9318,8 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +func_cc_basename $compiler +cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it @@ -8992,22 +9334,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -9030,13 +9372,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -9058,22 +9400,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -9096,13 +9438,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -9123,7 +9465,7 @@ esac # Use C for the default configuration in the libtool script -lt_save_CC="$CC" +lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -9185,7 +9527,7 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; @@ -9201,7 +9543,7 @@ else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -9231,7 +9573,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -9249,17 +9591,18 @@ lt_prog_compiler_pic= lt_prog_compiler_static= - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi + lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -9270,8 +9613,8 @@ lt_prog_compiler_static= ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -9287,6 +9630,11 @@ lt_prog_compiler_static= # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -9357,7 +9705,7 @@ lt_prog_compiler_static= case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -9365,10 +9713,29 @@ lt_prog_compiler_static= fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -9384,7 +9751,7 @@ lt_prog_compiler_static= ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' + lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -9395,12 +9762,18 @@ lt_prog_compiler_static= linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; + # flang / f18. f95 an alias for gfortran or flang on Debian + flang* | f18* | f95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) @@ -9420,6 +9793,12 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -9517,7 +9896,7 @@ lt_prog_compiler_static= ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -9546,7 +9925,7 @@ lt_prog_compiler_static= fi case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -9578,7 +9957,7 @@ else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -9608,7 +9987,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -9640,7 +10019,7 @@ if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -9659,13 +10038,13 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } -if test x"$lt_cv_prog_compiler_static_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= @@ -9785,8 +10164,8 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -9798,9 +10177,9 @@ $as_echo_n "checking if we can lock with hard links... " >&6; } ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -9843,9 +10222,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -9860,7 +10239,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test "$GCC" != yes; then + if test yes != "$GCC"; then with_gnu_ld=no fi ;; @@ -9868,7 +10247,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) @@ -9881,7 +10260,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -9903,24 +10282,24 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9933,7 +10312,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 @@ -9952,7 +10331,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9968,7 +10347,7 @@ _LT_EOF allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -9978,7 +10357,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='${wl}--export-all-symbols' + export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes @@ -9986,61 +10365,89 @@ _LT_EOF exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -10051,42 +10458,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -10100,8 +10512,8 @@ _LT_EOF archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -10119,8 +10531,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -10132,7 +10544,7 @@ _LT_EOF ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -10147,9 +10559,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -10166,15 +10578,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test "$ld_shlibs" = no; then + if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -10190,7 +10602,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -10198,34 +10610,57 @@ _LT_EOF ;; aix[4-9]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -10244,13 +10679,21 @@ _LT_EOF hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='${wl}-f,' + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -10269,36 +10712,42 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi - link_all_deplibs=no + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='${wl}-bexpall' + export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -10333,7 +10782,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -10341,17 +10790,17 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -10386,7 +10835,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -10394,21 +10843,33 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -10417,7 +10878,7 @@ fi case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -10447,16 +10908,17 @@ fi # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes @@ -10465,18 +10927,18 @@ fi # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -10485,7 +10947,7 @@ fi # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -10504,24 +10966,24 @@ fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" + allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -10563,33 +11025,33 @@ fi ;; hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -10597,25 +11059,25 @@ fi ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) @@ -10627,7 +11089,7 @@ if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -10646,14 +11108,14 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } -if test x"$lt_cv_prog_compiler__b" = xyes; then - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi @@ -10661,8 +11123,8 @@ fi ;; esac fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -10673,7 +11135,7 @@ fi *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -10684,8 +11146,8 @@ fi ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. @@ -10695,8 +11157,8 @@ $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " > if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } @@ -10708,24 +11170,35 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test "$lt_cv_irix_exported_symbol" = yes; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi + link_all_deplibs=no else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -10740,7 +11213,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -10748,27 +11221,19 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no @@ -10779,33 +11244,53 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes ;; osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -10816,24 +11301,24 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris*) no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -10843,11 +11328,11 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -10857,10 +11342,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -10909,43 +11394,43 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' + no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' + export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -10960,10 +11445,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' + export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi @@ -10971,7 +11456,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no +test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -10997,7 +11482,7 @@ x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -11212,14 +11697,14 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -11235,28 +11720,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -11270,7 +11762,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([A-Za-z]:\),\1,g'` ;; + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -11279,7 +11771,7 @@ fi library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -11296,14 +11788,16 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown + + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) @@ -11311,41 +11805,91 @@ aix[4-9]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -11355,18 +11899,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -11374,8 +11918,8 @@ beos*) bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -11387,7 +11931,7 @@ bsdi[45]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -11396,8 +11940,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -11413,17 +11957,17 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' @@ -11432,8 +11976,8 @@ cygwin* | mingw* | pw32* | cegcc*) *,cl*) # Native MSVC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -11460,7 +12004,7 @@ cygwin* | mingw* | pw32* | cegcc*) sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -11473,8 +12017,8 @@ cygwin* | mingw* | pw32* | cegcc*) esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -11487,7 +12031,7 @@ cygwin* | mingw* | pw32* | cegcc*) *) # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -11500,8 +12044,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -11514,8 +12058,8 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11533,12 +12077,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -11568,10 +12113,10 @@ haiku*) need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -11589,14 +12134,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -11604,8 +12150,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -11614,8 +12160,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -11628,8 +12174,8 @@ interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11640,7 +12186,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -11648,8 +12194,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -11668,8 +12214,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -11678,13 +12224,33 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11728,7 +12294,12 @@ fi # before this can be enabled. hardcode_into_libs=yes - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -11760,12 +12331,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -11775,7 +12346,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -11784,58 +12355,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no else - shlibpath_overrides_runpath=yes + need_version=yes fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -11846,8 +12427,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -11857,11 +12438,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -11869,8 +12450,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -11891,24 +12472,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -11926,7 +12507,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -11934,8 +12515,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11945,20 +12526,35 @@ uts4*) esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + @@ -12055,15 +12651,15 @@ $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then + test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && + if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -12078,12 +12674,12 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -12093,7 +12689,7 @@ fi - if test "x$enable_dlopen" != xyes; then + if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -12103,23 +12699,23 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : @@ -12157,10 +12753,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else - lt_cv_dlopen="dyld" + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -12168,10 +12764,18 @@ fi ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" + lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } @@ -12210,11 +12814,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -12253,7 +12857,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } @@ -12292,7 +12896,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } @@ -12331,7 +12935,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi @@ -12352,21 +12956,21 @@ fi ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 @@ -12374,7 +12978,7 @@ $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -12421,9 +13025,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -12453,7 +13057,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -12473,14 +13077,14 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -12527,9 +13131,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -12559,7 +13163,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -12580,9 +13184,9 @@ fi $as_echo "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -12626,7 +13230,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP" ; then + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -12654,7 +13258,7 @@ fi - # Report which library types will actually be built + # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 @@ -12662,13 +13266,13 @@ $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -12676,8 +13280,12 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -12687,7 +13295,7 @@ $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -12701,7 +13309,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC="$lt_save_CC" +CC=$lt_save_CC @@ -12846,899 +13454,1226 @@ $as_echo "no" >&6; } fi fi -ac_header_dirent=no -for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do - as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 -$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } -if eval \${$as_ac_Header+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include <$ac_hdr> - -int -main () -{ -if ((DIR *) 0) -return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_ac_Header=yes" -else - eval "$as_ac_Header=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$as_ac_Header - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 -_ACEOF - -ac_header_dirent=$ac_hdr; break -fi - -done -# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. -if test $ac_header_dirent = dirent.h; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 -$as_echo_n "checking for library containing opendir... " >&6; } -if ${ac_cv_search_opendir+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opendir (); -int -main () -{ -return opendir (); - ; - return 0; -} -_ACEOF -for ac_lib in '' dir; do - if test -z "$ac_lib"; then - ac_res="none required" + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" + acl_final_prefix="$prefix" fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_opendir=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_opendir+:} false; then : - break -fi -done -if ${ac_cv_search_opendir+:} false; then : + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else - ac_cv_search_opendir=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS + with_gnu_ld=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 -$as_echo "$ac_cv_search_opendir" >&6; } -ac_res=$ac_cv_search_opendir -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 -$as_echo_n "checking for library containing opendir... " >&6; } -if ${ac_cv_search_opendir+:} false; then : +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opendir (); -int -main () -{ -return opendir (); - ; - return 0; -} -_ACEOF -for ac_lib in '' x; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_opendir=$ac_res + if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } else - ac_cv_search_opendir=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 -$as_echo "$ac_cv_search_opendir" >&6; } -ac_res=$ac_cv_search_opendir -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_prog_gnu_ld" >&5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include -int -main () -{ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : else - ac_cv_header_stdc=no + enable_rpath=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : -else - ac_cv_header_stdc=no -fi -rm -f conftest* -fi -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 +$as_echo_n "checking for 64-bit host... " >&6; } +if ${gl_cv_solaris_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +#ifdef _LP64 +sixtyfour bits +#endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - + $EGREP "sixtyfour bits" >/dev/null 2>&1; then : + gl_cv_solaris_64bit=yes else - ac_cv_header_stdc=no + gl_cv_solaris_64bit=no fi rm -f conftest* + fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 +$as_echo "$gl_cv_solaris_64bit" >&6; } + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h -fi -for ac_header in fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \ - ctype.h unistd.h locale.h byteswap.h endian.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF -fi -done -for ac_header in uuid/uuid.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" -if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_UUID_UUID_H 1 -_ACEOF -else - as_fn_error $? "You need the uuid library." "$LINENO" 5 -fi + use_additional=yes -done + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" -ac_fn_c_check_header_mongrel "$LINENO" "libdevmapper.h" "ac_cv_header_libdevmapper_h" "$ac_includes_default" -if test "x$ac_cv_header_libdevmapper_h" = xyes; then : + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" -else - as_fn_error $? "You need the device-mapper library." "$LINENO" 5 -fi + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then -saved_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_clear in -luuid" >&5 -$as_echo_n "checking for uuid_clear in -luuid... " >&6; } -if ${ac_cv_lib_uuid_uuid_clear+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-luuid $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char uuid_clear (); -int -main () -{ -return uuid_clear (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_uuid_uuid_clear=yes -else - ac_cv_lib_uuid_uuid_clear=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_clear" >&5 -$as_echo "$ac_cv_lib_uuid_uuid_clear" >&6; } -if test "x$ac_cv_lib_uuid_uuid_clear" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBUUID 1 -_ACEOF + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" - LIBS="-luuid $LIBS" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi -else - as_fn_error $? "You need the uuid library." "$LINENO" 5 fi -UUID_LIBS=$LIBS + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + HAVE_LIBICONV= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do -LIBS=$saved_LIBS + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 -$as_echo_n "checking for library containing clock_gettime... " >&6; } -if ${ac_cv_search_clock_gettime+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char clock_gettime (); -int -main () -{ -return clock_gettime (); - ; - return 0; -} -_ACEOF -for ac_lib in '' rt posix4; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_clock_gettime=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_clock_gettime+:} false; then : - break -fi -done -if ${ac_cv_search_clock_gettime+:} false; then : + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" -else - ac_cv_search_clock_gettime=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 -$as_echo "$ac_cv_search_clock_gettime" >&6; } -ac_res=$ac_cv_search_clock_gettime -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do -fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" -for ac_func in posix_memalign clock_gettime -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do -fi -done + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do -if test "x$enable_largefile" = "xno" ; then - as_fn_error $? "Building with --disable-largefile is not supported, it can cause data corruption." "$LINENO" 5 -fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 -$as_echo_n "checking for an ANSI C-conforming const... " >&6; } -if ${ac_cv_c_const+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi -int -main () -{ -#ifndef __cplusplus - /* Ultrix mips cc rejects this sort of thing. */ - typedef int charset[2]; - const charset cs = { 0, 0 }; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *pcpcc; - char **ppc; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - pcpcc = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++pcpcc; - ppc = (char**) pcpcc; - pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this sort of thing. */ - char tx; - char *t = &tx; - char const *s = 0 ? (char *) 0 : (char const *) 0; - *t++ = 0; - if (s) return 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; } bx; - struct s *b = &bx; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - if (!foo) return 0; - } - return !cs[0] && !zero.x; -#endif - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_const=yes -else - ac_cv_c_const=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 -$as_echo "$ac_cv_c_const" >&6; } -if test $ac_cv_c_const = no; then -$as_echo "#define const /**/" >>confdefs.h -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -$as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if ${ac_cv_c_bigendian+:} false; then : + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_c_bigendian=unknown - # See if we're dealing with a universal compiler. + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#ifndef __APPLE_CC__ - not a universal capable compiler - #endif - typedef int dummy; -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - # Check for potential -arch flags. It is not universal unless - # there are at least two -arch flags with different values. - ac_arch= - ac_prev= - for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do - if test -n "$ac_prev"; then - case $ac_word in - i?86 | x86_64 | ppc | ppc64) - if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then - ac_arch=$ac_word - else - ac_cv_c_bigendian=universal - break - fi - ;; - esac - ac_prev= - elif test "x$ac_word" = "x-arch"; then - ac_prev=arch - fi - done -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test $ac_cv_c_bigendian = unknown; then - # See if sys/param.h defines the BYTE_ORDER macro. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include +#include +#include int main () { -#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ - && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ - && LITTLE_ENDIAN) - bogus endian macros - #endif - +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - #include + +#include +#include int main () { -#if BYTE_ORDER != BIG_ENDIAN - not big endian - #endif - +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" fi - if test $ac_cv_c_bigendian = unknown; then - # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes; then : + + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -int -main () +#include +#include +int main () { -#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) - bogus endian macros - #endif - - ; - return 0; + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to _BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +else + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 +$as_echo_n "checking for iconv declaration... " >&6; } + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif int main () { -#ifndef _BIG_ENDIAN - not big endian - #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes + am_cv_proto_iconv_arg1="" else - ac_cv_c_bigendian=no + am_cv_proto_iconv_arg1="const" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # Compile a test program. - if test "$cross_compiling" = yes; then : - # Try to guess by grepping values from an object file. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -short int ascii_mm[] = - { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - short int ascii_ii[] = - { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; - int use_ascii (int i) { - return ascii_mm[i] + ascii_ii[i]; - } - short int ebcdic_ii[] = - { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - short int ebcdic_mm[] = - { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; - int use_ebcdic (int i) { - return ebcdic_mm[i] + ebcdic_ii[i]; - } - extern int foo; + am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: + $am_cv_proto_iconv" >&5 +$as_echo " + $am_cv_proto_iconv" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + + fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 +$as_echo_n "checking for C/C++ restrict keyword... " >&6; } +if ${ac_cv_c_restrict+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_restrict=no + # The order here caters to the fact that C++ does not require restrict. + for ac_kw in __restrict __restrict__ _Restrict restrict; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +typedef int * int_ptr; + int foo (int_ptr $ac_kw ip) { + return ip[0]; + } int main () { -return use_ascii (foo) == use_ebcdic (foo); +int s[1]; + int * $ac_kw t = s; + t[0] = 0; + return foo(t) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then - ac_cv_c_bigendian=yes - fi - if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi - fi + ac_cv_c_restrict=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_restrict" != no && break + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5 +$as_echo "$ac_cv_c_restrict" >&6; } + + case $ac_cv_c_restrict in + restrict) ;; + no) $as_echo "#define restrict /**/" >>confdefs.h + ;; + *) cat >>confdefs.h <<_ACEOF +#define restrict $ac_cv_c_restrict +_ACEOF + ;; + esac + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_includes_default +#include +#include <$ac_hdr> + int main () { - - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long int l; - char c[sizeof (long int)]; - } u; - u.l = 1; - return u.c[sizeof (long int) - 1] == 1; - +if ((DIR *) 0) +return 0; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_c_bigendian=no +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" else - ac_cv_c_bigendian=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext + eval "$as_ac_Header=no" fi - - fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -$as_echo "$ac_cv_c_bigendian" >&6; } - case $ac_cv_c_bigendian in #( - yes) - $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h -;; #( - no) - ;; #( - universal) - -$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - - ;; #( - *) - as_fn_error $? "unknown endianness - presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; - esac - -ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" -if test "x$ac_cv_type_off_t" = xyes; then : - -else - -cat >>confdefs.h <<_ACEOF -#define off_t long int +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF +ac_header_dirent=$ac_hdr; break fi -# Check whether --enable-largefile was given. -if test "${enable_largefile+set}" = set; then : - enableval=$enable_largefile; -fi - -if test "$enable_largefile" != no; then - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 -$as_echo_n "checking for special C compiler options needed for large files... " >&6; } -if ${ac_cv_sys_largefile_CC+:} false; then : +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_sys_largefile_CC=no - if test "$GCC" != yes; then - ac_save_CC=$CC - while :; do - # IRIX 6.2 and later do not support large files by default, - # so use the C compiler's -n32 option if that helps. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); int main () { - +return opendir (); ; return 0; } _ACEOF - if ac_fn_c_try_compile "$LINENO"; then : +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : break fi -rm -f core conftest.err conftest.$ac_objext - CC="$CC -n32" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_largefile_CC=' -n32'; break +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no fi -rm -f core conftest.err conftest.$ac_objext - break - done - CC=$ac_save_CC - rm -f conftest.$ac_ext - fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 -$as_echo "$ac_cv_sys_largefile_CC" >&6; } - if test "$ac_cv_sys_largefile_CC" != no; then - CC=$CC$ac_cv_sys_largefile_CC - fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 -$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if ${ac_cv_sys_file_offset_bits+:} false; then : +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; -int -main () -{ - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_file_offset_bits=no; break -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#define _FILE_OFFSET_BITS 64 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); int main () { - +return opendir (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_file_offset_bits=64; break -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cv_sys_file_offset_bits=unknown +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : break +fi done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 -$as_echo "$ac_cv_sys_file_offset_bits" >&6; } -case $ac_cv_sys_file_offset_bits in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits -_ACEOF -;; -esac -rm -rf conftest* - if test $ac_cv_sys_file_offset_bits = unknown; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 -$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } -if ${ac_cv_sys_large_files+:} false; then : +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else - while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; +#include +#include +#include +#include + int main () { @@ -13748,868 +14683,1989 @@ main () } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_large_files=no; break + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#define _LARGE_FILES 1 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; -int -main () -{ +#include - ; - return 0; -} _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_large_files=1; break +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cv_sys_large_files=unknown - break -done +rm -f conftest* + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 -$as_echo "$ac_cv_sys_large_files" >&6; } -case $ac_cv_sys_large_files in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _LARGE_FILES $ac_cv_sys_large_files + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + _ACEOF -;; -esac -rm -rf conftest* - fi +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : +else + ac_cv_header_stdc=no +fi +rm -f conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 -$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } -if ${ac_cv_sys_largefile_source+:} false; then : - $as_echo_n "(cached) " >&6 +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : else - while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include /* for off_t */ - #include +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); - ; + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_sys_largefile_source=no; break +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#define _LARGEFILE_SOURCE 1 -#include /* for off_t */ - #include -int -main () -{ -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_sys_largefile_source=1; break +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_cv_sys_largefile_source=unknown - break -done + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 -$as_echo "$ac_cv_sys_largefile_source" >&6; } -case $ac_cv_sys_largefile_source in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source -_ACEOF -;; -esac -rm -rf conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then -# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug -# in glibc 2.1.3, but that breaks too many other things. -# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. -if test $ac_cv_sys_largefile_source != unknown; then +$as_echo "#define STDC_HEADERS 1" >>confdefs.h -$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h +fi + +for ac_header in fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \ + sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -if test $ac_cv_c_compiler_gnu = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 -$as_echo_n "checking whether $CC needs -traditional... " >&6; } -if ${ac_cv_prog_gcc_traditional+:} false; then : - $as_echo_n "(cached) " >&6 +done + +ac_fn_c_check_decl "$LINENO" "O_CLOEXEC" "ac_cv_have_decl_O_CLOEXEC" " +#ifdef HAVE_FCNTL_H +# include +#endif + +" +if test "x$ac_cv_have_decl_O_CLOEXEC" = xyes; then : + ac_have_decl=1 else - ac_pattern="Autoconf.*'x'" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -Autoconf TIOCGETP + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_O_CLOEXEC $ac_have_decl _ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "$ac_pattern" >/dev/null 2>&1; then : - ac_cv_prog_gcc_traditional=yes +if test $ac_have_decl = 1; then : + else - ac_cv_prog_gcc_traditional=no + +$as_echo "#define O_CLOEXEC 0" >>confdefs.h + fi -rm -f conftest* - if test $ac_cv_prog_gcc_traditional = no; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -Autoconf TCGETA +for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 _ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "$ac_pattern" >/dev/null 2>&1; then : - ac_cv_prog_gcc_traditional=yes -fi -rm -f conftest* - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 -$as_echo "$ac_cv_prog_gcc_traditional" >&6; } - if test $ac_cv_prog_gcc_traditional = yes; then - CC="$CC -traditional" - fi +else + as_fn_error $? "You need the uuid library." "$LINENO" 5 fi -ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" -if test "x$ac_cv_have_decl_strerror_r" = xyes; then : - ac_have_decl=1 +done + +ac_fn_c_check_header_mongrel "$LINENO" "libdevmapper.h" "ac_cv_header_libdevmapper_h" "$ac_includes_default" +if test "x$ac_cv_header_libdevmapper_h" = xyes; then : + else - ac_have_decl=0 + as_fn_error $? "You need the device-mapper library." "$LINENO" 5 fi -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_STRERROR_R $ac_have_decl -_ACEOF -for ac_func in strerror_r + +# Check whether --enable-keyring was given. +if test "${enable_keyring+set}" = set; then : + enableval=$enable_keyring; +else + enable_keyring=yes +fi + +if test "x$enable_keyring" = "xyes"; then + for ac_header in linux/keyctl.h do : - ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" -if test "x$ac_cv_func_strerror_r" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "linux/keyctl.h" "ac_cv_header_linux_keyctl_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_keyctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_STRERROR_R 1 +#define HAVE_LINUX_KEYCTL_H 1 _ACEOF +else + as_fn_error $? "You need Linux kernel headers with kernel keyring service compiled." "$LINENO" 5 fi -done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 -$as_echo_n "checking whether strerror_r returns char *... " >&6; } -if ${ac_cv_func_strerror_r_char_p+:} false; then : - $as_echo_n "(cached) " >&6 -else +done - ac_cv_func_strerror_r_char_p=no - if test $ac_cv_have_decl_strerror_r = yes; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ - char buf[100]; - char x = *strerror_r (0, buf, sizeof buf); - char *p = strerror_r (0, buf, sizeof buf); - return !p || x; + ac_fn_c_check_decl "$LINENO" "__NR_add_key" "ac_cv_have_decl___NR_add_key" "#include +" +if test "x$ac_cv_have_decl___NR_add_key" = xyes; then : - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_strerror_r_char_p=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - else - # strerror_r is not declared. Choose between - # systems that have relatively inaccessible declarations for the - # function. BeOS and DEC UNIX 4.0 fall in this category, but the - # former has a strerror_r that returns char*, while the latter - # has a strerror_r that returns `int'. - # This test should segfault on the DEC system. - if test "$cross_compiling" = yes; then : - : else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default - extern char *strerror_r (); -int -main () -{ -char buf[100]; - char x = *strerror_r (0, buf, sizeof buf); - return ! isalpha (x); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_strerror_r_char_p=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext + as_fn_error $? "The kernel is missing add_key syscall." "$LINENO" 5 fi - fi + ac_fn_c_check_decl "$LINENO" "__NR_keyctl" "ac_cv_have_decl___NR_keyctl" "#include +" +if test "x$ac_cv_have_decl___NR_keyctl" = xyes; then : +else + as_fn_error $? "The kernel is missing keyctl syscall." "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 -$as_echo "$ac_cv_func_strerror_r_char_p" >&6; } -if test $ac_cv_func_strerror_r_char_p = yes; then -$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h + ac_fn_c_check_decl "$LINENO" "__NR_request_key" "ac_cv_have_decl___NR_request_key" "#include +" +if test "x$ac_cv_have_decl___NR_request_key" = xyes; then : +else + as_fn_error $? "The kernel is missing request_key syscall." "$LINENO" 5 fi + ac_fn_c_check_type "$LINENO" "key_serial_t" "ac_cv_type_key_serial_t" " + $ac_includes_default + #ifdef HAVE_LINUX_KEYCTL_H + # include + #endif +" +if test "x$ac_cv_type_key_serial_t" = xyes; then : -mkdir_p="$MKDIR_P" -case $mkdir_p in - [\\/$]* | ?:[\\/]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac +cat >>confdefs.h <<_ACEOF +#define HAVE_KEY_SERIAL_T 1 +_ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 -$as_echo_n "checking whether NLS is requested... " >&6; } - # Check whether --enable-nls was given. -if test "${enable_nls+set}" = set; then : - enableval=$enable_nls; USE_NLS=$enableval -else - USE_NLS=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 -$as_echo "$USE_NLS" >&6; } - - - +$as_echo "#define KERNEL_KEYRING 1" >>confdefs.h -# Prepare PATH_SEPARATOR. -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh fi - -# Find out how to test for executable files. Don't use a zero-byte file, -# as systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - ac_executable_p="test -x" + if test "x$enable_keyring" = "xyes"; then + KERNEL_KEYRING_TRUE= + KERNEL_KEYRING_FALSE='#' else - ac_executable_p="test -f" + KERNEL_KEYRING_TRUE='#' + KERNEL_KEYRING_FALSE= fi -rm -f conf$$.file -# Extract the first word of "msgfmt", so it can be a program name with args. -set dummy msgfmt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_MSGFMT+:} false; then : + +saved_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_clear in -luuid" >&5 +$as_echo_n "checking for uuid_clear in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_clear+:} false; then : $as_echo_n "(cached) " >&6 else - case "$MSGFMT" in - [\\/]* | ?:[\\/]*) - ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. - ;; - *) - ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$ac_save_IFS" - test -z "$ac_dir" && ac_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then - echo "$as_me: trying $ac_dir/$ac_word..." >&5 - if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && - (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then - ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" - break 2 - fi - fi - done - done - IFS="$ac_save_IFS" - test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" - ;; -esac -fi -MSGFMT="$ac_cv_path_MSGFMT" -if test "$MSGFMT" != ":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 -$as_echo "$MSGFMT" >&6; } + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_clear (); +int +main () +{ +return uuid_clear (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_clear=yes else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_lib_uuid_uuid_clear=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_clear" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_clear" >&6; } +if test "x$ac_cv_lib_uuid_uuid_clear" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUUID 1 +_ACEOF - # Extract the first word of "gmsgfmt", so it can be a program name with args. -set dummy gmsgfmt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_GMSGFMT+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $GMSGFMT in - [\\/]* | ?:[\\/]*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + LIBS="-luuid $LIBS" - test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" - ;; -esac -fi -GMSGFMT=$ac_cv_path_GMSGFMT -if test -n "$GMSGFMT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 -$as_echo "$GMSGFMT" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + as_fn_error $? "You need the uuid library." "$LINENO" 5 fi +UUID_LIBS=$LIBS +LIBS=$saved_LIBS - case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in - '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; - *) MSGFMT_015=$MSGFMT ;; - esac - - case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in - '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; - *) GMSGFMT_015=$GMSGFMT ;; - esac - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -# Prepare PATH_SEPARATOR. -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt posix4; do + if test -z "$ac_lib"; then + ac_res="none required" else - PATH_SEPARATOR=: + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - rm -f conf$$.sh + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res fi - -# Find out how to test for executable files. Don't use a zero-byte file, -# as systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - ac_executable_p="test -x" -else - ac_executable_p="test -f" +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break fi -rm -f conf$$.file +done +if ${ac_cv_search_clock_gettime+:} false; then : -# Extract the first word of "xgettext", so it can be a program name with args. -set dummy xgettext; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_XGETTEXT+:} false; then : - $as_echo_n "(cached) " >&6 else - case "$XGETTEXT" in - [\\/]* | ?:[\\/]*) - ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. - ;; - *) - ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$ac_save_IFS" - test -z "$ac_dir" && ac_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then - echo "$as_me: trying $ac_dir/$ac_word..." >&5 - if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && - (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then - ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" - break 2 - fi - fi - done - done - IFS="$ac_save_IFS" - test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" - ;; -esac + ac_cv_search_clock_gettime=no fi -XGETTEXT="$ac_cv_path_XGETTEXT" -if test "$XGETTEXT" != ":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 -$as_echo "$XGETTEXT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - rm -f messages.po - - case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in - '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; - *) XGETTEXT_015=$XGETTEXT ;; - esac - +fi +for ac_func in posix_memalign clock_gettime posix_fallocate explicit_bzero +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF -# Prepare PATH_SEPARATOR. -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh fi +done -# Find out how to test for executable files. Don't use a zero-byte file, -# as systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - ac_executable_p="test -x" -else - ac_executable_p="test -f" + +if test "x$enable_largefile" = "xno"; then + as_fn_error $? "Building with --disable-largefile is not supported, it can cause data corruption." "$LINENO" 5 fi -rm -f conf$$.file -# Extract the first word of "msgmerge", so it can be a program name with args. -set dummy msgmerge; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_MSGMERGE+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else - case "$MSGMERGE" in - [\\/]* | ?:[\\/]*) - ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. - ;; - *) - ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$ac_save_IFS" - test -z "$ac_dir" && ac_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then - echo "$as_me: trying $ac_dir/$ac_word..." >&5 - if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then - ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" - break 2 - fi - fi - done - done - IFS="$ac_save_IFS" - test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" - ;; -esac -fi -MSGMERGE="$ac_cv_path_MSGMERGE" -if test "$MSGMERGE" != ":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 -$as_echo "$MSGMERGE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int +main () +{ - test -n "$localedir" || localedir='${datadir}/locale' +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif - ac_config_commands="$ac_config_commands po-directories" + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then +$as_echo "#define const /**/" >>confdefs.h +fi - if test "X$prefix" = "XNONE"; then - acl_final_prefix="$ac_default_prefix" - else - acl_final_prefix="$prefix" - fi - if test "X$exec_prefix" = "XNONE"; then - acl_final_exec_prefix='${prefix}' - else - acl_final_exec_prefix="$exec_prefix" - fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" - prefix="$acl_save_prefix" - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -# Prepare PATH_SEPARATOR. -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 -$as_echo_n "checking for ld used by GCC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | [A-Za-z]:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${acl_cv_path_LD+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else - if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - acl_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in - *GNU* | *'with BFD'*) - test "$with_gnu_ld" != no && break ;; - *) - test "$with_gnu_ld" != yes && break ;; - esac - fi - done - IFS="$ac_save_ifs" -else - acl_cv_path_LD="$LD" # Let the user override the test with a path. -fi -fi + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; -LD="$acl_cv_path_LD" -if test -n "$LD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${acl_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU ld's only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$acl_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$acl_cv_prog_gnu_ld +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 -$as_echo_n "checking for shared library run path origin... " >&6; } -if ${acl_cv_rpath+:} false; then : - $as_echo_n "(cached) " >&6 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes else - - CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ - ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh - . ./conftest.sh - rm -f ./conftest.sh - acl_cv_rpath=done - + ac_cv_c_bigendian=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 -$as_echo "$acl_cv_rpath" >&6; } - wl="$acl_cv_wl" - libext="$acl_cv_libext" - shlibext="$acl_cv_shlibext" - hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" - hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" - hardcode_direct="$acl_cv_hardcode_direct" - hardcode_minus_L="$acl_cv_hardcode_minus_L" - # Check whether --enable-rpath was given. -if test "${enable_rpath+set}" = set; then : - enableval=$enable_rpath; : -else - enable_rpath=yes +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include - acl_libdirstem=lib - searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` - if test -n "$searchpath"; then - acl_save_IFS="${IFS= }"; IFS=":" - for searchdir in $searchpath; do - if test -d "$searchdir"; then - case "$searchdir" in - */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; - *) searchdir=`cd "$searchdir" && pwd` - case "$searchdir" in - */lib64 ) acl_libdirstem=lib64 ;; - esac ;; - esac - fi - done - IFS="$acl_save_IFS" - fi - - +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) - use_additional=yes +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +else +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF -# Check whether --with-libiconv-prefix was given. -if test "${with_libiconv_prefix+set}" = set; then : - withval=$with_libiconv_prefix; - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then +fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" +if test "$enable_largefile" != no; then - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ - else - additional_includedir="$withval/include" - additional_libdir="$withval/$acl_libdirstem" - fi + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext fi - fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi - LIBICONV= - LTLIBICONV= - INCICONV= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='iconv ' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" - else - : - fi - else - found_dir= - found_la= - found_so= - found_a= - if test $use_additional = yes; then - if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then - found_dir="$additional_libdir" - found_so="$additional_libdir/lib$name.$shlibext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - else - if test -f "$additional_libdir/lib$name.$libext"; then - found_dir="$additional_libdir" - found_a="$additional_libdir/lib$name.$libext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIBICONV; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then - found_dir="$dir" - found_so="$dir/lib$name.$shlibext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - else - if test -f "$dir/lib$name.$libext"; then - found_dir="$dir" - found_a="$dir/lib$name.$libext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } +if ${ac_cv_sys_largefile_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=no; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=1; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 +$as_echo "$ac_cv_sys_largefile_source" >&6; } +case $ac_cv_sys_largefile_source in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF +;; +esac +rm -rf conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +if test $ac_cv_sys_largefile_source != unknown; then + +$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h + +fi + +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if ${ac_cv_prog_gcc_traditional+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" +if test "x$ac_cv_have_decl_strerror_r" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_R $ac_have_decl +_ACEOF + +for ac_func in strerror_r +do : + ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" +if test "x$ac_cv_func_strerror_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRERROR_R 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 +$as_echo_n "checking whether strerror_r returns char *... " >&6; } +if ${ac_cv_func_strerror_r_char_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_cv_func_strerror_r_char_p=no + if test $ac_cv_have_decl_strerror_r = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + char buf[100]; + char x = *strerror_r (0, buf, sizeof buf); + char *p = strerror_r (0, buf, sizeof buf); + return !p || x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_strerror_r_char_p=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + else + # strerror_r is not declared. Choose between + # systems that have relatively inaccessible declarations for the + # function. BeOS and DEC UNIX 4.0 fall in this category, but the + # former has a strerror_r that returns char*, while the latter + # has a strerror_r that returns `int'. + # This test should segfault on the DEC system. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + extern char *strerror_r (); +int +main () +{ +char buf[100]; + char x = *strerror_r (0, buf, sizeof buf); + return ! isalpha (x); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_strerror_r_char_p=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 +$as_echo "$ac_cv_func_strerror_r_char_p" >&6; } +if test $ac_cv_func_strerror_r_char_p = yes; then + +$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.18 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +$as_echo_n "checking for GNU gettext in libc... " >&6; } +if eval \${$gt_func_gnugettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libc=yes" +else + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes; then : + + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +else + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test "${with_libintl_prefix+set}" = set; then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + HAVE_LIBINTL= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done fi fi fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi ;; esac if test "X$found_dir" != "X"; then @@ -14618,10 +16674,12 @@ fi done fi if test "X$found_dir" != "X"; then - LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then - LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do @@ -14633,11 +16691,11 @@ fi if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi - if test "$hardcode_direct" = yes; then - LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then - LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then @@ -14646,1030 +16704,1709 @@ fi fi done if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi - else - haveit= - for x in $LDFLAGS $LIBICONV; do + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +$as_echo_n "checking for GNU gettext in libintl... " >&6; } +if eval \${$gt_func_gnugettext_libintl+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libintl=yes" +else + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +$as_echo_n "checking whether to use NLS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +$as_echo_n "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +$as_echo "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +$as_echo_n "checking how to link with libintl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +$as_echo "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + +$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + + INTLLIBS="$LIBINTL" + + + + + + + + + +saved_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for poptConfigFileToString in -lpopt" >&5 +$as_echo_n "checking for poptConfigFileToString in -lpopt... " >&6; } +if ${ac_cv_lib_popt_poptConfigFileToString+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpopt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char poptConfigFileToString (); +int +main () +{ +return poptConfigFileToString (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_popt_poptConfigFileToString=yes +else + ac_cv_lib_popt_poptConfigFileToString=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_popt_poptConfigFileToString" >&5 +$as_echo "$ac_cv_lib_popt_poptConfigFileToString" >&6; } +if test "x$ac_cv_lib_popt_poptConfigFileToString" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPOPT 1 +_ACEOF + + LIBS="-lpopt $LIBS" + +else + as_fn_error $? "You need popt 1.7 or newer to compile." "$LINENO" 5 +fi + +POPT_LIBS=$LIBS + +LIBS=$saved_LIBS + +# Check whether --enable-fips was given. +if test "${enable_fips+set}" = set; then : + enableval=$enable_fips; +fi + +if test "x$enable_fips" = "xyes"; then + +$as_echo "#define ENABLE_FIPS 1" >>confdefs.h + + + if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then + as_fn_error $? "Static build is not compatible with FIPS." "$LINENO" 5 + fi +fi + + + +# Check whether --enable-pwquality was given. +if test "${enable_pwquality+set}" = set; then : + enableval=$enable_pwquality; +fi + + +if test "x$enable_pwquality" = "xyes"; then + +$as_echo "#define ENABLE_PWQUALITY 1" >>confdefs.h + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pwquality >= 1.0.0" >&5 +$as_echo_n "checking for pwquality >= 1.0.0... " >&6; } + +if test -n "$PWQUALITY_CFLAGS"; then + pkg_cv_PWQUALITY_CFLAGS="$PWQUALITY_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pwquality >= 1.0.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pwquality >= 1.0.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PWQUALITY_CFLAGS=`$PKG_CONFIG --cflags "pwquality >= 1.0.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PWQUALITY_LIBS"; then + pkg_cv_PWQUALITY_LIBS="$PWQUALITY_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pwquality >= 1.0.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pwquality >= 1.0.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PWQUALITY_LIBS=`$PKG_CONFIG --libs "pwquality >= 1.0.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PWQUALITY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pwquality >= 1.0.0" 2>&1` + else + PWQUALITY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pwquality >= 1.0.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PWQUALITY_PKG_ERRORS" >&5 + + as_fn_error $? "You need pwquality library." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "You need pwquality library." "$LINENO" 5 +else + PWQUALITY_CFLAGS=$pkg_cv_PWQUALITY_CFLAGS + PWQUALITY_LIBS=$pkg_cv_PWQUALITY_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +fi - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" - fi - if test "$hardcode_minus_L" != no; then - LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" - else - LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" - else - LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" - fi - fi - additional_includedir= - case "$found_dir" in - */$acl_libdirstem | */$acl_libdirstem/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INCICONV; do + PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz" +fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +# Check whether --enable-passwdqc was given. +if test "${enable_passwdqc+set}" = set; then : + enableval=$enable_passwdqc; +fi - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - if test -n "$found_la"; then - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIBICONV; do - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +case "$enable_passwdqc" in + ""|yes|no) use_passwdqc_config="" ;; + /*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;; + *) as_fn_error $? "Unrecognized --enable-passwdqc parameter." "$LINENO" 5 ;; +esac - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIBICONV; do +cat >>confdefs.h <<_ACEOF +#define PASSWDQC_CONFIG_FILE "$use_passwdqc_config" +_ACEOF - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" - LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" - ;; - esac - done - fi - else - LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" - LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$hardcode_libdir_separator"; then - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" - done - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" - else - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - for found_dir in $ltrpathdirs; do - LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" - done - fi +if test "x$enable_passwdqc" = "xyes"; then + +$as_echo "#define ENABLE_PASSWDQC 1" >>confdefs.h + + + PASSWDQC_LIBS="-lpasswdqc" +fi + +if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then + as_fn_error $? "--enable-pwquality and --enable-passwdqc are mutually incompatible." "$LINENO" 5 +fi + + + + + + + + + + + + +saved_LIBS=$LIBS + +# Check whether --enable-static-cryptsetup was given. +if test "${enable_static_cryptsetup+set}" = set; then : + enableval=$enable_static_cryptsetup; +fi + +if test "x$enable_static_cryptsetup" = "xyes"; then + if test "x$enable_static" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Requested static cryptsetup build, enabling static library." >&5 +$as_echo "$as_me: WARNING: Requested static cryptsetup build, enabling static library." >&2;} + enable_static=yes + fi +fi + if test "x$enable_static_cryptsetup" = "xyes"; then + STATIC_TOOLS_TRUE= + STATIC_TOOLS_FALSE='#' +else + STATIC_TOOLS_TRUE='#' + STATIC_TOOLS_FALSE= +fi + + +# Check whether --enable-cryptsetup was given. +if test "${enable_cryptsetup+set}" = set; then : + enableval=$enable_cryptsetup; +else + enable_cryptsetup=yes +fi + + if test "x$enable_cryptsetup" = "xyes"; then + CRYPTSETUP_TRUE= + CRYPTSETUP_FALSE='#' +else + CRYPTSETUP_TRUE='#' + CRYPTSETUP_FALSE= +fi + + +# Check whether --enable-veritysetup was given. +if test "${enable_veritysetup+set}" = set; then : + enableval=$enable_veritysetup; +else + enable_veritysetup=yes +fi + + if test "x$enable_veritysetup" = "xyes"; then + VERITYSETUP_TRUE= + VERITYSETUP_FALSE='#' +else + VERITYSETUP_TRUE='#' + VERITYSETUP_FALSE= +fi + + +# Check whether --enable-cryptsetup-reencrypt was given. +if test "${enable_cryptsetup_reencrypt+set}" = set; then : + enableval=$enable_cryptsetup_reencrypt; +else + enable_cryptsetup_reencrypt=yes +fi + if test "x$enable_cryptsetup_reencrypt" = "xyes"; then + REENCRYPT_TRUE= + REENCRYPT_FALSE='#' +else + REENCRYPT_TRUE='#' + REENCRYPT_FALSE= +fi +# Check whether --enable-integritysetup was given. +if test "${enable_integritysetup+set}" = set; then : + enableval=$enable_integritysetup; +else + enable_integritysetup=yes +fi + if test "x$enable_integritysetup" = "xyes"; then + INTEGRITYSETUP_TRUE= + INTEGRITYSETUP_FALSE='#' +else + INTEGRITYSETUP_TRUE='#' + INTEGRITYSETUP_FALSE= +fi +# Check whether --enable-selinux was given. +if test "${enable_selinux+set}" = set; then : + enableval=$enable_selinux; +else + enable_selinux=yes +fi +# Check whether --enable-udev was given. +if test "${enable_udev+set}" = set; then : + enableval=$enable_udev; +else + enable_udev=yes +fi +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for devmapper >= 1.02.03" >&5 +$as_echo_n "checking for devmapper >= 1.02.03... " >&6; } +if test -n "$DEVMAPPER_CFLAGS"; then + pkg_cv_DEVMAPPER_CFLAGS="$DEVMAPPER_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"devmapper >= 1.02.03\""; } >&5 + ($PKG_CONFIG --exists --print-errors "devmapper >= 1.02.03") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DEVMAPPER_CFLAGS=`$PKG_CONFIG --cflags "devmapper >= 1.02.03" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DEVMAPPER_LIBS"; then + pkg_cv_DEVMAPPER_LIBS="$DEVMAPPER_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"devmapper >= 1.02.03\""; } >&5 + ($PKG_CONFIG --exists --print-errors "devmapper >= 1.02.03") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DEVMAPPER_LIBS=`$PKG_CONFIG --libs "devmapper >= 1.02.03" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + DEVMAPPER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "devmapper >= 1.02.03" 2>&1` + else + DEVMAPPER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "devmapper >= 1.02.03" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DEVMAPPER_PKG_ERRORS" >&5 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 -$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } -if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_name in -ldevmapper" >&5 +$as_echo_n "checking for dm_task_set_name in -ldevmapper... " >&6; } +if ${ac_cv_lib_devmapper_dm_task_set_name+:} false; then : $as_echo_n "(cached) " >&6 else - gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldevmapper $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dm_task_set_name (); int main () { -CFPreferencesCopyAppValue(NULL, NULL) +return dm_task_set_name (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_CFPreferencesCopyAppValue=yes + ac_cv_lib_devmapper_dm_task_set_name=yes else - gt_cv_func_CFPreferencesCopyAppValue=no + ac_cv_lib_devmapper_dm_task_set_name=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LIBS="$gt_save_LIBS" +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 -$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } - if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_name" >&5 +$as_echo "$ac_cv_lib_devmapper_dm_task_set_name" >&6; } +if test "x$ac_cv_lib_devmapper_dm_task_set_name" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDEVMAPPER 1 +_ACEOF -$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + LIBS="-ldevmapper $LIBS" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 -$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } -if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : +else + as_fn_error $? "You need the device-mapper library." "$LINENO" 5 +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_message in -ldevmapper" >&5 +$as_echo_n "checking for dm_task_set_message in -ldevmapper... " >&6; } +if ${ac_cv_lib_devmapper_dm_task_set_message+:} false; then : $as_echo_n "(cached) " >&6 else - gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldevmapper $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dm_task_set_message (); int main () { -CFLocaleCopyCurrent(); +return dm_task_set_message (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_CFLocaleCopyCurrent=yes + ac_cv_lib_devmapper_dm_task_set_message=yes else - gt_cv_func_CFLocaleCopyCurrent=no + ac_cv_lib_devmapper_dm_task_set_message=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LIBS="$gt_save_LIBS" +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 -$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } - if test $gt_cv_func_CFLocaleCopyCurrent = yes; then - -$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h - - fi - INTL_MACOSX_LIBS= - if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then - INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" - fi - - - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_message" >&5 +$as_echo "$ac_cv_lib_devmapper_dm_task_set_message" >&6; } +if test "x$ac_cv_lib_devmapper_dm_task_set_message" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDEVMAPPER 1 +_ACEOF + LIBS="-ldevmapper $LIBS" - LIBINTL= - LTLIBINTL= - POSUB= +else + as_fn_error $? "The device-mapper library on your system is too old." "$LINENO" 5 +fi - if test "$USE_NLS" = "yes"; then - gt_use_preinstalled_gnugettext=no + DEVMAPPER_LIBS=$LIBS +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_name in -ldevmapper" >&5 +$as_echo_n "checking for dm_task_set_name in -ldevmapper... " >&6; } +if ${ac_cv_lib_devmapper_dm_task_set_name+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldevmapper $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dm_task_set_name (); +int +main () +{ +return dm_task_set_name (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_devmapper_dm_task_set_name=yes +else + ac_cv_lib_devmapper_dm_task_set_name=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_name" >&5 +$as_echo "$ac_cv_lib_devmapper_dm_task_set_name" >&6; } +if test "x$ac_cv_lib_devmapper_dm_task_set_name" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDEVMAPPER 1 +_ACEOF + LIBS="-ldevmapper $LIBS" +else + as_fn_error $? "You need the device-mapper library." "$LINENO" 5 +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 -$as_echo_n "checking for GNU gettext in libc... " >&6; } -if ${gt_cv_func_gnugettext2_libc+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_message in -ldevmapper" >&5 +$as_echo_n "checking for dm_task_set_message in -ldevmapper... " >&6; } +if ${ac_cv_lib_devmapper_dm_task_set_message+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldevmapper $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -extern int _nl_msg_cat_cntr; -extern int *_nl_domain_bindings; + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dm_task_set_message (); int main () { -bindtextdomain ("", ""); -return * gettext ("") + * ngettext ("", "", 0) + _nl_msg_cat_cntr + *_nl_domain_bindings +return dm_task_set_message (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_gnugettext2_libc=yes + ac_cv_lib_devmapper_dm_task_set_message=yes else - gt_cv_func_gnugettext2_libc=no + ac_cv_lib_devmapper_dm_task_set_message=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_gnugettext2_libc" >&5 -$as_echo "$gt_cv_func_gnugettext2_libc" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_message" >&5 +$as_echo "$ac_cv_lib_devmapper_dm_task_set_message" >&6; } +if test "x$ac_cv_lib_devmapper_dm_task_set_message" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDEVMAPPER 1 +_ACEOF - if test "$gt_cv_func_gnugettext2_libc" != "yes"; then + LIBS="-ldevmapper $LIBS" +else + as_fn_error $? "The device-mapper library on your system is too old." "$LINENO" 5 +fi + DEVMAPPER_LIBS=$LIBS +else + DEVMAPPER_CFLAGS=$pkg_cv_DEVMAPPER_CFLAGS + DEVMAPPER_LIBS=$pkg_cv_DEVMAPPER_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +LIBS=$saved_LIBS - am_save_CPPFLAGS="$CPPFLAGS" +LIBS="$LIBS $DEVMAPPER_LIBS" +ac_fn_c_check_decl "$LINENO" "dm_task_secure_data" "ac_cv_have_decl_dm_task_secure_data" "#include +" +if test "x$ac_cv_have_decl_dm_task_secure_data" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi - for element in $INCICONV; do - haveit= - for x in $CPPFLAGS; do +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_TASK_SECURE_DATA $ac_have_decl +_ACEOF - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +ac_fn_c_check_decl "$LINENO" "dm_task_retry_remove" "ac_cv_have_decl_dm_task_retry_remove" "#include +" +if test "x$ac_cv_have_decl_dm_task_retry_remove" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" - fi - done +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_TASK_RETRY_REMOVE $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "dm_task_deferred_remove" "ac_cv_have_decl_dm_task_deferred_remove" "#include +" +if test "x$ac_cv_have_decl_dm_task_deferred_remove" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 -$as_echo_n "checking for iconv... " >&6; } -if ${am_cv_func_iconv+:} false; then : - $as_echo_n "(cached) " >&6 +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_TASK_DEFERRED_REMOVE $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "dm_device_has_mounted_fs" "ac_cv_have_decl_dm_device_has_mounted_fs" "#include +" +if test "x$ac_cv_have_decl_dm_device_has_mounted_fs" = xyes; then : + ac_have_decl=1 else + ac_have_decl=0 +fi - am_cv_func_iconv="no, consider installing GNU libiconv" - am_cv_lib_iconv=no - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -int -main () -{ -iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd); - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS $ac_have_decl _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - am_cv_func_iconv=yes + +ac_fn_c_check_decl "$LINENO" "dm_device_has_holders" "ac_cv_have_decl_dm_device_has_holders" "#include +" +if test "x$ac_cv_have_decl_dm_device_has_holders" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test "$am_cv_func_iconv" != yes; then - am_save_LIBS="$LIBS" - LIBS="$LIBS $LIBICONV" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -int -main () -{ -iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd); - ; - return 0; -} + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_HAS_HOLDERS $ac_have_decl _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - am_cv_lib_iconv=yes - am_cv_func_iconv=yes + +ac_fn_c_check_decl "$LINENO" "dm_device_get_name" "ac_cv_have_decl_dm_device_get_name" "#include +" +if test "x$ac_cv_have_decl_dm_device_get_name" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$am_save_LIBS" - fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_GET_NAME $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "DM_DEVICE_GET_TARGET_VERSION" "ac_cv_have_decl_DM_DEVICE_GET_TARGET_VERSION" "#include +" +if test "x$ac_cv_have_decl_DM_DEVICE_GET_TARGET_VERSION" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 -$as_echo "$am_cv_func_iconv" >&6; } - if test "$am_cv_func_iconv" = yes; then -$as_echo "#define HAVE_ICONV 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION $ac_have_decl +_ACEOF - fi - if test "$am_cv_lib_iconv" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 -$as_echo_n "checking how to link with libiconv... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 -$as_echo "$LIBICONV" >&6; } - else - CPPFLAGS="$am_save_CPPFLAGS" - LIBICONV= - LTLIBICONV= - fi +ac_fn_c_check_decl "$LINENO" "DM_UDEV_DISABLE_DISK_RULES_FLAG" "ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" "#include +" +if test "x$ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + have_cookie=yes +else + have_cookie=no +fi +if test "x$enable_udev" = xyes; then + if test "x$have_cookie" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The device-mapper library on your system has no udev support, udev support disabled." >&5 +$as_echo "$as_me: WARNING: The device-mapper library on your system has no udev support, udev support disabled." >&2;} + else +$as_echo "#define USE_UDEV 1" >>confdefs.h + fi +fi +LIBS=$saved_LIBS +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for json-c" >&5 +$as_echo_n "checking for json-c... " >&6; } - use_additional=yes +if test -n "$JSON_C_CFLAGS"; then + pkg_cv_JSON_C_CFLAGS="$JSON_C_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json-c\""; } >&5 + ($PKG_CONFIG --exists --print-errors "json-c") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JSON_C_CFLAGS=`$PKG_CONFIG --cflags "json-c" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$JSON_C_LIBS"; then + pkg_cv_JSON_C_LIBS="$JSON_C_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json-c\""; } >&5 + ($PKG_CONFIG --exists --print-errors "json-c") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JSON_C_LIBS=`$PKG_CONFIG --libs "json-c" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + JSON_C_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "json-c" 2>&1` + else + JSON_C_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "json-c" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$JSON_C_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (json-c) were not met: + +$JSON_C_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables JSON_C_CFLAGS +and JSON_C_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables JSON_C_CFLAGS +and JSON_C_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + JSON_C_CFLAGS=$pkg_cv_JSON_C_CFLAGS + JSON_C_LIBS=$pkg_cv_JSON_C_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +ac_fn_c_check_decl "$LINENO" "json_object_object_add_ex" "ac_cv_have_decl_json_object_object_add_ex" "#include +" +if test "x$ac_cv_have_decl_json_object_object_add_ex" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_JSON_OBJECT_OBJECT_ADD_EX $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "json_object_deep_copy" "ac_cv_have_decl_json_object_deep_copy" "#include +" +if test "x$ac_cv_have_decl_json_object_deep_copy" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_JSON_OBJECT_DEEP_COPY $ac_have_decl +_ACEOF + -# Check whether --with-libintl-prefix was given. -if test "${with_libintl_prefix+set}" = set; then : - withval=$with_libintl_prefix; - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then +# Check whether --with-crypto_backend was given. +if test "${with_crypto_backend+set}" = set; then : + withval=$with_crypto_backend; +else + with_crypto_backend=openssl +fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" +# Check whether --enable-kernel_crypto was given. +if test "${enable_kernel_crypto+set}" = set; then : + enableval=$enable_kernel_crypto; +else + enable_kernel_crypto=yes +fi - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - else - additional_includedir="$withval/include" - additional_libdir="$withval/$acl_libdirstem" - fi - fi +if test "x$enable_kernel_crypto" = "xyes"; then + for ac_header in linux/if_alg.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linux/if_alg.h" "ac_cv_header_linux_if_alg_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_if_alg_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_IF_ALG_H 1 +_ACEOF +else + as_fn_error $? "You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)" "$LINENO" 5 fi - LIBINTL= - LTLIBINTL= - INCINTL= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='intl ' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" - else - : - fi - else - found_dir= - found_la= - found_so= - found_a= - if test $use_additional = yes; then - if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then - found_dir="$additional_libdir" - found_so="$additional_libdir/lib$name.$shlibext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - else - if test -f "$additional_libdir/lib$name.$libext"; then - found_dir="$additional_libdir" - found_a="$additional_libdir/lib$name.$libext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIBINTL; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +done - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then - found_dir="$dir" - found_so="$dir/lib$name.$shlibext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - else - if test -f "$dir/lib$name.$libext"; then - found_dir="$dir" - found_a="$dir/lib$name.$libext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then - LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" - else - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - if test "$hardcode_direct" = yes; then - LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" - else - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then - LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - haveit= - for x in $LDFLAGS $LIBINTL; do - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +$as_echo "#define ENABLE_AF_ALG 1" >>confdefs.h - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" - fi - if test "$hardcode_minus_L" != no; then - LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" - else - LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" - else - LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" - fi - fi - additional_includedir= - case "$found_dir" in - */$acl_libdirstem | */$acl_libdirstem/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INCINTL; do +fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +case $with_crypto_backend in + gcrypt) + if test "x$enable_fips" = "xyes"; then + GCRYPT_REQ_VERSION=1.4.5 + else + GCRYPT_REQ_VERSION=1.1.42 + fi - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - if test -n "$found_la"; then - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then - if test -n "$GCC"; then - case $host_os in - linux* | gnu* | k*bsd*-gnu) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIBINTL; do - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" + # Check whether --enable-gcrypt-pbkdf2 was given. +if test "${enable_gcrypt_pbkdf2+set}" = set; then : + enableval=$enable_gcrypt_pbkdf2; if test "x$enableval" = "xyes"; then + use_internal_pbkdf2=0 + else + use_internal_pbkdf2=1 + fi +else - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIBINTL; do - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" +# Check whether --with-libgcrypt-prefix was given. +if test "${with_libgcrypt_prefix+set}" = set; then : + withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" +else + libgcrypt_config_prefix="" +fi - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" - LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" - ;; - esac - done - fi - else - LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" - LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$hardcode_libdir_separator"; then - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" - done - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" - else - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - for found_dir in $ltrpathdirs; do - LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" - done + if test x"${LIBGCRYPT_CONFIG}" = x ; then + if test x"${libgcrypt_config_prefix}" != x ; then + LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config" + fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 -$as_echo_n "checking for GNU gettext in libintl... " >&6; } -if ${gt_cv_func_gnugettext2_libintl+:} false; then : + use_gpgrt_config="" + if test x"${LIBGCRYPT_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then + if $GPGRT_CONFIG libgcrypt --exists; then + LIBGCRYPT_CONFIG="$GPGRT_CONFIG libgcrypt" + { $as_echo "$as_me:${as_lineno-$LINENO}: Use gpgrt-config as libgcrypt-config" >&5 +$as_echo "$as_me: Use gpgrt-config as libgcrypt-config" >&6;} + use_gpgrt_config=yes + fi + fi + if test -z "$use_gpgrt_config"; then + if test x"${LIBGCRYPT_CONFIG}" = x ; then + case "${SYSROOT}" in + /*) + if test -x "${SYSROOT}/bin/libgcrypt-config" ; then + LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config" + fi + ;; + '') + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&5 +$as_echo "$as_me: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&2;} + ;; + esac + fi + # Extract the first word of "libgcrypt-config", so it can be a program name with args. +set dummy libgcrypt-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else - gt_save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $INCINTL" - gt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBINTL" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -extern int _nl_msg_cat_cntr; -extern -#ifdef __cplusplus -"C" -#endif -const char *_nl_expand_alias (const char *); -int -main () -{ -bindtextdomain ("", ""); -return * gettext ("") + * ngettext ("", "", 0) + _nl_msg_cat_cntr + *_nl_expand_alias ("") - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_gnugettext2_libintl=yes + case $LIBGCRYPT_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_LIBGCRYPT_CONFIG" && ac_cv_path_LIBGCRYPT_CONFIG="no" + ;; +esac +fi +LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG +if test -n "$LIBGCRYPT_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 +$as_echo "$LIBGCRYPT_CONFIG" >&6; } else - gt_cv_func_gnugettext2_libintl=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test "$gt_cv_func_gnugettext2_libintl" != yes && test -n "$LIBICONV"; then - LIBS="$LIBS $LIBICONV" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -extern int _nl_msg_cat_cntr; -extern -#ifdef __cplusplus -"C" -#endif -const char *_nl_expand_alias (const char *); -int -main () -{ -bindtextdomain ("", ""); -return * gettext ("") + * ngettext ("", "", 0) + _nl_msg_cat_cntr + *_nl_expand_alias ("") - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - LIBINTL="$LIBINTL $LIBICONV" - LTLIBINTL="$LTLIBINTL $LTLIBICONV" - gt_cv_func_gnugettext2_libintl=yes -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + + fi + + tmp=1.6.1 + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 +$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` + if test -z "$use_gpgrt_config"; then + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + else + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --modversion` + fi + major=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` + micro=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi fi - CPPFLAGS="$gt_save_CPPFLAGS" - LIBS="$gt_save_LIBS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_gnugettext2_libintl" >&5 -$as_echo "$gt_cv_func_gnugettext2_libintl" >&6; } fi + fi + fi + if test $ok = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 +$as_echo "yes ($libgcrypt_config_version)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + if test -z "$use_gpgrt_config"; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$LIBGCRYPT_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi + if test "$tmp" -gt 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 +$as_echo_n "checking LIBGCRYPT API version... " >&6; } + if test "$req_libgcrypt_api" -eq "$tmp" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 +$as_echo "okay" >&6; } + else + ok=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 +$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` + use_internal_pbkdf2=0 + if test -z "$use_gpgrt_config"; then + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + else + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --variable=host 2>/dev/null || echo none` + fi + if test x"$libgcrypt_config_host" != xnone ; then + if test x"$libgcrypt_config_host" != x"$host" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: +*** +*** The config script \"$LIBGCRYPT_CONFIG\" was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script or use \$SYSROOT. +***" >&5 +$as_echo "$as_me: WARNING: +*** +*** The config script \"$LIBGCRYPT_CONFIG\" was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script or use \$SYSROOT. +***" >&2;} + gpg_config_script_warn="$gpg_config_script_warn libgcrypt" + fi + fi + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + use_internal_pbkdf2=1 + fi - if test "$gt_cv_func_gnugettext2_libc" = "yes" \ - || { test "$gt_cv_func_gnugettext2_libintl" = "yes" \ - && test "$PACKAGE" != gettext-runtime \ - && test "$PACKAGE" != gettext-tools; }; then - gt_use_preinstalled_gnugettext=yes - else - LIBINTL= - LTLIBINTL= - INCINTL= - fi +fi - if test -n "$INTL_MACOSX_LIBS"; then - if test "$gt_use_preinstalled_gnugettext" = "yes" \ - || test "$nls_cv_use_gnu_gettext" = "yes"; then - LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" - LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" - fi - fi - if test "$gt_use_preinstalled_gnugettext" = "yes" \ - || test "$nls_cv_use_gnu_gettext" = "yes"; then -$as_echo "#define ENABLE_NLS 1" >>confdefs.h +# Check whether --with-libgcrypt-prefix was given. +if test "${with_libgcrypt_prefix+set}" = set; then : + withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" +else + libgcrypt_config_prefix="" +fi - else - USE_NLS=no - fi + if test x"${LIBGCRYPT_CONFIG}" = x ; then + if test x"${libgcrypt_config_prefix}" != x ; then + LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config" + fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 -$as_echo_n "checking whether to use NLS... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 -$as_echo "$USE_NLS" >&6; } - if test "$USE_NLS" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 -$as_echo_n "checking where the gettext function comes from... " >&6; } - if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext2_libintl" = "yes"; then - gt_source="external libintl" - else - gt_source="libc" - fi - else - gt_source="included intl directory" + use_gpgrt_config="" + if test x"${LIBGCRYPT_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then + if $GPGRT_CONFIG libgcrypt --exists; then + LIBGCRYPT_CONFIG="$GPGRT_CONFIG libgcrypt" + { $as_echo "$as_me:${as_lineno-$LINENO}: Use gpgrt-config as libgcrypt-config" >&5 +$as_echo "$as_me: Use gpgrt-config as libgcrypt-config" >&6;} + use_gpgrt_config=yes fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 -$as_echo "$gt_source" >&6; } fi - - if test "$USE_NLS" = "yes"; then - - if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext2_libintl" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 -$as_echo_n "checking how to link with libintl... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 -$as_echo "$LIBINTL" >&6; } - - for element in $INCINTL; do - haveit= - for x in $CPPFLAGS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + if test -z "$use_gpgrt_config"; then + if test x"${LIBGCRYPT_CONFIG}" = x ; then + case "${SYSROOT}" in + /*) + if test -x "${SYSROOT}/bin/libgcrypt-config" ; then + LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config" + fi + ;; + '') + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&5 +$as_echo "$as_me: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&2;} + ;; + esac fi + # Extract the first word of "libgcrypt-config", so it can be a program name with args. +set dummy libgcrypt-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LIBGCRYPT_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done +IFS=$as_save_IFS - fi - + test -z "$ac_cv_path_LIBGCRYPT_CONFIG" && ac_cv_path_LIBGCRYPT_CONFIG="no" + ;; +esac +fi +LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG +if test -n "$LIBGCRYPT_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 +$as_echo "$LIBGCRYPT_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi -$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + fi -$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + tmp=$GCRYPT_REQ_VERSION + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 +$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` + if test -z "$use_gpgrt_config"; then + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + else + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --modversion` + fi + major=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` + micro=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi fi - - POSUB=po + fi + if test $ok = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 +$as_echo "yes ($libgcrypt_config_version)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + if test -z "$use_gpgrt_config"; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$LIBGCRYPT_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi + if test "$tmp" -gt 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 +$as_echo_n "checking LIBGCRYPT API version... " >&6; } + if test "$req_libgcrypt_api" -eq "$tmp" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 +$as_echo "okay" >&6; } + else + ok=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 +$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` + : + if test -z "$use_gpgrt_config"; then + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + else + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --variable=host 2>/dev/null || echo none` + fi + if test x"$libgcrypt_config_host" != xnone ; then + if test x"$libgcrypt_config_host" != x"$host" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: +*** +*** The config script \"$LIBGCRYPT_CONFIG\" was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script or use \$SYSROOT. +***" >&5 +$as_echo "$as_me: WARNING: +*** +*** The config script \"$LIBGCRYPT_CONFIG\" was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script or use \$SYSROOT. +***" >&2;} + gpg_config_script_warn="$gpg_config_script_warn libgcrypt" + fi + fi + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + as_fn_error $? "You need the gcrypt library." "$LINENO" 5 fi - INTLLIBS="$LIBINTL" - - + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if internal cryptsetup PBKDF2 is compiled-in" >&5 +$as_echo_n "checking if internal cryptsetup PBKDF2 is compiled-in... " >&6; } + if test $use_internal_pbkdf2 = 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + if test "x$enable_fips" = "xyes"; then + as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 + fi + fi + ac_fn_c_check_decl "$LINENO" "GCRY_CIPHER_MODE_XTS" "ac_cv_have_decl_GCRY_CIPHER_MODE_XTS" "#include +" +if test "x$ac_cv_have_decl_GCRY_CIPHER_MODE_XTS" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GCRY_CIPHER_MODE_XTS $ac_have_decl +_ACEOF -saved_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for poptConfigFileToString in -lpopt" >&5 -$as_echo_n "checking for poptConfigFileToString in -lpopt... " >&6; } -if ${ac_cv_lib_popt_poptConfigFileToString+:} false; then : + if test "x$enable_static_cryptsetup" = "xyes"; then + saved_LIBS=$LIBS + LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_check_version in -lgcrypt" >&5 +$as_echo_n "checking for gcry_check_version in -lgcrypt... " >&6; } +if ${ac_cv_lib_gcrypt_gcry_check_version+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lpopt $LIBS" +LIBS="-lgcrypt -lgpg-error $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15679,88 +18416,67 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char poptConfigFileToString (); +char gcry_check_version (); int main () { -return poptConfigFileToString (); +return gcry_check_version (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_popt_poptConfigFileToString=yes + ac_cv_lib_gcrypt_gcry_check_version=yes else - ac_cv_lib_popt_poptConfigFileToString=no + ac_cv_lib_gcrypt_gcry_check_version=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_popt_poptConfigFileToString" >&5 -$as_echo "$ac_cv_lib_popt_poptConfigFileToString" >&6; } -if test "x$ac_cv_lib_popt_poptConfigFileToString" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_check_version" >&5 +$as_echo "$ac_cv_lib_gcrypt_gcry_check_version" >&6; } +if test "x$ac_cv_lib_gcrypt_gcry_check_version" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPOPT 1 +#define HAVE_LIBGCRYPT 1 _ACEOF - LIBS="-lpopt $LIBS" - -else - as_fn_error $? "You need popt 1.7 or newer to compile." "$LINENO" 5 -fi - -POPT_LIBS=$LIBS - -LIBS=$saved_LIBS + LIBS="-lgcrypt $LIBS" -# Check whether --enable-fips was given. -if test "${enable_fips+set}" = set; then : - enableval=$enable_fips; with_fips=$enableval else - with_fips=no -fi - - -if test "x$with_fips" = "xyes"; then - -$as_echo "#define ENABLE_FIPS 1" >>confdefs.h - - - if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then - as_fn_error $? "Static build is not compatible with FIPS." "$LINENO" 5 - fi + as_fn_error $? "Cannot find static gcrypt library." "$LINENO" 5 fi + LIBGCRYPT_STATIC_LIBS="$LIBGCRYPT_LIBS -lgpg-error" + LIBS=$saved_LIBS + fi + CRYPTO_CFLAGS=$LIBGCRYPT_CFLAGS + CRYPTO_LIBS=$LIBGCRYPT_LIBS + CRYPTO_STATIC_LIBS=$LIBGCRYPT_STATIC_LIBS -# Check whether --enable-pwquality was given. -if test "${enable_pwquality+set}" = set; then : - enableval=$enable_pwquality; with_pwquality=$enableval -else - with_pwquality=no -fi - - -if test "x$with_pwquality" = "xyes"; then -$as_echo "#define ENABLE_PWQUALITY 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define GCRYPT_REQ_VERSION "$GCRYPT_REQ_VERSION" +_ACEOF + ;; + openssl) pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PWQUALITY" >&5 -$as_echo_n "checking for PWQUALITY... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl >= 0.9.8" >&5 +$as_echo_n "checking for openssl >= 0.9.8... " >&6; } -if test -n "$PWQUALITY_CFLAGS"; then - pkg_cv_PWQUALITY_CFLAGS="$PWQUALITY_CFLAGS" +if test -n "$OPENSSL_CFLAGS"; then + pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pwquality >= 1.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "pwquality >= 1.0.0") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_PWQUALITY_CFLAGS=`$PKG_CONFIG --cflags "pwquality >= 1.0.0" 2>/dev/null` + pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15768,16 +18484,16 @@ fi else pkg_failed=untried fi -if test -n "$PWQUALITY_LIBS"; then - pkg_cv_PWQUALITY_LIBS="$PWQUALITY_LIBS" +if test -n "$OPENSSL_LIBS"; then + pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pwquality >= 1.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "pwquality >= 1.0.0") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_PWQUALITY_LIBS=`$PKG_CONFIG --libs "pwquality >= 1.0.0" 2>/dev/null` + pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15789,7 +18505,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15798,122 +18514,150 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - PWQUALITY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pwquality >= 1.0.0" 2>&1` + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.8" 2>&1` else - PWQUALITY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pwquality >= 1.0.0" 2>&1` + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.8" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$PWQUALITY_PKG_ERRORS" >&5 + echo "$OPENSSL_PKG_ERRORS" >&5 - as_fn_error $? "You need pwquality library." "$LINENO" 5 + as_fn_error $? "You need openssl library." "$LINENO" 5 elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "You need pwquality library." "$LINENO" 5 + as_fn_error $? "You need openssl library." "$LINENO" 5 else - PWQUALITY_CFLAGS=$pkg_cv_PWQUALITY_CFLAGS - PWQUALITY_LIBS=$pkg_cv_PWQUALITY_LIBS + OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS + OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi + CRYPTO_CFLAGS=$OPENSSL_CFLAGS + CRYPTO_LIBS=$OPENSSL_LIBS + use_internal_pbkdf2=0 - PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz" -fi - - - - - - - - - - - + if test "x$enable_static_cryptsetup" = "xyes"; then + saved_PKG_CONFIG=$PKG_CONFIG + PKG_CONFIG="$PKG_CONFIG --static" -saved_LIBS=$LIBS +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl" >&5 +$as_echo_n "checking for openssl... " >&6; } -# Check whether --enable-static-cryptsetup was given. -if test "${enable_static_cryptsetup+set}" = set; then : - enableval=$enable_static_cryptsetup; +if test -n "$OPENSSL_STATIC_CFLAGS"; then + pkg_cv_OPENSSL_STATIC_CFLAGS="$OPENSSL_STATIC_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_STATIC_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes fi - -if test x$enable_static_cryptsetup = xyes; then - if test x$enable_static = xno; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Requested static cryptsetup build, enabling static library." >&5 -$as_echo "$as_me: WARNING: Requested static cryptsetup build, enabling static library." >&2;} - enable_static=yes - fi + else + pkg_failed=untried fi - if test x$enable_static_cryptsetup = xyes; then - STATIC_TOOLS_TRUE= - STATIC_TOOLS_FALSE='#' +if test -n "$OPENSSL_STATIC_LIBS"; then + pkg_cv_OPENSSL_STATIC_LIBS="$OPENSSL_STATIC_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_STATIC_LIBS=`$PKG_CONFIG --libs "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - STATIC_TOOLS_TRUE='#' - STATIC_TOOLS_FALSE= + pkg_failed=yes fi - - -# Check whether --enable-veritysetup was given. -if test "${enable_veritysetup+set}" = set; then : - enableval=$enable_veritysetup; -else - enable_veritysetup=yes + else + pkg_failed=untried fi - if test x$enable_veritysetup = xyes; then - VERITYSETUP_TRUE= - VERITYSETUP_FALSE='#' -else - VERITYSETUP_TRUE='#' - VERITYSETUP_FALSE= -fi -# Check whether --enable-cryptsetup-reencrypt was given. -if test "${enable_cryptsetup_reencrypt+set}" = set; then : - enableval=$enable_cryptsetup_reencrypt; -fi +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } - if test x$enable_cryptsetup_reencrypt = xyes; then - REENCRYPT_TRUE= - REENCRYPT_FALSE='#' +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes else - REENCRYPT_TRUE='#' - REENCRYPT_FALSE= + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + OPENSSL_STATIC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1` + else + OPENSSL_STATIC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OPENSSL_STATIC_PKG_ERRORS" >&5 + as_fn_error $? "Package requirements (openssl) were not met: -# Check whether --enable-selinux was given. -if test "${enable_selinux+set}" = set; then : - enableval=$enable_selinux; -fi +$OPENSSL_STATIC_PKG_ERRORS +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. -# Check whether --enable-udev was given. -if test "${enable_udev+set}" = set; then : - enableval=$enable_udev; +Alternatively, you may set the environment variables OPENSSL_STATIC_CFLAGS +and OPENSSL_STATIC_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables OPENSSL_STATIC_CFLAGS +and OPENSSL_STATIC_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } else - enable_udev=yes + OPENSSL_STATIC_CFLAGS=$pkg_cv_OPENSSL_STATIC_CFLAGS + OPENSSL_STATIC_LIBS=$pkg_cv_OPENSSL_STATIC_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS + PKG_CONFIG=$saved_PKG_CONFIG + fi + ;; + nss) + if test "x$enable_static_cryptsetup" = "xyes"; then + as_fn_error $? "Static build of cryptsetup is not supported with NSS." "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: NSS backend does NOT provide backward compatibility (missing ripemd160 hash)." >&5 +$as_echo "$as_me: WARNING: NSS backend does NOT provide backward compatibility (missing ripemd160 hash)." >&2;} pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEVMAPPER" >&5 -$as_echo_n "checking for DEVMAPPER... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nss" >&5 +$as_echo_n "checking for nss... " >&6; } -if test -n "$DEVMAPPER_CFLAGS"; then - pkg_cv_DEVMAPPER_CFLAGS="$DEVMAPPER_CFLAGS" +if test -n "$NSS_CFLAGS"; then + pkg_cv_NSS_CFLAGS="$NSS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"devmapper >= 1.02.03\""; } >&5 - ($PKG_CONFIG --exists --print-errors "devmapper >= 1.02.03") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss\""; } >&5 + ($PKG_CONFIG --exists --print-errors "nss") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_DEVMAPPER_CFLAGS=`$PKG_CONFIG --cflags "devmapper >= 1.02.03" 2>/dev/null` + pkg_cv_NSS_CFLAGS=`$PKG_CONFIG --cflags "nss" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15921,16 +18665,16 @@ fi else pkg_failed=untried fi -if test -n "$DEVMAPPER_LIBS"; then - pkg_cv_DEVMAPPER_LIBS="$DEVMAPPER_LIBS" +if test -n "$NSS_LIBS"; then + pkg_cv_NSS_LIBS="$NSS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"devmapper >= 1.02.03\""; } >&5 - ($PKG_CONFIG --exists --print-errors "devmapper >= 1.02.03") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss\""; } >&5 + ($PKG_CONFIG --exists --print-errors "nss") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_DEVMAPPER_LIBS=`$PKG_CONFIG --libs "devmapper >= 1.02.03" 2>/dev/null` + pkg_cv_NSS_LIBS=`$PKG_CONFIG --libs "nss" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15942,7 +18686,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15951,292 +18695,52 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - DEVMAPPER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "devmapper >= 1.02.03" 2>&1` + NSS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "nss" 2>&1` else - DEVMAPPER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "devmapper >= 1.02.03" 2>&1` + NSS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "nss" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$DEVMAPPER_PKG_ERRORS" >&5 - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_name in -ldevmapper" >&5 -$as_echo_n "checking for dm_task_set_name in -ldevmapper... " >&6; } -if ${ac_cv_lib_devmapper_dm_task_set_name+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldevmapper $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dm_task_set_name (); -int -main () -{ -return dm_task_set_name (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_devmapper_dm_task_set_name=yes -else - ac_cv_lib_devmapper_dm_task_set_name=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_name" >&5 -$as_echo "$ac_cv_lib_devmapper_dm_task_set_name" >&6; } -if test "x$ac_cv_lib_devmapper_dm_task_set_name" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBDEVMAPPER 1 -_ACEOF - - LIBS="-ldevmapper $LIBS" - -else - as_fn_error $? "You need the device-mapper library." "$LINENO" 5 -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_message in -ldevmapper" >&5 -$as_echo_n "checking for dm_task_set_message in -ldevmapper... " >&6; } -if ${ac_cv_lib_devmapper_dm_task_set_message+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldevmapper $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dm_task_set_message (); -int -main () -{ -return dm_task_set_message (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_devmapper_dm_task_set_message=yes -else - ac_cv_lib_devmapper_dm_task_set_message=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_message" >&5 -$as_echo "$ac_cv_lib_devmapper_dm_task_set_message" >&6; } -if test "x$ac_cv_lib_devmapper_dm_task_set_message" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBDEVMAPPER 1 -_ACEOF - - LIBS="-ldevmapper $LIBS" - -else - as_fn_error $? "The device-mapper library on your system is too old." "$LINENO" 5 -fi - - DEVMAPPER_LIBS=$LIBS + echo "$NSS_PKG_ERRORS" >&5 + as_fn_error $? "You need nss library." "$LINENO" 5 elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_name in -ldevmapper" >&5 -$as_echo_n "checking for dm_task_set_name in -ldevmapper... " >&6; } -if ${ac_cv_lib_devmapper_dm_task_set_name+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldevmapper $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dm_task_set_name (); -int -main () -{ -return dm_task_set_name (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_devmapper_dm_task_set_name=yes -else - ac_cv_lib_devmapper_dm_task_set_name=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_name" >&5 -$as_echo "$ac_cv_lib_devmapper_dm_task_set_name" >&6; } -if test "x$ac_cv_lib_devmapper_dm_task_set_name" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBDEVMAPPER 1 -_ACEOF - - LIBS="-ldevmapper $LIBS" - -else - as_fn_error $? "You need the device-mapper library." "$LINENO" 5 -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dm_task_set_message in -ldevmapper" >&5 -$as_echo_n "checking for dm_task_set_message in -ldevmapper... " >&6; } -if ${ac_cv_lib_devmapper_dm_task_set_message+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldevmapper $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dm_task_set_message (); -int -main () -{ -return dm_task_set_message (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_devmapper_dm_task_set_message=yes -else - ac_cv_lib_devmapper_dm_task_set_message=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devmapper_dm_task_set_message" >&5 -$as_echo "$ac_cv_lib_devmapper_dm_task_set_message" >&6; } -if test "x$ac_cv_lib_devmapper_dm_task_set_message" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBDEVMAPPER 1 -_ACEOF - - LIBS="-ldevmapper $LIBS" - -else - as_fn_error $? "The device-mapper library on your system is too old." "$LINENO" 5 -fi - - DEVMAPPER_LIBS=$LIBS - + as_fn_error $? "You need nss library." "$LINENO" 5 else - DEVMAPPER_CFLAGS=$pkg_cv_DEVMAPPER_CFLAGS - DEVMAPPER_LIBS=$pkg_cv_DEVMAPPER_LIBS + NSS_CFLAGS=$pkg_cv_NSS_CFLAGS + NSS_LIBS=$pkg_cv_NSS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } -fi -LIBS=$saved_LIBS - -LIBS="$LIBS $DEVMAPPER_LIBS" -ac_fn_c_check_decl "$LINENO" "dm_task_secure_data" "ac_cv_have_decl_dm_task_secure_data" "#include -" -if test "x$ac_cv_have_decl_dm_task_secure_data" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_DM_TASK_SECURE_DATA $ac_have_decl -_ACEOF - -ac_fn_c_check_decl "$LINENO" "dm_task_retry_remove" "ac_cv_have_decl_dm_task_retry_remove" "#include -" -if test "x$ac_cv_have_decl_dm_task_retry_remove" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_DM_TASK_RETRY_REMOVE $ac_have_decl -_ACEOF - -ac_fn_c_check_decl "$LINENO" "DM_UDEV_DISABLE_DISK_RULES_FLAG" "ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" "#include +fi + + saved_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $NSS_CFLAGS" + ac_fn_c_check_decl "$LINENO" "NSS_GetVersion" "ac_cv_have_decl_NSS_GetVersion" "#include " -if test "x$ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" = xyes; then : +if test "x$ac_cv_have_decl_NSS_GetVersion" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG $ac_have_decl +#define HAVE_DECL_NSS_GETVERSION $ac_have_decl _ACEOF -if test $ac_have_decl = 1; then : - have_cookie=yes -else - have_cookie=no -fi -if test "x$enable_udev" = xyes; then - if test "x$have_cookie" = xno; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The device-mapper library on your system has no udev support, udev support disabled." >&5 -$as_echo "$as_me: WARNING: The device-mapper library on your system has no udev support, udev support disabled." >&2;} - else + CFLAGS=$saved_CFLAGS -$as_echo "#define USE_UDEV 1" >>confdefs.h + CRYPTO_CFLAGS=$NSS_CFLAGS + CRYPTO_LIBS=$NSS_LIBS + use_internal_pbkdf2=1 + if test "x$enable_fips" = "xyes"; then + as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 fi -fi -LIBS=$saved_LIBS - - -# Check whether --with-crypto_backend was given. -if test "${with_crypto_backend+set}" = set; then : - withval=$with_crypto_backend; -else - with_crypto_backend=gcrypt - -fi - - -# Check whether --enable-kernel_crypto was given. -if test "${enable_kernel_crypto+set}" = set; then : - enableval=$enable_kernel_crypto; with_kernel_crypto=$enableval -else - with_kernel_crypto=yes -fi - -if test "x$with_kernel_crypto" = "xyes"; then + ;; + kernel) for ac_header in linux/if_alg.h do : ac_fn_c_check_header_mongrel "$LINENO" "linux/if_alg.h" "ac_cv_header_linux_if_alg_h" "$ac_includes_default" @@ -16246,557 +18750,217 @@ if test "x$ac_cv_header_linux_if_alg_h" = xyes; then : _ACEOF else - as_fn_error $? "You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)" "$LINENO" 5 + as_fn_error $? "You need Linux kernel headers with userspace crypto interface." "$LINENO" 5 fi done +# AC_CHECK_DECLS([AF_ALG],, +# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])], +# [#include ]) + use_internal_pbkdf2=1 -$as_echo "#define ENABLE_AF_ALG 1" >>confdefs.h - -fi - -case $with_crypto_backend in - gcrypt) - if test "x$with_fips" = "xyes"; then - GCRYPT_REQ_VERSION=1.4.5 - else - GCRYPT_REQ_VERSION=1.1.42 + if test "x$enable_fips" = "xyes"; then + as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 fi - # Check whether --enable-gcrypt-pbkdf2 was given. -if test "${enable_gcrypt_pbkdf2+set}" = set; then : - enableval=$enable_gcrypt_pbkdf2; if test "x$enableval" = "xyes"; then - use_internal_pbkdf2=0 - else - use_internal_pbkdf2=1 - fi -else - - -# Check whether --with-libgcrypt-prefix was given. -if test "${with_libgcrypt_prefix+set}" = set; then : - withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" -else - libgcrypt_config_prefix="" -fi - if test x$libgcrypt_config_prefix != x ; then - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config - fi - fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}libgcrypt-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + ;; + nettle) + for ac_header in nettle/sha.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "nettle/sha.h" "ac_cv_header_nettle_sha_h" "$ac_includes_default" +if test "x$ac_cv_header_nettle_sha_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETTLE_SHA_H 1 +_ACEOF - ;; -esac -fi -LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG -if test -n "$LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 -$as_echo "$LIBGCRYPT_CONFIG" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + as_fn_error $? "You need Nettle cryptographic library." "$LINENO" 5 fi - -fi -if test -z "$ac_cv_path_LIBGCRYPT_CONFIG"; then - ac_pt_LIBGCRYPT_CONFIG=$LIBGCRYPT_CONFIG - # Extract the first word of "libgcrypt-config", so it can be a program name with args. -set dummy libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$ac_pt_LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi done - done -IFS=$as_save_IFS - ;; -esac -fi -ac_pt_LIBGCRYPT_CONFIG=$ac_cv_path_ac_pt_LIBGCRYPT_CONFIG -if test -n "$ac_pt_LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LIBGCRYPT_CONFIG" >&5 -$as_echo "$ac_pt_LIBGCRYPT_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi + for ac_header in nettle/version.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "nettle/version.h" "ac_cv_header_nettle_version_h" "$ac_includes_default" +if test "x$ac_cv_header_nettle_version_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETTLE_VERSION_H 1 +_ACEOF - if test "x$ac_pt_LIBGCRYPT_CONFIG" = x; then - LIBGCRYPT_CONFIG="no" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIBGCRYPT_CONFIG=$ac_pt_LIBGCRYPT_CONFIG - fi -else - LIBGCRYPT_CONFIG="$ac_cv_path_LIBGCRYPT_CONFIG" fi - tmp=1.6.1 - if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then - req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` - min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` - else - req_libgcrypt_api=0 - min_libgcrypt_version="$tmp" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 -$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } - ok=no - if test "$LIBGCRYPT_CONFIG" != "no" ; then - req_major=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` - req_minor=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` - req_micro=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` - major=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` - minor=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` - micro=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` - if test "$major" -gt "$req_major"; then - ok=yes - else - if test "$major" -eq "$req_major"; then - if test "$minor" -gt "$req_minor"; then - ok=yes - else - if test "$minor" -eq "$req_minor"; then - if test "$micro" -ge "$req_micro"; then - ok=yes - fi - fi - fi - fi - fi - fi - if test $ok = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 -$as_echo "yes ($libgcrypt_config_version)" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - if test $ok = yes; then - # If we have a recent libgcrypt, we should also check that the - # API is compatible - if test "$req_libgcrypt_api" -gt 0 ; then - tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` - if test "$tmp" -gt 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 -$as_echo_n "checking LIBGCRYPT API version... " >&6; } - if test "$req_libgcrypt_api" -eq "$tmp" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 -$as_echo "okay" >&6; } - else - ok=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 -$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } - fi - fi - fi - fi - if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` - use_internal_pbkdf2=0 - libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` - if test x"$libgcrypt_config_host" != xnone ; then - if test x"$libgcrypt_config_host" != x"$host" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&5 -$as_echo "$as_me: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&2;} - fi - fi - else - LIBGCRYPT_CFLAGS="" - LIBGCRYPT_LIBS="" - use_internal_pbkdf2=1 - fi +done + saved_LIBS=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nettle_pbkdf2_hmac_sha256 in -lnettle" >&5 +$as_echo_n "checking for nettle_pbkdf2_hmac_sha256 in -lnettle... " >&6; } +if ${ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnettle $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char nettle_pbkdf2_hmac_sha256 (); +int +main () +{ +return nettle_pbkdf2_hmac_sha256 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256=yes +else + ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256=no fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" >&5 +$as_echo "$ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" >&6; } +if test "x$ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNETTLE 1 +_ACEOF + LIBS="-lnettle $LIBS" - -# Check whether --with-libgcrypt-prefix was given. -if test "${with_libgcrypt_prefix+set}" = set; then : - withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" else - libgcrypt_config_prefix="" + as_fn_error $? "You need Nettle library version 2.6 or more recent." "$LINENO" 5 fi - if test x$libgcrypt_config_prefix != x ; then - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config - fi - fi + CRYPTO_LIBS=$LIBS + LIBS=$saved_LIBS - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}libgcrypt-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + CRYPTO_STATIC_LIBS=$CRYPTO_LIBS + use_internal_pbkdf2=0 - ;; + if test "x$enable_fips" = "xyes"; then + as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 + fi + + ;; + *) as_fn_error $? "Unknown crypto backend." "$LINENO" 5 ;; esac -fi -LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG -if test -n "$LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 -$as_echo "$LIBGCRYPT_CONFIG" >&6; } + if test "$with_crypto_backend" = "gcrypt"; then + CRYPTO_BACKEND_GCRYPT_TRUE= + CRYPTO_BACKEND_GCRYPT_FALSE='#' else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + CRYPTO_BACKEND_GCRYPT_TRUE='#' + CRYPTO_BACKEND_GCRYPT_FALSE= fi - -fi -if test -z "$ac_cv_path_LIBGCRYPT_CONFIG"; then - ac_pt_LIBGCRYPT_CONFIG=$LIBGCRYPT_CONFIG - # Extract the first word of "libgcrypt-config", so it can be a program name with args. -set dummy libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 + if test "$with_crypto_backend" = "openssl"; then + CRYPTO_BACKEND_OPENSSL_TRUE= + CRYPTO_BACKEND_OPENSSL_FALSE='#' else - case $ac_pt_LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$ac_pt_LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac + CRYPTO_BACKEND_OPENSSL_TRUE='#' + CRYPTO_BACKEND_OPENSSL_FALSE= fi -ac_pt_LIBGCRYPT_CONFIG=$ac_cv_path_ac_pt_LIBGCRYPT_CONFIG -if test -n "$ac_pt_LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LIBGCRYPT_CONFIG" >&5 -$as_echo "$ac_pt_LIBGCRYPT_CONFIG" >&6; } + + if test "$with_crypto_backend" = "nss"; then + CRYPTO_BACKEND_NSS_TRUE= + CRYPTO_BACKEND_NSS_FALSE='#' else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + CRYPTO_BACKEND_NSS_TRUE='#' + CRYPTO_BACKEND_NSS_FALSE= fi - if test "x$ac_pt_LIBGCRYPT_CONFIG" = x; then - LIBGCRYPT_CONFIG="no" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIBGCRYPT_CONFIG=$ac_pt_LIBGCRYPT_CONFIG - fi + if test "$with_crypto_backend" = "kernel"; then + CRYPTO_BACKEND_KERNEL_TRUE= + CRYPTO_BACKEND_KERNEL_FALSE='#' else - LIBGCRYPT_CONFIG="$ac_cv_path_LIBGCRYPT_CONFIG" + CRYPTO_BACKEND_KERNEL_TRUE='#' + CRYPTO_BACKEND_KERNEL_FALSE= fi - tmp=$GCRYPT_REQ_VERSION - if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then - req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` - min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` - else - req_libgcrypt_api=0 - min_libgcrypt_version="$tmp" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 -$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } - ok=no - if test "$LIBGCRYPT_CONFIG" != "no" ; then - req_major=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` - req_minor=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` - req_micro=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` - major=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` - minor=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` - micro=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` - if test "$major" -gt "$req_major"; then - ok=yes - else - if test "$major" -eq "$req_major"; then - if test "$minor" -gt "$req_minor"; then - ok=yes - else - if test "$minor" -eq "$req_minor"; then - if test "$micro" -ge "$req_micro"; then - ok=yes - fi - fi - fi - fi - fi - fi - if test $ok = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 -$as_echo "yes ($libgcrypt_config_version)" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - if test $ok = yes; then - # If we have a recent libgcrypt, we should also check that the - # API is compatible - if test "$req_libgcrypt_api" -gt 0 ; then - tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` - if test "$tmp" -gt 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 -$as_echo_n "checking LIBGCRYPT API version... " >&6; } - if test "$req_libgcrypt_api" -eq "$tmp" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 -$as_echo "okay" >&6; } - else - ok=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 -$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } - fi - fi - fi - fi - if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` - : - libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` - if test x"$libgcrypt_config_host" != xnone ; then - if test x"$libgcrypt_config_host" != x"$host" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&5 -$as_echo "$as_me: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&2;} - fi - fi - else - LIBGCRYPT_CFLAGS="" - LIBGCRYPT_LIBS="" - as_fn_error $? "You need the gcrypt library." "$LINENO" 5 - fi - - + if test "$with_crypto_backend" = "nettle"; then + CRYPTO_BACKEND_NETTLE_TRUE= + CRYPTO_BACKEND_NETTLE_FALSE='#' +else + CRYPTO_BACKEND_NETTLE_TRUE='#' + CRYPTO_BACKEND_NETTLE_FALSE= +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if internal cryptsetup PBKDF2 is compiled-in" >&5 -$as_echo_n "checking if internal cryptsetup PBKDF2 is compiled-in... " >&6; } - if test $use_internal_pbkdf2 = 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + if test $use_internal_pbkdf2 = 1; then + CRYPTO_INTERNAL_PBKDF2_TRUE= + CRYPTO_INTERNAL_PBKDF2_FALSE='#' +else + CRYPTO_INTERNAL_PBKDF2_TRUE='#' + CRYPTO_INTERNAL_PBKDF2_FALSE= +fi - if test "x$with_fips" = "xyes"; then - as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 - fi - fi +cat >>confdefs.h <<_ACEOF +#define USE_INTERNAL_PBKDF2 $use_internal_pbkdf2 +_ACEOF - if test x$enable_static_cryptsetup = xyes; then - saved_LIBS=$LIBS - LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_check_version in -lgcrypt" >&5 -$as_echo_n "checking for gcry_check_version in -lgcrypt... " >&6; } -if ${ac_cv_lib_gcrypt_gcry_check_version+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lgcrypt -lgpg-error $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gcry_check_version (); -int -main () -{ -return gcry_check_version (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_gcrypt_gcry_check_version=yes +# Check whether --enable-internal-argon2 was given. +if test "${enable_internal_argon2+set}" = set; then : + enableval=$enable_internal_argon2; else - ac_cv_lib_gcrypt_gcry_check_version=no + enable_internal_argon2=yes fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + + +# Check whether --enable-libargon2 was given. +if test "${enable_libargon2+set}" = set; then : + enableval=$enable_libargon2; fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_check_version" >&5 -$as_echo "$ac_cv_lib_gcrypt_gcry_check_version" >&6; } -if test "x$ac_cv_lib_gcrypt_gcry_check_version" = xyes; then : + + +if test "x$enable_libargon2" = "xyes" ; then + for ac_header in argon2.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "argon2.h" "ac_cv_header_argon2_h" "$ac_includes_default" +if test "x$ac_cv_header_argon2_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_LIBGCRYPT 1 +#define HAVE_ARGON2_H 1 _ACEOF - LIBS="-lgcrypt $LIBS" - else - as_fn_error $? "Cannot find static gcrypt library." "$LINENO" 5 + as_fn_error $? "You need libargon2 development library installed." "$LINENO" 5 fi - LIBGCRYPT_STATIC_LIBS="$LIBGCRYPT_LIBS -lgpg-error" - LIBS=$saved_LIBS - fi - - CRYPTO_CFLAGS=$LIBGCRYPT_CFLAGS - CRYPTO_LIBS=$LIBGCRYPT_LIBS - CRYPTO_STATIC_LIBS=$LIBGCRYPT_STATIC_LIBS +done + ac_fn_c_check_decl "$LINENO" "Argon2_id" "ac_cv_have_decl_Argon2_id" "#include +" +if test "x$ac_cv_have_decl_Argon2_id" = xyes; then : -cat >>confdefs.h <<_ACEOF -#define GCRYPT_REQ_VERSION "$GCRYPT_REQ_VERSION" -_ACEOF +else + as_fn_error $? "You need more recent Argon2 library with support for Argon2id." "$LINENO" 5 +fi - ;; - openssl) pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5 -$as_echo_n "checking for OPENSSL... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libargon2" >&5 +$as_echo_n "checking for libargon2... " >&6; } -if test -n "$OPENSSL_CFLAGS"; then - pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" +if test -n "$LIBARGON2_CFLAGS"; then + pkg_cv_LIBARGON2_CFLAGS="$LIBARGON2_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libargon2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libargon2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.8" 2>/dev/null` + pkg_cv_LIBARGON2_CFLAGS=`$PKG_CONFIG --cflags "libargon2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -16804,16 +18968,16 @@ fi else pkg_failed=untried fi -if test -n "$OPENSSL_LIBS"; then - pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" +if test -n "$LIBARGON2_LIBS"; then + pkg_cv_LIBARGON2_LIBS="$LIBARGON2_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libargon2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libargon2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.8" 2>/dev/null` + pkg_cv_LIBARGON2_LIBS=`$PKG_CONFIG --libs "libargon2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -16825,7 +18989,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16834,155 +18998,113 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.8" 2>&1` + LIBARGON2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libargon2" 2>&1` else - OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.8" 2>&1` + LIBARGON2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libargon2" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$OPENSSL_PKG_ERRORS" >&5 + echo "$LIBARGON2_PKG_ERRORS" >&5 - as_fn_error $? "You need openssl library." "$LINENO" 5 + LIBARGON2_LIBS="-largon2" elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "You need openssl library." "$LINENO" 5 + LIBARGON2_LIBS="-largon2" else - OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS - OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS + LIBARGON2_CFLAGS=$pkg_cv_LIBARGON2_CFLAGS + LIBARGON2_LIBS=$pkg_cv_LIBARGON2_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi - CRYPTO_CFLAGS=$OPENSSL_CFLAGS - CRYPTO_LIBS=$OPENSSL_LIBS - use_internal_pbkdf2=0 + enable_internal_argon2=no +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2." >&5 +$as_echo "$as_me: WARNING: Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2." >&2;} - if test x$enable_static_cryptsetup = xyes; then - saved_PKG_CONFIG=$PKG_CONFIG - PKG_CONFIG="$PKG_CONFIG --static" + # Check whether --enable-internal-sse-argon2 was given. +if test "${enable_internal_sse_argon2+set}" = set; then : + enableval=$enable_internal_sse_argon2; +fi -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_STATIC" >&5 -$as_echo_n "checking for OPENSSL_STATIC... " >&6; } -if test -n "$OPENSSL_STATIC_CFLAGS"; then - pkg_cv_OPENSSL_STATIC_CFLAGS="$OPENSSL_STATIC_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_OPENSSL_STATIC_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$OPENSSL_STATIC_LIBS"; then - pkg_cv_OPENSSL_STATIC_LIBS="$OPENSSL_STATIC_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_OPENSSL_STATIC_LIBS=`$PKG_CONFIG --libs "openssl" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi + if test "x$enable_internal_sse_argon2" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Argon2 SSE optimization can be used" >&5 +$as_echo_n "checking if Argon2 SSE optimization can be used... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + #include + __m128i testfunc(__m128i *a, __m128i *b) { + return _mm_xor_si128(_mm_loadu_si128(a), _mm_loadu_si128(b)); + } +int +main () +{ -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes else - _pkg_short_errors_supported=no + enable_internal_sse_argon2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_internal_sse_argon2" >&5 +$as_echo "$enable_internal_sse_argon2" >&6; } + fi fi - if test $_pkg_short_errors_supported = yes; then - OPENSSL_STATIC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1` - else - OPENSSL_STATIC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$OPENSSL_STATIC_PKG_ERRORS" >&5 - - as_fn_error $? "Package requirements (openssl) were not met: - -$OPENSSL_STATIC_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. -Alternatively, you may set the environment variables OPENSSL_STATIC_CFLAGS -and OPENSSL_STATIC_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details." "$LINENO" 5 -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. +if test "x$enable_internal_argon2" = "xyes"; then -Alternatively, you may set the environment variables OPENSSL_STATIC_CFLAGS -and OPENSSL_STATIC_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details. +$as_echo "#define USE_INTERNAL_ARGON2 1" >>confdefs.h -To get pkg-config, see . -See \`config.log' for more details" "$LINENO" 5; } +fi + if test "x$enable_internal_argon2" = "xyes"; then + CRYPTO_INTERNAL_ARGON2_TRUE= + CRYPTO_INTERNAL_ARGON2_FALSE='#' else - OPENSSL_STATIC_CFLAGS=$pkg_cv_OPENSSL_STATIC_CFLAGS - OPENSSL_STATIC_LIBS=$pkg_cv_OPENSSL_STATIC_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + CRYPTO_INTERNAL_ARGON2_TRUE='#' + CRYPTO_INTERNAL_ARGON2_FALSE= +fi + if test "x$enable_internal_sse_argon2" = "xyes"; then + CRYPTO_INTERNAL_SSE_ARGON2_TRUE= + CRYPTO_INTERNAL_SSE_ARGON2_FALSE='#' +else + CRYPTO_INTERNAL_SSE_ARGON2_TRUE='#' + CRYPTO_INTERNAL_SSE_ARGON2_FALSE= fi - CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS - PKG_CONFIG=$saved_PKG_CONFIG - fi - if test "x$with_fips" = "xyes"; then - as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 - fi - ;; - nss) - if test x$enable_static_cryptsetup = xyes; then - as_fn_error $? "Static build of cryptsetup is not supported with NSS." "$LINENO" 5 - fi +# Check whether --enable-blkid was given. +if test "${enable_blkid+set}" = set; then : + enableval=$enable_blkid; +else + enable_blkid=yes +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: NSS backend does NOT provide backward compatibility (missing ripemd160 hash)." >&5 -$as_echo "$as_me: WARNING: NSS backend does NOT provide backward compatibility (missing ripemd160 hash)." >&2;} +if test "x$enable_blkid" = "xyes"; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for NSS" >&5 -$as_echo_n "checking for NSS... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for blkid" >&5 +$as_echo_n "checking for blkid... " >&6; } -if test -n "$NSS_CFLAGS"; then - pkg_cv_NSS_CFLAGS="$NSS_CFLAGS" +if test -n "$BLKID_CFLAGS"; then + pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss\""; } >&5 - ($PKG_CONFIG --exists --print-errors "nss") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid\""; } >&5 + ($PKG_CONFIG --exists --print-errors "blkid") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_NSS_CFLAGS=`$PKG_CONFIG --cflags "nss" 2>/dev/null` + pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -16990,16 +19112,16 @@ fi else pkg_failed=untried fi -if test -n "$NSS_LIBS"; then - pkg_cv_NSS_LIBS="$NSS_LIBS" +if test -n "$BLKID_LIBS"; then + pkg_cv_BLKID_LIBS="$BLKID_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nss\""; } >&5 - ($PKG_CONFIG --exists --print-errors "nss") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid\""; } >&5 + ($PKG_CONFIG --exists --print-errors "blkid") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_NSS_LIBS=`$PKG_CONFIG --libs "nss" 2>/dev/null` + pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -17011,7 +19133,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17020,209 +19142,187 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - NSS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "nss" 2>&1` + BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid" 2>&1` else - NSS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "nss" 2>&1` + BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$NSS_PKG_ERRORS" >&5 + echo "$BLKID_PKG_ERRORS" >&5 - as_fn_error $? "You need nss library." "$LINENO" 5 + LIBBLKID_LIBS="-lblkid" elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "You need nss library." "$LINENO" 5 + LIBBLKID_LIBS="-lblkid" else - NSS_CFLAGS=$pkg_cv_NSS_CFLAGS - NSS_LIBS=$pkg_cv_NSS_LIBS + BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS + BLKID_LIBS=$pkg_cv_BLKID_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } -fi +$as_echo "#define HAVE_BLKID 1" >>confdefs.h - saved_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $NSS_CFLAGS" - ac_fn_c_check_decl "$LINENO" "NSS_GetVersion" "ac_cv_have_decl_NSS_GetVersion" "#include -" -if test "x$ac_cv_have_decl_NSS_GetVersion" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 fi -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_NSS_GETVERSION $ac_have_decl -_ACEOF - - CFLAGS=$saved_CFLAGS - - CRYPTO_CFLAGS=$NSS_CFLAGS - CRYPTO_LIBS=$NSS_LIBS - use_internal_pbkdf2=1 - - if test "x$with_fips" = "xyes"; then - as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 - fi - - ;; - kernel) - for ac_header in linux/if_alg.h + for ac_header in blkid/blkid.h do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/if_alg.h" "ac_cv_header_linux_if_alg_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_if_alg_h" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "blkid/blkid.h" "ac_cv_header_blkid_blkid_h" "$ac_includes_default" +if test "x$ac_cv_header_blkid_blkid_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_IF_ALG_H 1 +#define HAVE_BLKID_BLKID_H 1 _ACEOF else - as_fn_error $? "You need Linux kernel headers with userspace crypto interface." "$LINENO" 5 + as_fn_error $? "You need blkid development library installed." "$LINENO" 5 fi done -# AC_CHECK_DECLS([AF_ALG],, -# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])], -# [#include ]) - use_internal_pbkdf2=1 + ac_fn_c_check_decl "$LINENO" "blkid_do_wipe" "ac_cv_have_decl_blkid_do_wipe" "#include +" +if test "x$ac_cv_have_decl_blkid_do_wipe" = xyes; then : - if test "x$with_fips" = "xyes"; then - as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 - fi +$as_echo "#define HAVE_BLKID_WIPE 1" >>confdefs.h - ;; - nettle) - for ac_header in nettle/sha.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "nettle/sha.h" "ac_cv_header_nettle_sha_h" "$ac_includes_default" -if test "x$ac_cv_header_nettle_sha_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_NETTLE_SHA_H 1 -_ACEOF + enable_blkid_wipe=yes -else - as_fn_error $? "You need Nettle cryptographic library." "$LINENO" 5 fi -done + ac_fn_c_check_decl "$LINENO" "blkid_probe_step_back" "ac_cv_have_decl_blkid_probe_step_back" "#include +" +if test "x$ac_cv_have_decl_blkid_probe_step_back" = xyes; then : +$as_echo "#define HAVE_BLKID_STEP_BACK 1" >>confdefs.h - saved_LIBS=$LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nettle_pbkdf2_hmac_sha256 in -lnettle" >&5 -$as_echo_n "checking for nettle_pbkdf2_hmac_sha256 in -lnettle... " >&6; } -if ${ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256+:} false; then : - $as_echo_n "(cached) " >&6 + enable_blkid_step_back=yes + +fi + + ac_fn_c_check_decl "$LINENO" "blkid_reset_probe" "ac_cv_have_decl_blkid_reset_probe" "#include +" +if test "x$ac_cv_have_decl_blkid_reset_probe" = xyes; then : + ac_have_decl=1 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnettle $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + ac_have_decl=0 +fi -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char nettle_pbkdf2_hmac_sha256 (); -int -main () -{ -return nettle_pbkdf2_hmac_sha256 (); - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_RESET_PROBE $ac_have_decl _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256=yes +if test $ac_have_decl = 1; then : + else - ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256=no + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS +ac_fn_c_check_decl "$LINENO" "blkid_probe_set_device" "ac_cv_have_decl_blkid_probe_set_device" "#include +" +if test "x$ac_cv_have_decl_blkid_probe_set_device" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" >&5 -$as_echo "$ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" >&6; } -if test "x$ac_cv_lib_nettle_nettle_pbkdf2_hmac_sha256" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBNETTLE 1 -_ACEOF - LIBS="-lnettle $LIBS" +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_PROBE_SET_DEVICE $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : else - as_fn_error $? "You need Nettle library version 2.6 or more recent." "$LINENO" 5 + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 +fi +ac_fn_c_check_decl "$LINENO" "blkid_probe_filter_superblocks_type" "ac_cv_have_decl_blkid_probe_filter_superblocks_type" "#include +" +if test "x$ac_cv_have_decl_blkid_probe_filter_superblocks_type" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi - CRYPTO_LIBS=$LIBS - LIBS=$saved_LIBS +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_PROBE_FILTER_SUPERBLOCKS_TYPE $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : - CRYPTO_STATIC_LIBS=$CRYPTO_LIBS - use_internal_pbkdf2=0 +else + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 +fi +ac_fn_c_check_decl "$LINENO" "blkid_do_safeprobe" "ac_cv_have_decl_blkid_do_safeprobe" "#include +" +if test "x$ac_cv_have_decl_blkid_do_safeprobe" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi - if test "x$with_fips" = "xyes"; then - as_fn_error $? "This option is not compatible with FIPS." "$LINENO" 5 - fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_DO_SAFEPROBE $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : - ;; - *) as_fn_error $? "Unknown crypto backend." "$LINENO" 5 ;; -esac - if test $with_crypto_backend = gcrypt; then - CRYPTO_BACKEND_GCRYPT_TRUE= - CRYPTO_BACKEND_GCRYPT_FALSE='#' else - CRYPTO_BACKEND_GCRYPT_TRUE='#' - CRYPTO_BACKEND_GCRYPT_FALSE= + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 fi - - if test $with_crypto_backend = openssl; then - CRYPTO_BACKEND_OPENSSL_TRUE= - CRYPTO_BACKEND_OPENSSL_FALSE='#' +ac_fn_c_check_decl "$LINENO" "blkid_do_probe" "ac_cv_have_decl_blkid_do_probe" "#include +" +if test "x$ac_cv_have_decl_blkid_do_probe" = xyes; then : + ac_have_decl=1 else - CRYPTO_BACKEND_OPENSSL_TRUE='#' - CRYPTO_BACKEND_OPENSSL_FALSE= + ac_have_decl=0 fi - if test $with_crypto_backend = nss; then - CRYPTO_BACKEND_NSS_TRUE= - CRYPTO_BACKEND_NSS_FALSE='#' +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_DO_PROBE $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + else - CRYPTO_BACKEND_NSS_TRUE='#' - CRYPTO_BACKEND_NSS_FALSE= + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 fi - - if test $with_crypto_backend = kernel; then - CRYPTO_BACKEND_KERNEL_TRUE= - CRYPTO_BACKEND_KERNEL_FALSE='#' +ac_fn_c_check_decl "$LINENO" "blkid_probe_lookup_value + " "ac_cv_have_decl_blkid_probe_lookup_value__________" "#include +" +if test "x$ac_cv_have_decl_blkid_probe_lookup_value__________" = xyes; then : + ac_have_decl=1 else - CRYPTO_BACKEND_KERNEL_TRUE='#' - CRYPTO_BACKEND_KERNEL_FALSE= + ac_have_decl=0 fi - if test $with_crypto_backend = nettle; then - CRYPTO_BACKEND_NETTLE_TRUE= - CRYPTO_BACKEND_NETTLE_FALSE='#' +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BLKID_PROBE_LOOKUP_VALUE__________ $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + else - CRYPTO_BACKEND_NETTLE_TRUE='#' - CRYPTO_BACKEND_NETTLE_FALSE= + as_fn_error $? "Can not compile with blkid support, disable it by --disable-blkid." "$LINENO" 5 fi - - if test $use_internal_pbkdf2 = 1; then - CRYPTO_INTERNAL_PBKDF2_TRUE= - CRYPTO_INTERNAL_PBKDF2_FALSE='#' +fi + if test "x$enable_blkid" = "xyes"; then + HAVE_BLKID_TRUE= + HAVE_BLKID_FALSE='#' else - CRYPTO_INTERNAL_PBKDF2_TRUE='#' - CRYPTO_INTERNAL_PBKDF2_FALSE= + HAVE_BLKID_TRUE='#' + HAVE_BLKID_FALSE= fi + if test "x$enable_blkid_wipe" = "xyes"; then + HAVE_BLKID_WIPE_TRUE= + HAVE_BLKID_WIPE_FALSE='#' +else + HAVE_BLKID_WIPE_TRUE='#' + HAVE_BLKID_WIPE_FALSE= +fi -cat >>confdefs.h <<_ACEOF -#define USE_INTERNAL_PBKDF2 $use_internal_pbkdf2 -_ACEOF + if test "x$enable_blkid_step_back" = "xyes"; then + HAVE_BLKID_STEP_BACK_TRUE= + HAVE_BLKID_STEP_BACK_FALSE='#' +else + HAVE_BLKID_STEP_BACK_TRUE='#' + HAVE_BLKID_STEP_BACK_FALSE= +fi -if test x$enable_static_cryptsetup = xyes; then +if test "x$enable_static_cryptsetup" = "xyes"; then saved_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" @@ -17278,8 +19378,8 @@ fi LIBS="$saved_LIBS -static" pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEVMAPPER_STATIC" >&5 -$as_echo_n "checking for DEVMAPPER_STATIC... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for devmapper >= 1.02.27" >&5 +$as_echo_n "checking for devmapper >= 1.02.27... " >&6; } if test -n "$DEVMAPPER_STATIC_CFLAGS"; then pkg_cv_DEVMAPPER_STATIC_CFLAGS="$DEVMAPPER_STATIC_CFLAGS" @@ -17319,7 +19419,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17337,7 +19437,7 @@ fi DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS - if test "x$enable_selinux" != xno; then + if test "x$enable_selinux" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sepol_bool_set in -lsepol" >&5 $as_echo_n "checking for sepol_bool_set in -lsepol... " >&6; } if ${ac_cv_lib_sepol_sepol_bool_set+:} false; then : @@ -17432,11 +19532,11 @@ fi fi elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS - if test "x$enable_selinux" != xno; then + if test "x$enable_selinux" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sepol_bool_set in -lsepol" >&5 $as_echo_n "checking for sepol_bool_set in -lsepol... " >&6; } if ${ac_cv_lib_sepol_sepol_bool_set+:} false; then : @@ -17639,335 +19739,75 @@ fi PKG_CONFIG=$saved_PKG_CONFIG fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd tmpfiles config directory" >&5 +$as_echo_n "checking for systemd tmpfiles config directory... " >&6; } - - - - - - - - - - - - -# Check whether --enable-dev-random was given. -if test "${enable_dev_random+set}" = set; then : - enableval=$enable_dev_random; default_rng=/dev/random +if test -n "$systemd_tmpfilesdir"; then + pkg_cv_systemd_tmpfilesdir="$systemd_tmpfilesdir" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd\""; } >&5 + ($PKG_CONFIG --exists --print-errors "systemd") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_systemd_tmpfilesdir=`$PKG_CONFIG --variable="tmpfilesdir" "systemd" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - default_rng=/dev/urandom + pkg_failed=yes fi - - -cat >>confdefs.h <<_ACEOF -#define DEFAULT_RNG "$default_rng" -_ACEOF - - - - - - - - -# Check whether --enable-python was given. -if test "${enable_python+set}" = set; then : - enableval=$enable_python; with_python=$enableval -else - with_python=no + else + pkg_failed=untried fi +systemd_tmpfilesdir=$pkg_cv_systemd_tmpfilesdir - - -# Check whether --with-python_version was given. -if test "${with_python_version+set}" = set; then : - withval=$with_python_version; PYTHON_VERSION=$withval -else - PYTHON_VERSION=2.6 +if test "x$systemd_tmpfilesdir" = x""; then : + systemd_tmpfilesdir=no fi - - -if test "x$with_python" = "xyes"; then - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $systemd_tmpfilesdir" >&5 +$as_echo "$systemd_tmpfilesdir" >&6; } - if test -n "$PYTHON"; then - # If the user set $PYTHON, use it and don't search something else. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= $PYTHON_VERSION" >&5 -$as_echo_n "checking whether $PYTHON version is >= $PYTHON_VERSION... " >&6; } - prog="import sys -# split strings by '.' and convert to numeric. Append some zeros -# because we need at least 4 digits for the hex conversion. -# map returns an iterator in Python 3.0 and a list in 2.x -minver = list(map(int, '$PYTHON_VERSION'.split('.'))) + [0, 0, 0] -minverhex = 0 -# xrange is not present in Python 3.0 and range returns an iterator -for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] -sys.exit(sys.hexversion < minverhex)" - if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 - ($PYTHON -c "$prog") >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - as_fn_error $? "Python interpreter is too old" "$LINENO" 5 -fi - am_display_PYTHON=$PYTHON - else - # Otherwise, try each interpreter until we find one that satisfies - # VERSION. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= $PYTHON_VERSION" >&5 -$as_echo_n "checking for a Python interpreter with version >= $PYTHON_VERSION... " >&6; } -if ${am_cv_pathless_PYTHON+:} false; then : - $as_echo_n "(cached) " >&6 -else - - for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do - test "$am_cv_pathless_PYTHON" = none && break - prog="import sys -# split strings by '.' and convert to numeric. Append some zeros -# because we need at least 4 digits for the hex conversion. -# map returns an iterator in Python 3.0 and a list in 2.x -minver = list(map(int, '$PYTHON_VERSION'.split('.'))) + [0, 0, 0] -minverhex = 0 -# xrange is not present in Python 3.0 and range returns an iterator -for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] -sys.exit(sys.hexversion < minverhex)" - if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 - ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then : - break -fi - done -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 -$as_echo "$am_cv_pathless_PYTHON" >&6; } - # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. - if test "$am_cv_pathless_PYTHON" = none; then - PYTHON=: - else - # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. -set dummy $am_cv_pathless_PYTHON; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PYTHON+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PYTHON in - [\\/]* | ?:[\\/]*) - ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - ;; -esac -fi -PYTHON=$ac_cv_path_PYTHON -if test -n "$PYTHON"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 -$as_echo "$PYTHON" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - fi - am_display_PYTHON=$am_cv_pathless_PYTHON - fi - if test "$PYTHON" = :; then - as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 -$as_echo_n "checking for $am_display_PYTHON version... " >&6; } -if ${am_cv_python_version+:} false; then : - $as_echo_n "(cached) " >&6 -else - am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 -$as_echo "$am_cv_python_version" >&6; } - PYTHON_VERSION=$am_cv_python_version - PYTHON_PREFIX='${prefix}' - PYTHON_EXEC_PREFIX='${exec_prefix}' - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 -$as_echo_n "checking for $am_display_PYTHON platform... " >&6; } -if ${am_cv_python_platform+:} false; then : - $as_echo_n "(cached) " >&6 -else - am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 -$as_echo "$am_cv_python_platform" >&6; } - PYTHON_PLATFORM=$am_cv_python_platform - - - # Just factor out some code duplication. - am_python_setup_sysconfig="\ -import sys -# Prefer sysconfig over distutils.sysconfig, for better compatibility -# with python 3.x. See automake bug#10227. -try: - import sysconfig -except ImportError: - can_use_sysconfig = 0 -else: - can_use_sysconfig = 1 -# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: -# -try: - from platform import python_implementation - if python_implementation() == 'CPython' and sys.version[:3] == '2.7': - can_use_sysconfig = 0 -except ImportError: - pass" - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 -$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } -if ${am_cv_python_pythondir+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$prefix" = xNONE - then - am_py_prefix=$ac_default_prefix - else - am_py_prefix=$prefix - fi - am_cv_python_pythondir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - case $am_cv_python_pythondir in - $am_py_prefix*) - am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` - am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` - ;; - *) - case $am_py_prefix in - /usr|/System*) ;; - *) - am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac +# Check whether --enable-dev-random was given. +if test "${enable_dev_random+set}" = set; then : + enableval=$enable_dev_random; fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 -$as_echo "$am_cv_python_pythondir" >&6; } - pythondir=$am_cv_python_pythondir - - - pkgpythondir=\${pythondir}/$PACKAGE - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 -$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } -if ${am_cv_python_pyexecdir+:} false; then : - $as_echo_n "(cached) " >&6 +if test "x$enable_dev_random" = "xyes"; then + default_rng=/dev/random else - if test "x$exec_prefix" = xNONE - then - am_py_exec_prefix=$am_py_prefix - else - am_py_exec_prefix=$exec_prefix - fi - am_cv_python_pyexecdir=`$PYTHON -c " -$am_python_setup_sysconfig -if can_use_sysconfig: - sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) -else: - from distutils import sysconfig - sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') -sys.stdout.write(sitedir)"` - case $am_cv_python_pyexecdir in - $am_py_exec_prefix*) - am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` - am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` - ;; - *) - case $am_py_exec_prefix in - /usr|/System*) ;; - *) - am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages - ;; - esac - ;; - esac - + default_rng=/dev/urandom fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 -$as_echo "$am_cv_python_pyexecdir" >&6; } - pyexecdir=$am_cv_python_pyexecdir - - - - pkgpyexecdir=\${pyexecdir}/$PACKAGE - +cat >>confdefs.h <<_ACEOF +#define DEFAULT_RNG "$default_rng" +_ACEOF - fi - if ! test -x "$PYTHON-config" ; then - as_fn_error $? "Cannot find python development packages to build bindings" "$LINENO" 5 - fi - PYTHON_INCLUDES=$($PYTHON-config --includes) - PYTHON_LIBS=$($PYTHON-config --libs) -fi - if test "x$with_python" = "xyes"; then - PYTHON_CRYPTSETUP_TRUE= - PYTHON_CRYPTSETUP_FALSE='#' -else - PYTHON_CRYPTSETUP_TRUE='#' - PYTHON_CRYPTSETUP_FALSE= -fi @@ -18059,7 +19899,7 @@ _ACEOF else cat >>confdefs.h <<_ACEOF -#define DEFAULT_LUKS1_HASH "sha1" +#define DEFAULT_LUKS1_HASH "sha256" _ACEOF @@ -18124,6 +19964,39 @@ _ACEOF fi +# Check whether --enable-luks_adjust_xts_keysize was given. +if test "${enable_luks_adjust_xts_keysize+set}" = set; then : + enableval=$enable_luks_adjust_xts_keysize; +else + enable_luks_adjust_xts_keysize=yes +fi + +if test "x$enable_luks_adjust_xts_keysize" = "xyes"; then + +$as_echo "#define ENABLE_LUKS_ADJUST_XTS_KEYSIZE 1" >>confdefs.h + +fi + + +# Check whether --with-luks2-pbkdf was given. +if test "${with_luks2_pbkdf+set}" = set; then : + withval=$with_luks2_pbkdf; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_PBKDF "$withval" +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_PBKDF "argon2i" +_ACEOF + + + +fi + + # Check whether --with-luks1-iter-time was given. if test "${with_luks1_iter_time+set}" = set; then : withval=$with_luks1_iter_time; @@ -18135,7 +20008,103 @@ _ACEOF else cat >>confdefs.h <<_ACEOF -#define DEFAULT_LUKS1_ITER_TIME 1000 +#define DEFAULT_LUKS1_ITER_TIME 2000 +_ACEOF + + + +fi + + +# Check whether --with-luks2-iter-time was given. +if test "${with_luks2_iter_time+set}" = set; then : + withval=$with_luks2_iter_time; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_ITER_TIME $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_ITER_TIME 2000 +_ACEOF + + + +fi + + +# Check whether --with-luks2-memory-kb was given. +if test "${with_luks2_memory_kb+set}" = set; then : + withval=$with_luks2_memory_kb; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_MEMORY_KB $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_MEMORY_KB 1048576 +_ACEOF + + + +fi + + +# Check whether --with-luks2-parallel-threads was given. +if test "${with_luks2_parallel_threads+set}" = set; then : + withval=$with_luks2_parallel_threads; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_PARALLEL_THREADS $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_PARALLEL_THREADS 4 +_ACEOF + + + +fi + + + +# Check whether --with-luks2-keyslot-cipher was given. +if test "${with_luks2_keyslot_cipher+set}" = set; then : + withval=$with_luks2_keyslot_cipher; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_KEYSLOT_CIPHER "$withval" +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_KEYSLOT_CIPHER "aes-xts-plain64" +_ACEOF + + + +fi + + +# Check whether --with-luks2-keyslot-keybits was given. +if test "${with_luks2_keyslot_keybits+set}" = set; then : + withval=$with_luks2_keyslot_keybits; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_KEYSLOT_KEYBITS $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_KEYSLOT_KEYBITS 512 _ACEOF @@ -18298,8 +20267,138 @@ _ACEOF fi +# Check whether --with-verity-fec-roots was given. +if test "${with_verity_fec_roots+set}" = set; then : + withval=$with_verity_fec_roots; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_VERITY_FEC_ROOTS $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_VERITY_FEC_ROOTS 2 +_ACEOF + + + +fi + + + +# Check whether --with-tmpfilesdir was given. +if test "${with_tmpfilesdir+set}" = set; then : + withval=$with_tmpfilesdir; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_TMPFILESDIR "$withval" +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_TMPFILESDIR "" +_ACEOF + + + +fi + +test -z "$with_tmpfilesdir" && with_tmpfilesdir=$systemd_tmpfilesdir +test "x$with_tmpfilesdir" = "xno" || { + + case "${with_tmpfilesdir}" in + /*) ;; + *) as_fn_error $? "with-tmpfilesdir argument must be an absolute path." "$LINENO" 5;; + esac + + DEFAULT_TMPFILESDIR=$with_tmpfilesdir + +} + if test -n "$DEFAULT_TMPFILESDIR"; then + CRYPTSETUP_TMPFILE_TRUE= + CRYPTSETUP_TMPFILE_FALSE='#' +else + CRYPTSETUP_TMPFILE_TRUE='#' + CRYPTSETUP_TMPFILE_FALSE= +fi + + + +# Check whether --with-luks2-lock-path was given. +if test "${with_luks2_lock_path+set}" = set; then : + withval=$with_luks2_lock_path; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_LOCK_PATH "$withval" +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_LOCK_PATH "/run/cryptsetup" +_ACEOF + + + +fi + +test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup + + case "${with_luks2_lock_path}" in + /*) ;; + *) as_fn_error $? "with-luks2-lock-path argument must be an absolute path." "$LINENO" 5;; + esac + +DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path + + + +# Check whether --with-luks2-lock-dir-perms was given. +if test "${with_luks2_lock_dir_perms+set}" = set; then : + withval=$with_luks2_lock_dir_perms; +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_LOCK_DIR_PERMS $withval +_ACEOF + + +else + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS2_LOCK_DIR_PERMS 0700 +_ACEOF + + + +fi + +test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700 +DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms + + + +# Check whether --with-default_luks_format was given. +if test "${with_default_luks_format+set}" = set; then : + withval=$with_default_luks_format; +else + with_default_luks_format=LUKS2 +fi + + +case $with_default_luks_format in + LUKS1) default_luks=CRYPT_LUKS1 ;; + LUKS2) default_luks=CRYPT_LUKS2 ;; + *) as_fn_error $? "Unknown default LUKS format. Use LUKS1 or LUKS2 only." "$LINENO" 5 ;; +esac + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_LUKS_FORMAT $default_luks +_ACEOF + + -ac_config_files="$ac_config_files Makefile lib/Makefile lib/libcryptsetup.pc lib/crypto_backend/Makefile lib/luks1/Makefile lib/loopaes/Makefile lib/verity/Makefile lib/tcrypt/Makefile src/Makefile po/Makefile.in man/Makefile tests/Makefile python/Makefile" +ac_config_files="$ac_config_files Makefile lib/libcryptsetup.pc po/Makefile.in scripts/cryptsetup.conf tests/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -18438,11 +20537,19 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${KERNEL_KEYRING_TRUE}" && test -z "${KERNEL_KEYRING_FALSE}"; then + as_fn_error $? "conditional \"KERNEL_KEYRING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${STATIC_TOOLS_TRUE}" && test -z "${STATIC_TOOLS_FALSE}"; then as_fn_error $? "conditional \"STATIC_TOOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${CRYPTSETUP_TRUE}" && test -z "${CRYPTSETUP_FALSE}"; then + as_fn_error $? "conditional \"CRYPTSETUP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${VERITYSETUP_TRUE}" && test -z "${VERITYSETUP_FALSE}"; then as_fn_error $? "conditional \"VERITYSETUP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18451,6 +20558,10 @@ if test -z "${REENCRYPT_TRUE}" && test -z "${REENCRYPT_FALSE}"; then as_fn_error $? "conditional \"REENCRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${INTEGRITYSETUP_TRUE}" && test -z "${INTEGRITYSETUP_FALSE}"; then + as_fn_error $? "conditional \"INTEGRITYSETUP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${CRYPTO_BACKEND_GCRYPT_TRUE}" && test -z "${CRYPTO_BACKEND_GCRYPT_FALSE}"; then as_fn_error $? "conditional \"CRYPTO_BACKEND_GCRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18475,8 +20586,28 @@ if test -z "${CRYPTO_INTERNAL_PBKDF2_TRUE}" && test -z "${CRYPTO_INTERNAL_PBKDF2 as_fn_error $? "conditional \"CRYPTO_INTERNAL_PBKDF2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${PYTHON_CRYPTSETUP_TRUE}" && test -z "${PYTHON_CRYPTSETUP_FALSE}"; then - as_fn_error $? "conditional \"PYTHON_CRYPTSETUP\" was never defined. +if test -z "${CRYPTO_INTERNAL_ARGON2_TRUE}" && test -z "${CRYPTO_INTERNAL_ARGON2_FALSE}"; then + as_fn_error $? "conditional \"CRYPTO_INTERNAL_ARGON2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CRYPTO_INTERNAL_SSE_ARGON2_TRUE}" && test -z "${CRYPTO_INTERNAL_SSE_ARGON2_FALSE}"; then + as_fn_error $? "conditional \"CRYPTO_INTERNAL_SSE_ARGON2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_BLKID_TRUE}" && test -z "${HAVE_BLKID_FALSE}"; then + as_fn_error $? "conditional \"HAVE_BLKID\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_BLKID_WIPE_TRUE}" && test -z "${HAVE_BLKID_WIPE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_BLKID_WIPE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_BLKID_STEP_BACK_TRUE}" && test -z "${HAVE_BLKID_STEP_BACK_FALSE}"; then + as_fn_error $? "conditional \"HAVE_BLKID_STEP_BACK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CRYPTSETUP_TMPFILE_TRUE}" && test -z "${CRYPTSETUP_TMPFILE_FALSE}"; then + as_fn_error $? "conditional \"CRYPTSETUP_TMPFILE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -18876,7 +21007,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by cryptsetup $as_me 1.6.7, which was +This file was extended by cryptsetup $as_me 2.3.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18942,7 +21073,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -cryptsetup config.status 1.6.7 +cryptsetup config.status 2.3.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -19061,7 +21192,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout @@ -19077,6 +21208,7 @@ macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' @@ -19126,10 +21258,13 @@ compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' @@ -19194,7 +21329,8 @@ finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' @@ -19245,9 +21381,12 @@ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ nm_file_list_spec \ +lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ @@ -19282,7 +21421,7 @@ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -19309,10 +21448,11 @@ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec; do +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -19321,19 +21461,16 @@ sys_lib_dlsearch_path_spec; do done ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' @@ -19360,18 +21497,10 @@ do "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "lib/libcryptsetup.pc") CONFIG_FILES="$CONFIG_FILES lib/libcryptsetup.pc" ;; - "lib/crypto_backend/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto_backend/Makefile" ;; - "lib/luks1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/luks1/Makefile" ;; - "lib/loopaes/Makefile") CONFIG_FILES="$CONFIG_FILES lib/loopaes/Makefile" ;; - "lib/verity/Makefile") CONFIG_FILES="$CONFIG_FILES lib/verity/Makefile" ;; - "lib/tcrypt/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tcrypt/Makefile" ;; - "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; - "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "scripts/cryptsetup.conf") CONFIG_FILES="$CONFIG_FILES scripts/cryptsetup.conf" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; - "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -19971,29 +22100,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -20011,106 +22146,100 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)$/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; "libtool":C) - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . # The names of the tagged configurations supported by this script. -available_tags="" +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG @@ -20130,6 +22259,9 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + # Shell to use when invoking shell scripts. SHELL=$lt_SHELL @@ -20247,18 +22379,27 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec -# The root where to search for dependent libraries,and in which our libraries should be installed. +# The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + # The name of the directory that contains temporary libtool files. objdir=$objdir @@ -20349,8 +22490,11 @@ hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -20443,13 +22587,13 @@ hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -20501,13 +22645,72 @@ hardcode_action=$hardcode_action _LT_EOF + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -20516,7 +22719,7 @@ _LT_EOF esac -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if @@ -20526,165 +22729,6 @@ ltmain="$ac_aux_dir/ltmain.sh" sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - if test x"$xsi_shell" = xyes; then - sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ -func_dirname ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_basename ()$/,/^} # func_basename /c\ -func_basename ()\ -{\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ -func_dirname_and_basename ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ -func_stripname ()\ -{\ -\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ -\ # positional parameters, so assign one to ordinary parameter first.\ -\ func_stripname_result=${3}\ -\ func_stripname_result=${func_stripname_result#"${1}"}\ -\ func_stripname_result=${func_stripname_result%"${2}"}\ -} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ -func_split_long_opt ()\ -{\ -\ func_split_long_opt_name=${1%%=*}\ -\ func_split_long_opt_arg=${1#*=}\ -} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ -func_split_short_opt ()\ -{\ -\ func_split_short_opt_arg=${1#??}\ -\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ -} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ -func_lo2o ()\ -{\ -\ case ${1} in\ -\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ -\ *) func_lo2o_result=${1} ;;\ -\ esac\ -} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_xform ()$/,/^} # func_xform /c\ -func_xform ()\ -{\ - func_xform_result=${1%.*}.lo\ -} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_arith ()$/,/^} # func_arith /c\ -func_arith ()\ -{\ - func_arith_result=$(( $* ))\ -} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_len ()$/,/^} # func_len /c\ -func_len ()\ -{\ - func_len_result=${#1}\ -} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - -fi - -if test x"$lt_shell_append" = xyes; then - sed -e '/^func_append ()$/,/^} # func_append /c\ -func_append ()\ -{\ - eval "${1}+=\\${2}"\ -} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ -func_append_quoted ()\ -{\ -\ func_quote_for_eval "${2}"\ -\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ -} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 -$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} -fi - - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -20700,7 +22744,7 @@ fi case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. @@ -20716,7 +22760,8 @@ fi if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" - cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration @@ -20727,12 +22772,12 @@ fi test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` - # Hide the ALL_LINGUAS assigment from automake < 1.5. + # Hide the ALL_LINGUAS assignment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. - # Hide the ALL_LINGUAS assigment from automake < 1.5. + # Hide the ALL_LINGUAS assignment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES diff --git a/configure.ac b/configure.ac index 05574d2..0d2fa63 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ AC_PREREQ([2.67]) -AC_INIT([cryptsetup],[1.6.7]) +AC_INIT([cryptsetup],[2.3.3]) dnl library version from ..[-] LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-) -LIBCRYPTSETUP_VERSION_INFO=11:0:7 +LIBCRYPTSETUP_VERSION_INFO=18:0:6 AM_SILENT_RULES([yes]) AC_CONFIG_SRCDIR(src/cryptsetup.c) @@ -15,8 +15,8 @@ AC_CONFIG_HEADERS([config.h:config.h.in]) # http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html # For old automake use this -#AM_INIT_AUTOMAKE(dist-xz) -AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests]) +#AM_INIT_AUTOMAKE(dist-xz subdir-objects) +AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects]) if test "x$prefix" = "xNONE"; then sysconfdir=/etc @@ -33,24 +33,77 @@ AC_PROG_MAKE_SET AC_ENABLE_STATIC(no) LT_INIT PKG_PROG_PKG_CONFIG +AM_ICONV + +dnl ========================================================================== +dnl define PKG_CHECK_VAR for old pkg-config <= 0.28 +m4_ifndef([AS_VAR_COPY], +[m4_define([AS_VAR_COPY], +[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])]) +]) +m4_ifndef([PKG_CHECK_VAR], [ +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config]) + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4]) +]) +]) +dnl ========================================================================== + +AC_C_RESTRICT AC_HEADER_DIRENT AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \ - ctype.h unistd.h locale.h byteswap.h endian.h) + sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h) +AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])], +[[ +#ifdef HAVE_FCNTL_H +# include +#endif +]]) AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])]) AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])]) +AC_ARG_ENABLE([keyring], + AS_HELP_STRING([--disable-keyring], [disable kernel keyring support and builtin kernel keyring token]), + [], [enable_keyring=yes]) +if test "x$enable_keyring" = "xyes"; then + AC_CHECK_HEADERS(linux/keyctl.h,,[AC_MSG_ERROR([You need Linux kernel headers with kernel keyring service compiled.])]) + + dnl ========================================================================== + dnl check whether kernel is compiled with kernel keyring service syscalls + AC_CHECK_DECL(__NR_add_key,,[AC_MSG_ERROR([The kernel is missing add_key syscall.])], [#include ]) + AC_CHECK_DECL(__NR_keyctl,,[AC_MSG_ERROR([The kernel is missing keyctl syscall.])], [#include ]) + AC_CHECK_DECL(__NR_request_key,,[AC_MSG_ERROR([The kernel is missing request_key syscall.])], [#include ]) + + dnl ========================================================================== + dnl check that key_serial_t hasn't been adopted yet in stdlib + AC_CHECK_TYPES([key_serial_t], [], [], [ + AC_INCLUDES_DEFAULT + #ifdef HAVE_LINUX_KEYCTL_H + # include + #endif + ]) + + AC_DEFINE(KERNEL_KEYRING, 1, [Enable kernel keyring service support]) +fi +AM_CONDITIONAL(KERNEL_KEYRING, test "x$enable_keyring" = "xyes") + saved_LIBS=$LIBS AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])]) AC_SUBST(UUID_LIBS, $LIBS) LIBS=$saved_LIBS AC_SEARCH_LIBS([clock_gettime],[rt posix4]) -AC_CHECK_FUNCS([posix_memalign clock_gettime]) +AC_CHECK_FUNCS([posix_memalign clock_gettime posix_fallocate explicit_bzero]) -if test "x$enable_largefile" = "xno" ; then +if test "x$enable_largefile" = "xno"; then AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.]) fi @@ -65,7 +118,7 @@ AC_FUNC_STRERROR_R dnl ========================================================================== AM_GNU_GETTEXT([external],[need-ngettext]) -AM_GNU_GETTEXT_VERSION([0.15]) +AM_GNU_GETTEXT_VERSION([0.18.3]) dnl ========================================================================== @@ -76,12 +129,10 @@ AC_SUBST(POPT_LIBS, $LIBS) LIBS=$saved_LIBS dnl ========================================================================== -dnl FIPS extensions (only for RHEL) -AC_ARG_ENABLE([fips], AS_HELP_STRING([--enable-fips],[enable FIPS mode restrictions]), -[with_fips=$enableval], -[with_fips=no]) - -if test "x$with_fips" = "xyes"; then +dnl FIPS extensions +AC_ARG_ENABLE([fips], + AS_HELP_STRING([--enable-fips], [enable FIPS mode restrictions])) +if test "x$enable_fips" = "xyes"; then AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions]) if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then @@ -90,19 +141,18 @@ if test "x$with_fips" = "xyes"; then fi AC_DEFUN([NO_FIPS], [ - if test "x$with_fips" = "xyes"; then + if test "x$enable_fips" = "xyes"; then AC_MSG_ERROR([This option is not compatible with FIPS.]) fi ]) dnl ========================================================================== dnl pwquality library (cryptsetup CLI only) -AC_ARG_ENABLE([pwquality], AS_HELP_STRING([--enable-pwquality],[enable password quality checking]), -[with_pwquality=$enableval], -[with_pwquality=no]) +AC_ARG_ENABLE([pwquality], + AS_HELP_STRING([--enable-pwquality], [enable password quality checking using pwquality library])) -if test "x$with_pwquality" = "xyes"; then - AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking]) +if test "x$enable_pwquality" = "xyes"; then + AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking using pwquality library]) PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],, AC_MSG_ERROR([You need pwquality library.])) @@ -111,23 +161,52 @@ if test "x$with_pwquality" = "xyes"; then fi dnl ========================================================================== +dnl passwdqc library (cryptsetup CLI only) +AC_ARG_ENABLE([passwdqc], + AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@], + [enable password quality checking using passwdqc library (optionally with CONFIG_PATH)])) + +case "$enable_passwdqc" in + ""|yes|no) use_passwdqc_config="" ;; + /*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;; + *) AC_MSG_ERROR([Unrecognized --enable-passwdqc parameter.]) ;; +esac +AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc library config file]) + +if test "x$enable_passwdqc" = "xyes"; then + AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library]) + + PASSWDQC_LIBS="-lpasswdqc" +fi + +if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then + AC_MSG_ERROR([--enable-pwquality and --enable-passwdqc are mutually incompatible.]) +fi + +dnl ========================================================================== dnl Crypto backend functions AC_DEFUN([CONFIGURE_GCRYPT], [ - if test "x$with_fips" = "xyes"; then + if test "x$enable_fips" = "xyes"; then GCRYPT_REQ_VERSION=1.4.5 else GCRYPT_REQ_VERSION=1.1.42 fi - dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password) - AC_ARG_ENABLE([gcrypt-pbkdf2], AS_HELP_STRING([--enable-gcrypt-pbkdf2],[force enable internal gcrypt PBKDF2]), + + dnl libgcrypt rejects to use pkgconfig, use AM_PATH_LIBGCRYPT from gcrypt-devel here. + dnl Do not require gcrypt-devel if other crypto backend is used. + m4_ifdef([AM_PATH_LIBGCRYPT],[ + AC_ARG_ENABLE([gcrypt-pbkdf2], + dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password) + AS_HELP_STRING([--enable-gcrypt-pbkdf2], [force enable internal gcrypt PBKDF2]), if test "x$enableval" = "xyes"; then [use_internal_pbkdf2=0] else [use_internal_pbkdf2=1] fi, [AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])]) - AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])]) + AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])], + AC_MSG_ERROR([Missing support for gcrypt: install gcrypt and regenerate configure.])) AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in]) if test $use_internal_pbkdf2 = 0; then @@ -137,7 +216,9 @@ AC_DEFUN([CONFIGURE_GCRYPT], [ NO_FIPS([]) fi - if test x$enable_static_cryptsetup = xyes; then + AC_CHECK_DECLS([GCRY_CIPHER_MODE_XTS], [], [], [#include ]) + + if test "x$enable_static_cryptsetup" = "xyes"; then saved_LIBS=$LIBS LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static" AC_CHECK_LIB(gcrypt, gcry_check_version,, @@ -161,18 +242,17 @@ AC_DEFUN([CONFIGURE_OPENSSL], [ CRYPTO_LIBS=$OPENSSL_LIBS use_internal_pbkdf2=0 - if test x$enable_static_cryptsetup = xyes; then + if test "x$enable_static_cryptsetup" = "xyes"; then saved_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl]) CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS PKG_CONFIG=$saved_PKG_CONFIG fi - NO_FIPS([]) ]) AC_DEFUN([CONFIGURE_NSS], [ - if test x$enable_static_cryptsetup = xyes; then + if test "x$enable_static_cryptsetup" = "xyes"; then AC_MSG_ERROR([Static build of cryptsetup is not supported with NSS.]) fi @@ -205,6 +285,7 @@ AC_DEFUN([CONFIGURE_KERNEL], [ AC_DEFUN([CONFIGURE_NETTLE], [ AC_CHECK_HEADERS(nettle/sha.h,, [AC_MSG_ERROR([You need Nettle cryptographic library.])]) + AC_CHECK_HEADERS(nettle/version.h) saved_LIBS=$LIBS AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,, @@ -221,33 +302,42 @@ dnl ========================================================================== saved_LIBS=$LIBS AC_ARG_ENABLE([static-cryptsetup], - AS_HELP_STRING([--enable-static-cryptsetup], - [enable build of static cryptsetup binary])) -if test x$enable_static_cryptsetup = xyes; then - if test x$enable_static = xno; then + AS_HELP_STRING([--enable-static-cryptsetup], [enable build of static version of tools])) +if test "x$enable_static_cryptsetup" = "xyes"; then + if test "x$enable_static" = "xno"; then AC_MSG_WARN([Requested static cryptsetup build, enabling static library.]) enable_static=yes fi fi -AM_CONDITIONAL(STATIC_TOOLS, test x$enable_static_cryptsetup = xyes) +AM_CONDITIONAL(STATIC_TOOLS, test "x$enable_static_cryptsetup" = "xyes") + +AC_ARG_ENABLE([cryptsetup], + AS_HELP_STRING([--disable-cryptsetup], [disable cryptsetup support]), + [], [enable_cryptsetup=yes]) +AM_CONDITIONAL(CRYPTSETUP, test "x$enable_cryptsetup" = "xyes") -AC_ARG_ENABLE(veritysetup, - AS_HELP_STRING([--disable-veritysetup], - [disable veritysetup support]),[], [enable_veritysetup=yes]) -AM_CONDITIONAL(VERITYSETUP, test x$enable_veritysetup = xyes) +AC_ARG_ENABLE([veritysetup], + AS_HELP_STRING([--disable-veritysetup], [disable veritysetup support]), + [], [enable_veritysetup=yes]) +AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes") AC_ARG_ENABLE([cryptsetup-reencrypt], - AS_HELP_STRING([--enable-cryptsetup-reencrypt], - [enable cryptsetup-reencrypt tool])) -AM_CONDITIONAL(REENCRYPT, test x$enable_cryptsetup_reencrypt = xyes) + AS_HELP_STRING([--disable-cryptsetup-reencrypt], [disable cryptsetup-reencrypt tool]), + [], [enable_cryptsetup_reencrypt=yes]) +AM_CONDITIONAL(REENCRYPT, test "x$enable_cryptsetup_reencrypt" = "xyes") -AC_ARG_ENABLE(selinux, - AS_HELP_STRING([--disable-selinux], - [disable selinux support [default=auto]]),[], []) +AC_ARG_ENABLE([integritysetup], + AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]), + [], [enable_integritysetup=yes]) +AM_CONDITIONAL(INTEGRITYSETUP, test "x$enable_integritysetup" = "xyes") + +AC_ARG_ENABLE([selinux], + AS_HELP_STRING([--disable-selinux], [disable selinux support [default=auto]]), + [], [enable_selinux=yes]) AC_ARG_ENABLE([udev], - AS_HELP_STRING([--disable-udev], - [disable udev support]),[], enable_udev=yes) + AS_HELP_STRING([--disable-udev], [disable udev support]), + [], [enable_udev=yes]) dnl Try to use pkg-config for devmapper, but fallback to old detection PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [ @@ -262,6 +352,11 @@ LIBS=$saved_LIBS LIBS="$LIBS $DEVMAPPER_LIBS" AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include ]) AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include ]) +AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include ]) +AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include ]) +AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include ]) +AC_CHECK_DECLS([dm_device_get_name], [], [], [#include ]) +AC_CHECK_DECLS([DM_DEVICE_GET_TARGET_VERSION], [], [], [#include ]) AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include ]) if test "x$enable_udev" = xyes; then if test "x$have_cookie" = xno; then @@ -272,19 +367,22 @@ if test "x$enable_udev" = xyes; then fi LIBS=$saved_LIBS +dnl Check for JSON-C used in LUKS2 +PKG_CHECK_MODULES([JSON_C], [json-c]) +AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include ]) +AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include ]) + dnl Crypto backend configuration. AC_ARG_WITH([crypto_backend], - AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [gcrypt]]), - [], with_crypto_backend=gcrypt -) + AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]), + [], [with_crypto_backend=openssl]) dnl Kernel crypto API backend needed for benchmark and tcrypt -AC_ARG_ENABLE([kernel_crypto], AS_HELP_STRING([--disable-kernel_crypto], - [disable kernel userspace crypto (no benchmark and tcrypt)]), - [with_kernel_crypto=$enableval], - [with_kernel_crypto=yes]) +AC_ARG_ENABLE([kernel_crypto], + AS_HELP_STRING([--disable-kernel_crypto], [disable kernel userspace crypto (no benchmark and tcrypt)]), + [], [enable_kernel_crypto=yes]) -if test "x$with_kernel_crypto" = "xyes"; then +if test "x$enable_kernel_crypto" = "xyes"; then AC_CHECK_HEADERS(linux/if_alg.h,, [AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)])]) AC_DEFINE(ENABLE_AF_ALG, 1, [Enable using of kernel userspace crypto]) @@ -298,17 +396,88 @@ case $with_crypto_backend in nettle) CONFIGURE_NETTLE([]) ;; *) AC_MSG_ERROR([Unknown crypto backend.]) ;; esac -AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test $with_crypto_backend = gcrypt) -AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test $with_crypto_backend = openssl) -AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test $with_crypto_backend = nss) -AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test $with_crypto_backend = kernel) -AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test $with_crypto_backend = nettle) +AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test "$with_crypto_backend" = "gcrypt") +AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test "$with_crypto_backend" = "openssl") +AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test "$with_crypto_backend" = "nss") +AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test "$with_crypto_backend" = "kernel") +AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test "$with_crypto_backend" = "nettle") AM_CONDITIONAL(CRYPTO_INTERNAL_PBKDF2, test $use_internal_pbkdf2 = 1) AC_DEFINE_UNQUOTED(USE_INTERNAL_PBKDF2, [$use_internal_pbkdf2], [Use internal PBKDF2]) +dnl Argon2 implementation +AC_ARG_ENABLE([internal-argon2], + AS_HELP_STRING([--disable-internal-argon2], [disable internal implementation of Argon2 PBKDF]), + [], [enable_internal_argon2=yes]) + +AC_ARG_ENABLE([libargon2], + AS_HELP_STRING([--enable-libargon2], [enable external libargon2 (PHC) library (disables internal bundled version)])) + +if test "x$enable_libargon2" = "xyes" ; then + AC_CHECK_HEADERS(argon2.h,, + [AC_MSG_ERROR([You need libargon2 development library installed.])]) + AC_CHECK_DECL(Argon2_id,,[AC_MSG_ERROR([You need more recent Argon2 library with support for Argon2id.])], [#include ]) + PKG_CHECK_MODULES([LIBARGON2], [libargon2],,[LIBARGON2_LIBS="-largon2"]) + enable_internal_argon2=no +else + AC_MSG_WARN([Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2.]) + + AC_ARG_ENABLE([internal-sse-argon2], + AS_HELP_STRING([--enable-internal-sse-argon2], [enable internal SSE implementation of Argon2 PBKDF])) + + if test "x$enable_internal_sse_argon2" = "xyes"; then + AC_MSG_CHECKING(if Argon2 SSE optimization can be used) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include + __m128i testfunc(__m128i *a, __m128i *b) { + return _mm_xor_si128(_mm_loadu_si128(a), _mm_loadu_si128(b)); + } + ]])],,[enable_internal_sse_argon2=no]) + AC_MSG_RESULT($enable_internal_sse_argon2) + fi +fi + +if test "x$enable_internal_argon2" = "xyes"; then + AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2]) +fi +AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test "x$enable_internal_argon2" = "xyes") +AM_CONDITIONAL(CRYPTO_INTERNAL_SSE_ARGON2, test "x$enable_internal_sse_argon2" = "xyes") + +dnl Link with blkid to check for other device types +AC_ARG_ENABLE([blkid], + AS_HELP_STRING([--disable-blkid], [disable use of blkid for device signature detection and wiping]), + [], [enable_blkid=yes]) + +if test "x$enable_blkid" = "xyes"; then + PKG_CHECK_MODULES([BLKID], [blkid],[AC_DEFINE([HAVE_BLKID], 1, [Define to 1 to use blkid for detection of disk signatures.])],[LIBBLKID_LIBS="-lblkid"]) + + AC_CHECK_HEADERS(blkid/blkid.h,,[AC_MSG_ERROR([You need blkid development library installed.])]) + AC_CHECK_DECL([blkid_do_wipe], + [ AC_DEFINE([HAVE_BLKID_WIPE], 1, [Define to 1 to use blkid_do_wipe.]) + enable_blkid_wipe=yes + ],, + [#include ]) + AC_CHECK_DECL([blkid_probe_step_back], + [ AC_DEFINE([HAVE_BLKID_STEP_BACK], 1, [Define to 1 to use blkid_probe_step_back.]) + enable_blkid_step_back=yes + ],, + [#include ]) + AC_CHECK_DECLS([ blkid_reset_probe, + blkid_probe_set_device, + blkid_probe_filter_superblocks_type, + blkid_do_safeprobe, + blkid_do_probe, + blkid_probe_lookup_value + ],, + [AC_MSG_ERROR([Can not compile with blkid support, disable it by --disable-blkid.])], + [#include ]) +fi +AM_CONDITIONAL(HAVE_BLKID, test "x$enable_blkid" = "xyes") +AM_CONDITIONAL(HAVE_BLKID_WIPE, test "x$enable_blkid_wipe" = "xyes") +AM_CONDITIONAL(HAVE_BLKID_STEP_BACK, test "x$enable_blkid_step_back" = "xyes") + dnl Magic for cryptsetup.static build. -if test x$enable_static_cryptsetup = xyes; then +if test "x$enable_static_cryptsetup" = "xyes"; then saved_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" @@ -320,7 +489,7 @@ if test x$enable_static_cryptsetup = xyes; then LIBS="$saved_LIBS -static" PKG_CHECK_MODULES([DEVMAPPER_STATIC], [devmapper >= 1.02.27],,[ DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS - if test "x$enable_selinux" != xno; then + if test "x$enable_selinux" = "xyes"; then AC_CHECK_LIB(sepol, sepol_bool_set) AC_CHECK_LIB(selinux, is_selinux_enabled) DEVMAPPER_STATIC_LIBS="$DEVMAPPER_STATIC_LIBS $LIBS" @@ -339,23 +508,37 @@ if test x$enable_static_cryptsetup = xyes; then PKG_CONFIG=$saved_PKG_CONFIG fi +AC_MSG_CHECKING([for systemd tmpfiles config directory]) +PKG_CHECK_VAR([systemd_tmpfilesdir], [systemd], [tmpfilesdir], [], [systemd_tmpfilesdir=no]) +AC_MSG_RESULT([$systemd_tmpfilesdir]) + AC_SUBST([DEVMAPPER_LIBS]) AC_SUBST([DEVMAPPER_STATIC_LIBS]) AC_SUBST([PWQUALITY_LIBS]) AC_SUBST([PWQUALITY_STATIC_LIBS]) +AC_SUBST([PASSWDQC_LIBS]) + AC_SUBST([CRYPTO_CFLAGS]) AC_SUBST([CRYPTO_LIBS]) AC_SUBST([CRYPTO_STATIC_LIBS]) +AC_SUBST([JSON_C_LIBS]) +AC_SUBST([LIBARGON2_LIBS]) +AC_SUBST([BLKID_LIBS]) + AC_SUBST([LIBCRYPTSETUP_VERSION]) AC_SUBST([LIBCRYPTSETUP_VERSION_INFO]) dnl ========================================================================== -AC_ARG_ENABLE([dev-random], AS_HELP_STRING([--enable-dev-random], -[use blocking /dev/random by default for key generator (otherwise use /dev/urandom)]), -[default_rng=/dev/random], [default_rng=/dev/urandom]) +AC_ARG_ENABLE([dev-random], + AS_HELP_STRING([--enable-dev-random], [use /dev/random by default for key generation (otherwise use /dev/urandom)])) +if test "x$enable_dev_random" = "xyes"; then + default_rng=/dev/random +else + default_rng=/dev/urandom +fi AC_DEFINE_UNQUOTED(DEFAULT_RNG, ["$default_rng"], [default RNG type for key generator]) dnl ========================================================================== @@ -375,30 +558,12 @@ AC_DEFUN([CS_NUM_WITH], [AC_ARG_WITH([$1], [CS_DEFINE([$1], [$3], [$2])] )]) -dnl ========================================================================== -dnl Python bindings -AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings]), -[with_python=$enableval], -[with_python=no]) - -AC_ARG_WITH([python_version], - AS_HELP_STRING([--with-python_version=VERSION], [required Python version [2.6]]), - [PYTHON_VERSION=$withval], [PYTHON_VERSION=2.6]) - -if test "x$with_python" = "xyes"; then - AM_PATH_PYTHON([$PYTHON_VERSION]) - - if ! test -x "$PYTHON-config" ; then - AC_MSG_ERROR([Cannot find python development packages to build bindings]) - fi - - PYTHON_INCLUDES=$($PYTHON-config --includes) - AC_SUBST(PYTHON_INCLUDES) - - PYTHON_LIBS=$($PYTHON-config --libs) - AC_SUBST(PYTHON_LIBS) -fi -AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"]) +AC_DEFUN([CS_ABSPATH], [ + case "$1" in + /*) ;; + *) AC_MSG_ERROR([$2 argument must be an absolute path.]);; + esac +]) dnl ========================================================================== CS_STR_WITH([plain-hash], [password hashing function for plain mode], [ripemd160]) @@ -406,11 +571,26 @@ CS_STR_WITH([plain-cipher], [cipher for plain mode], [aes]) CS_STR_WITH([plain-mode], [cipher mode for plain mode], [cbc-essiv:sha256]) CS_NUM_WITH([plain-keybits],[key length in bits for plain mode], [256]) -CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha1]) +CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256]) CS_STR_WITH([luks1-cipher], [cipher for LUKS1], [aes]) CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [xts-plain64]) CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256]) -CS_NUM_WITH([luks1-iter-time],[PBKDF2 iteration time for LUKS1 (in ms)], [1000]) + +AC_ARG_ENABLE([luks_adjust_xts_keysize], AS_HELP_STRING([--disable-luks-adjust-xts-keysize], + [XTS mode requires two keys, double default LUKS keysize if needed]), + [], [enable_luks_adjust_xts_keysize=yes]) +if test "x$enable_luks_adjust_xts_keysize" = "xyes"; then + AC_DEFINE(ENABLE_LUKS_ADJUST_XTS_KEYSIZE, 1, [XTS mode - double default LUKS keysize if needed]) +fi + +CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2i]) +CS_NUM_WITH([luks1-iter-time], [PBKDF2 iteration time for LUKS1 (in ms)], [2000]) +CS_NUM_WITH([luks2-iter-time], [Argon2 PBKDF iteration time for LUKS2 (in ms)], [2000]) +CS_NUM_WITH([luks2-memory-kb], [Argon2 PBKDF memory cost for LUKS2 (in kB)], [1048576]) +CS_NUM_WITH([luks2-parallel-threads],[Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available)], [4]) + +CS_STR_WITH([luks2-keyslot-cipher], [fallback cipher for LUKS2 keyslot (if data encryption is incompatible)], [aes-xts-plain64]) +CS_NUM_WITH([luks2-keyslot-keybits],[fallback key size for LUKS2 keyslot (if data encryption is incompatible)], [512]) CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes]) CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256]) @@ -422,21 +602,46 @@ CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256]) CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096]) CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096]) CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32]) +CS_NUM_WITH([verity-fec-roots], [parity bytes for verity FEC], [2]) + +CS_STR_WITH([tmpfilesdir], [override default path to directory with systemd temporary files], []) +test -z "$with_tmpfilesdir" && with_tmpfilesdir=$systemd_tmpfilesdir +test "x$with_tmpfilesdir" = "xno" || { + CS_ABSPATH([${with_tmpfilesdir}],[with-tmpfilesdir]) + DEFAULT_TMPFILESDIR=$with_tmpfilesdir + AC_SUBST(DEFAULT_TMPFILESDIR) +} +AM_CONDITIONAL(CRYPTSETUP_TMPFILE, test -n "$DEFAULT_TMPFILESDIR") + +CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/cryptsetup]) +test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup +CS_ABSPATH([${with_luks2_lock_path}],[with-luks2-lock-path]) +DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path +AC_SUBST(DEFAULT_LUKS2_LOCK_PATH) + +CS_NUM_WITH([luks2-lock-dir-perms], [default luks2 locking directory permissions], [0700]) +test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700 +DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms +AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS) + +dnl Override default LUKS format version (for cryptsetup or cryptsetup-reencrypt format actions only). +AC_ARG_WITH([default_luks_format], + AS_HELP_STRING([--with-default-luks-format=FORMAT], [default LUKS format version (LUKS1/LUKS2) [LUKS2]]), + [], [with_default_luks_format=LUKS2]) + +case $with_default_luks_format in + LUKS1) default_luks=CRYPT_LUKS1 ;; + LUKS2) default_luks=CRYPT_LUKS2 ;; + *) AC_MSG_ERROR([Unknown default LUKS format. Use LUKS1 or LUKS2 only.]) ;; +esac +AC_DEFINE_UNQUOTED([DEFAULT_LUKS_FORMAT], [$default_luks], [default LUKS format version]) dnl ========================================================================== AC_CONFIG_FILES([ Makefile -lib/Makefile lib/libcryptsetup.pc -lib/crypto_backend/Makefile -lib/luks1/Makefile -lib/loopaes/Makefile -lib/verity/Makefile -lib/tcrypt/Makefile -src/Makefile po/Makefile.in -man/Makefile +scripts/cryptsetup.conf tests/Makefile -python/Makefile ]) AC_OUTPUT diff --git a/depcomp b/depcomp index 4ebd5b3..6b39162 100755 --- a/depcomp +++ b/depcomp @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -783,9 +783,9 @@ exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/docs/ChangeLog.old b/docs/ChangeLog.old index e51d362..7a4027c 100644 --- a/docs/ChangeLog.old +++ b/docs/ChangeLog.old @@ -178,7 +178,7 @@ * Document cryptsetup exit codes. 2011-03-18 Milan Broz - * Respect maximum keyfile size paramater. + * Respect maximum keyfile size parameter. * Introduce maximum default keyfile size, add configure option. * Require the whole key read from keyfile in create command (broken in 1.2.0). * Fix offset option for loopaesOpen. @@ -195,7 +195,7 @@ 2011-03-05 Milan Broz * Add exception to COPYING for binary distribution linked with OpenSSL library. - * Set secure data flag (wipe all ioclt buffers) if devmapper library supports it. + * Set secure data flag (wipe all ioctl buffers) if devmapper library supports it. 2011-01-29 Milan Broz * Fix mapping removal if device disappeared but node still exists. @@ -334,13 +334,13 @@ * Version 1.1.0. 2010-01-10 Milan Broz - * Fix initialisation of gcrypt duting luksFormat. - * Convert hash name to lower case in header (fix sha1 backward comatible header) + * Fix initialisation of gcrypt during luksFormat. + * Convert hash name to lower case in header (fix sha1 backward compatible header) * Check for minimum required gcrypt version. 2009-12-30 Milan Broz * Fix key slot iteration count calculation (small -i value was the same as default). - * The slot and key digest iteration minimun is now 1000. + * The slot and key digest iteration minimum is now 1000. * The key digest iteration # is calculated from iteration time (approx 1/8 of that). * Version 1.1.0-rc4. @@ -395,16 +395,16 @@ * Require device device-mapper to build and do not use backend wrapper for dm calls. * Move memory locking and dm initialization to command layer. * Increase priority of process if memory is locked. - * Add log macros and make logging modre consitent. + * Add log macros and make logging more consistent. * Move command successful messages to verbose level. * Introduce --debug parameter. * Move device utils code and provide context parameter (for log). * Keyfile now must be provided by path, only stdin file descriptor is used (api only). * Do not call isatty() on closed keyfile descriptor. - * Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results. + * Run performance check for PBKDF2 from LUKS code, do not mix hash algorithms results. * Add ability to provide pre-generated master key and UUID in LUKS header format. * Add LUKS function to verify master key digest. - * Move key slot manuipulation function into LUKS specific code. + * Move key slot manipulation function into LUKS specific code. * Replace global options struct with separate parameters in helper functions. * Add new libcryptsetup API (documented in libcryptsetup.h). * Implement old API calls using new functions. @@ -412,7 +412,7 @@ * Add --master-key-file option for luksFormat and luksAddKey. 2009-08-17 Milan Broz - * Fix PBKDF2 speed calculation for large passhrases. + * Fix PBKDF2 speed calculation for large passphrases. * Allow using passphrase provided in options struct for LuksOpen. * Allow restrict keys size in LuksOpen. @@ -424,7 +424,7 @@ * Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here. * Add required parameters for changing hash used in LUKS key setup scheme. * Do not export simple XOR helper now used only inside AF functions. - * Completely remove internal SHA1 implementanion code, not needed anymore. + * Completely remove internal SHA1 implementation code, not needed anymore. * Enable hash algorithm selection for LUKS through -h luksFormat option. 2009-07-28 Milan Broz @@ -636,7 +636,7 @@ 2006-03-15 Clemens Fruhwirth - * configure.in: 1.0.3-rc3. Most unplease release ever. + * configure.in: 1.0.3-rc3. Most displease release ever. * lib/setup.c (__crypt_create_device): More verbose error message. 2006-02-26 Clemens Fruhwirth @@ -705,7 +705,7 @@ 2005-12-06 Clemens Fruhwirth - * man/cryptsetup.8: Correct "seconds" to "microseconds" in the explaination for -i. + * man/cryptsetup.8: Correct "seconds" to "microseconds" in the explanation for -i. 2005-11-09 Clemens Fruhwirth @@ -726,7 +726,7 @@ 2005-09-08 Clemens Fruhwirth - * lib/setup.c (get_key): Fixed another incompatiblity with + * lib/setup.c (get_key): Fixed another incompatibility with original cryptsetup. 2005-08-20 Clemens Fruhwirth @@ -816,7 +816,7 @@ * man/cryptsetup.1: Add man page. - * lib/setup.c: Remove unneccessary LUKS_write_phdr call, so the + * lib/setup.c: Remove unnecessary LUKS_write_phdr call, so the phdr is written after passphrase reading, so the user can change his mind, and not have a partial written LUKS header on it's disk. diff --git a/docs/Keyring.txt b/docs/Keyring.txt new file mode 100644 index 0000000..bdcc838 --- /dev/null +++ b/docs/Keyring.txt @@ -0,0 +1,56 @@ +Integration with kernel keyring service +--------------------------------------- + +We have two different use cases for kernel keyring service: + +I) Volume keys + +Since upstream kernel 4.10 dm-crypt device mapper target allows loading volume +key (VK) in kernel keyring service. The key offloaded in kernel keyring service +is only referenced (by key description) in dm-crypt target and the VK is therefore +no longer stored directly in dm-crypt target. Starting with cryptsetup 2.0 we +load VK in kernel keyring by default for LUKSv2 devices (when dm-crypt with the +feature is available). + +Currently cryptsetup loads VK in 'logon' type kernel key so that VK is passed in +the kernel and can't be read from userspace afterward. Also cryptsetup loads VK in +thread keyring (before passing the reference to dm-crypt target) so that the key +lifetime is directly bound to the process that performs the dm-crypt setup. When +cryptsetup process exits (for whatever reason) the key gets unlinked in kernel +automatically. In summary, the key description visible in dm-crypt table line is +a reference to VK that usually no longer exists in kernel keyring service if you +used cryptsetup to for device activation. + +Using this feature dm-crypt no longer maintains a direct key copy (but there's +always at least one copy in kernel crypto layer). + +II) Keyslot passphrase +The second use case for kernel keyring is to allow cryptsetup reading the keyslot +passphrase stored in kernel keyring instead. The user may load passphrase in kernel +keyring and notify cryptsetup to read it from there later. Currently, cryptsetup +cli supports kernel keyring for passphrase only via LUKS2 internal token +(luks2-keyring). Library also provides a general method for device activation by +reading passphrase from keyring: crypt_activate_by_keyring(). The key type +for use case II) must always be 'user' since we need to read the actual key +data from userspace unlike with VK in I). Ability to read keyslot passphrase +from kernel keyring also allows easily auto-activate LUKS2 devices. + +Simple example how to use kernel keyring for keyslot passphrase: + +1) create LUKS2 keyring token for keyslot 0 (in LUKS2 device/image) +cryptsetup token add --key-description my:key -S 0 /dev/device + +2) Load keyslot passphrase in user keyring +read -s -p "Keyslot passphrase: "; echo -n $REPLY | keyctl padd user my:key @u + +3) Activate device using passphrase stored in kernel keyring +cryptsetup open /dev/device my_unlocked_device + +4a) unlink the key when no longer needed by +keyctl unlink %user:my:key @u + +4b) or revoke it immediately by +keyctl revoke %user:my:key + +If cryptsetup asks for passphrase in step 3) something went wrong with keyring +activation. See --debug output then. diff --git a/docs/LUKS2-locking.txt b/docs/LUKS2-locking.txt new file mode 100644 index 0000000..e401b61 --- /dev/null +++ b/docs/LUKS2-locking.txt @@ -0,0 +1,61 @@ +LUKS2 device locking overview +============================= + +Why +~~~ + +LUKS2 format keeps two identical copies of metadata stored consecutively +at the head of metadata device (file or bdev). The metadata +area (both copies) must be updated in a single atomic operation to avoid +header corruption during concurrent write. + +While with LUKS1 users may have clear knowledge of when a LUKS header is +being updated (written to) or when it's being read solely the need for +locking with legacy format was not so obvious as it is with the LUKSv2 format. + +With LUKS2 the boundary between read-only and read-write is blurry and what +used to be the exclusively read-only operation (i.e., cryptsetup open command) may +easily become read-update operation silently without user's knowledge. +Major feature of LUKS2 format is resilience against accidental +corruption of metadata (i.e., partial header overwrite by parted or cfdisk +while creating partition on mistaken block device). +Such header corruption is detected early on header read and auto-recovery +procedure takes place (the corrupted header with checksum mismatch is being +replaced by the secondary one if that one is intact). +On current Linux systems header load operation may be triggered without user +direct intervention for example by udev rule or from systemd service. +Such clash of header read and auto-recovery procedure could have severe +consequences with the worst case of having LUKS2 device unaccessible or being +broken beyond repair. + +The whole locking of LUKSv2 device headers split into two categories depending +what backend the header is stored on: + +I) block device +~~~~~~~~~~~~~~~ + +We perform flock() on file descriptors of files stored in a private +directory (by default /run/lock/cryptsetup). The file name is derived +from major:minor couple of affected block device. Note we recommend +that access to private locking directory is supposed to be limited +to superuser only. For this method to work the distribution needs +to install the locking directory with appropriate access rights. + +II) regular files +~~~~~~~~~~~~~~~~~ + +First notable difference between headers stored in a file +vs. headers stored in a block device is that headers in a file may be +manipulated by the regular user unlike headers on block devices. Therefore +we perform flock() protection on file with the luks2 header directly. + +Limitations +~~~~~~~~~~~ + +a) In general, the locking model provides serialization of I/Os targeting +the header only. It means the header is always written or read at once +while locking is enabled. +We do not suppress any other negative effect that two or more concurrent +writers of the same header may cause. + +b) The locking is not cluster aware in any way. diff --git a/docs/doxyfile b/docs/doxyfile index 1257eff..a8c84db 100644 --- a/docs/doxyfile +++ b/docs/doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.7.4 +# Doxyfile 1.8.8 #--------------------------------------------------------------------------- # Project related configuration options @@ -10,6 +10,7 @@ PROJECT_BRIEF = "Public cryptsetup API" PROJECT_LOGO = OUTPUT_DIRECTORY = doxygen_api_docs CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES @@ -27,11 +28,14 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = +TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO @@ -39,13 +43,15 @@ IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = YES -SYMBOL_CACHE_SIZE = 0 +LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO @@ -58,6 +64,7 @@ INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES @@ -73,13 +80,13 @@ GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = +CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES @@ -89,9 +96,10 @@ WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = "doxygen_index" "../lib/libcryptsetup.h" +INPUT = "doxygen_index.h" \ + "../lib/libcryptsetup.h" INPUT_ENCODING = UTF-8 FILE_PATTERNS = RECURSIVE = NO @@ -107,8 +115,9 @@ INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO @@ -116,16 +125,19 @@ STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = YES +CLANG_ASSISTED_PARSING = NO +CLANG_OPTIONS = #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html @@ -133,13 +145,14 @@ HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES -HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project @@ -163,19 +176,26 @@ QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -USE_INLINE_TREES = NO +ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = http://www.mathjax.org/mathjax +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- -# configuration options related to the LaTeX output +# Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex @@ -186,13 +206,15 @@ PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = +LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- -# configuration options related to the RTF output +# Configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf @@ -201,26 +223,31 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- -# configuration options related to the man page output +# Configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 +MAN_SUBDIR = MAN_LINKS = NO #--------------------------------------------------------------------------- -# configuration options related to the XML output +# Configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- -# configuration options related to the Perl module output +# Configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO @@ -239,18 +266,20 @@ PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Configuration options related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES PERL_PATH = #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = +DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_NUM_THREADS = 0 @@ -261,6 +290,7 @@ CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES @@ -269,9 +299,12 @@ CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO diff --git a/docs/doxygen_index b/docs/doxygen_index.h similarity index 91% rename from docs/doxygen_index rename to docs/doxygen_index.h index ec394ad..8bdf05f 100644 --- a/docs/doxygen_index +++ b/docs/doxygen_index.h @@ -1,10 +1,9 @@ -/** - * @mainpage Cryptsetup API +/*! \mainpage Cryptsetup API * - * The documentation covers public parts of cryptsetup API. In the following sections you'll find + * The documentation covers public parts of cryptsetup API. In the following sections you'll find * the examples that describe some features of cryptsetup API. * For more info about libcryptsetup API versions see - * Upstream Tracker. + * API Tracker. * *
    *
  1. @ref cexamples "Cryptsetup API examples"
  2. @@ -32,18 +31,16 @@ * @section cexamples Cryptsetup API examples * @section cluks crypt_luks_usage - cryptsetup LUKS device type usage * @subsection cinit crypt_init() - * - * Every time you need to do something with cryptsetup or dmcrypt device + * Every time you need to do something with cryptsetup or dmcrypt device * you need a valid context. The first step to start your work is * @ref crypt_init call. You can call it either with path * to the block device or path to the regular file. If you don't supply the path, * empty context is initialized. * * @subsection cformat crypt_format() - header and payload on mutual device - * * This section covers basic use cases for formatting LUKS devices. Format operation * sets device type in context and in case of LUKS header is written at the beginning - * of block device. In the example bellow we use the scenario where LUKS header and data + * of block device. In the example below we use the scenario where LUKS header and data * are both stored on the same device. There's also a possibility to store header and * data separately. * @@ -51,7 +48,6 @@ * overwrites part of the backing block device. * * @subsection ckeys Keyslot operations examples - * * After successful @ref crypt_format of LUKS device, volume key is not stored * in a persistent way on the device. Keyslot area is an array beyond LUKS header, where * volume key is stored in the encrypted form using user input passphrase. For more info about @@ -60,33 +56,27 @@ * There are two basic methods to create a new keyslot: * * @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key() - * * Creates a new keyslot directly by encrypting volume_key stored in the device * context. Passphrase should be supplied or user is prompted if passphrase param is * NULL. * * @subsection ckeyslot_pass crypt_keyslot_add_by_passphrase() - * * Creates a new keyslot for the volume key by opening existing active keyslot, * extracting volume key from it and storing it into a new keyslot * protected by a new passphrase * * @subsection cload crypt_load() - * * Function loads header from backing block device into device context. * * @subsection cactivate crypt_activate_by_passphrase() - * * Activates crypt device by user supplied password for keyslot containing the volume_key. * If keyslot parameter is set to CRYPT_ANY_SLOT then all active keyslots * are tried one by one until the volume key is found. * * @subsection cactive_pars crypt_get_active_device() - * * This call returns structure containing runtime attributes of active device. * * @subsection cinit_by_name crypt_init_by_name() - * * In case you need to do operations with active device (device which already * has its corresponding mapping) and you miss valid device context stored in * *crypt_device reference, you should use this call. Function tries to @@ -94,22 +84,18 @@ * header. * * @subsection cdeactivate crypt_deactivate() - * * Deactivates crypt device (removes DM mapping and safely erases volume key from kernel). * * @subsection cluks_ex crypt_luks_usage.c - Complex example - * * To compile and run use following commands in examples directory: * * @code * make * ./crypt_luks_usage _path_to_[block_device]_file * @endcode - * * Note that you need to have the cryptsetup library compiled. @include crypt_luks_usage.c * * @section clog crypt_log_usage - cryptsetup logging API example - * * Example describes basic use case for cryptsetup logging. To compile and run * use following commands in examples directory: * @@ -117,7 +103,6 @@ * make * ./crypt_log_usage * @endcode - * * Note that you need to have the cryptsetup library compiled. @include crypt_log_usage.c * * @example crypt_luks_usage.c diff --git a/docs/examples/crypt_log_usage.c b/docs/examples/crypt_log_usage.c index e3e4a2a..d8364af 100644 --- a/docs/examples/crypt_log_usage.c +++ b/docs/examples/crypt_log_usage.c @@ -1,7 +1,7 @@ /* - * An example of using logging through libcryptsetup API + * libcryptsetup API log example * - * Copyright (C) 2011, Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,10 +25,8 @@ #include /* - * This is an example of function that can be registered using crypt_set_log_callback API. + * This is an example of crypt_set_log_callback API callback. * - * Its prototype is void (*log)(int level, const char *msg, void *usrptr) as defined - * in crypt_set_log_callback */ static void simple_syslog_wrapper(int level, const char *msg, void *usrptr) { @@ -71,7 +69,7 @@ int main(void) return 2; } - /* crypt_set_log_callback() - register a log function for crypt context */ + /* crypt_set_log_callback() - register a log callback for crypt context */ crypt_set_log_callback(cd, &simple_syslog_wrapper, (void *)usrprefix); /* send messages ithrough the crypt_log() interface */ @@ -83,7 +81,7 @@ int main(void) /* release crypt context */ crypt_free(cd); - /* Initialize default (global) log function */ + /* Initialize default (global) log callback */ crypt_set_log_callback(NULL, &simple_syslog_wrapper, NULL); crypt_log(NULL, CRYPT_LOG_NORMAL, "This is normal log message"); diff --git a/docs/examples/crypt_luks_usage.c b/docs/examples/crypt_luks_usage.c index 2abd4ed..7299a1c 100644 --- a/docs/examples/crypt_luks_usage.c +++ b/docs/examples/crypt_luks_usage.c @@ -1,7 +1,7 @@ /* - * An example of using LUKS device through libcryptsetup API + * libcryptsetup API - using LUKS device example * - * Copyright (C) 2011, Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,23 +29,18 @@ static int format_and_add_keyslots(const char *path) { struct crypt_device *cd; - struct crypt_params_luks1 params; int r; /* - * crypt_init() call precedes most of operations of cryptsetup API. The call is used - * to initialize crypt device context stored in structure referenced by _cd_ in - * the example. Second parameter is used to pass underlaying device path. + * The crypt_init() call is used to initialize crypt_device context, + * The path parameter specifies a device path. * - * Note: - * If path refers to a regular file it'll be attached to a first free loop device. - * crypt_init() operation fails in case there's no more loop device available. - * Also, loop device will have the AUTOCLEAR flag set, so the file loopback will - * be detached automatically. + * For path, you can use either link to a file or block device. + * The loopback device will be detached automatically. */ r = crypt_init(&cd, path); - if (r < 0 ) { + if (r < 0) { printf("crypt_init() failed for %s.\n", path); return r; } @@ -53,73 +48,37 @@ static int format_and_add_keyslots(const char *path) printf("Context is attached to block device %s.\n", crypt_get_device_name(cd)); /* - * So far no data were written on your device. This will change with call of - * crypt_format() only if you specify CRYPT_LUKS1 as device type. + * So far, no data were written to the device. */ - printf("Device %s will be formatted to LUKS device after 5 seconds.\n" + printf("Device %s will be formatted as a LUKS device after 5 seconds.\n" "Press CTRL+C now if you want to cancel this operation.\n", path); sleep(5); - - /* - * Prepare LUKS format parameters - * - * hash parameter defines PBKDF2 hash algorithm used in LUKS header. - * For compatibility reason we use SHA1 here. - */ - params.hash = "sha1"; - - /* - * data_alignment parameter is relevant only in case of the luks header - * and the payload are both stored on same device. - * - * if you set data_alignment = 0, cryptsetup will autodetect - * data_alignment according to underlaying device topology. - */ - params.data_alignment = 0; - - /* - * data_device parameter defines that no external device - * for luks header will be used - */ - params.data_device = NULL; - /* * NULLs for uuid and volume_key means that these attributes will be - * generated during crypt_format(). Volume key is generated with respect - * to key size parameter passed to function. - * - * crypt_format() checks device size (LUKS header must fit there). + * generated during crypt_format(). */ r = crypt_format(cd, /* crypt context */ - CRYPT_LUKS1, /* LUKS1 is standard LUKS header */ + CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */ "aes", /* used cipher */ - "xts-plain64", /* used block mode and IV generator*/ + "xts-plain64", /* used block mode and IV */ NULL, /* generate UUID */ NULL, /* generate volume key from RNG */ - 256 / 8, /* 256bit key - here AES-128 in XTS mode, size is in bytes */ - ¶ms); /* parameters above */ + 512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */ + NULL); /* default parameters */ - if(r < 0) { + if (r < 0) { printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd)); crypt_free(cd); return r; } /* - * The device now contains LUKS1 header, but there is - * no active keyslot with encrypted volume key yet. - */ - - /* - * cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot. - * Without keyslot you can't manipulate with LUKS device after the context will be freed. + * The device now contains a LUKS header, but there is no active keyslot. * - * To create a new keyslot you need to supply the existing one (to get the volume key from) or - * you need to supply the volume key. + * crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot. * - * After format, we have volume key stored internally in context so add new keyslot - * using this internal volume key. + * After format, the volume key is stored internally. */ r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */ CRYPT_ANY_SLOT, /* just use first free slot */ @@ -137,8 +96,8 @@ static int format_and_add_keyslots(const char *path) printf("The first keyslot is initialized.\n"); /* - * Add another keyslot, now using the first keyslot. - * It will decrypt volume key from the first keyslot and creates new one with another passphrase. + * Add another keyslot, now authenticating with the first keyslot. + * It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase. */ r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */ CRYPT_ANY_SLOT, /* just use first free slot */ @@ -164,21 +123,18 @@ static int activate_and_check_status(const char *path, const char *device_name) /* * LUKS device activation example. - * It's sequence of sub-steps: device initialization, LUKS header load - * and the device activation itself. */ r = crypt_init(&cd, path); - if (r < 0 ) { + if (r < 0) { printf("crypt_init() failed for %s.\n", path); return r; } /* - * crypt_load() is used to load the LUKS header from block device - * into crypt_device context. + * crypt_load() is used to load existing LUKS header from a block device */ r = crypt_load(cd, /* crypt context */ - CRYPT_LUKS1, /* requested type */ + CRYPT_LUKS, /* requested type - here LUKS of any type */ NULL); /* additional parameters (not used) */ if (r < 0) { @@ -188,11 +144,11 @@ static int activate_and_check_status(const char *path, const char *device_name) } /* - * Device activation creates device-mapper devie mapping with name device_name. + * Device activation creates a device-mapper device with the specified name. */ r = crypt_activate_by_passphrase(cd, /* crypt context */ device_name, /* device name to activate */ - CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */ + CRYPT_ANY_SLOT,/* the keyslot use (try all here) */ "foo", 3, /* passphrase */ CRYPT_ACTIVATE_READONLY); /* flags */ if (r < 0) { @@ -201,13 +157,13 @@ static int activate_and_check_status(const char *path, const char *device_name) return r; } - printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name); + printf("%s device %s/%s is active.\n", crypt_get_type(cd), crypt_get_dir(), device_name); printf("\tcipher used: %s\n", crypt_get_cipher(cd)); printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd)); printf("\tdevice UUID: %s\n", crypt_get_uuid(cd)); /* - * Get info about active device (query DM backend) + * Get info about the active device. */ r = crypt_get_active_device(cd, device_name, &cad); if (r < 0) { @@ -235,7 +191,7 @@ static int handle_active_device(const char *device_name) int r; /* - * crypt_init_by_name() initializes device context and loads LUKS header from backing device + * crypt_init_by_name() initializes context by an active device-mapper name */ r = crypt_init_by_name(&cd, device_name); if (r < 0) { @@ -252,7 +208,7 @@ static int handle_active_device(const char *device_name) } /* - * crypt_deactivate() is used to deactivate device + * crypt_deactivate() is used to deactivate a device */ r = crypt_deactivate(cd, device_name); if (r < 0) { diff --git a/docs/on-disk-format-luks2.pdf b/docs/on-disk-format-luks2.pdf new file mode 100644 index 0000000..f4ecda3 Binary files /dev/null and b/docs/on-disk-format-luks2.pdf differ diff --git a/docs/on-disk-format.pdf b/docs/on-disk-format.pdf index a9a18d5..7f6e5e7 100644 Binary files a/docs/on-disk-format.pdf and b/docs/on-disk-format.pdf differ diff --git a/docs/v1.3.0-ReleaseNotes b/docs/v1.3.0-ReleaseNotes index 9ba8a3b..b7ae977 100644 --- a/docs/v1.3.0-ReleaseNotes +++ b/docs/v1.3.0-ReleaseNotes @@ -15,7 +15,7 @@ Important changes * NSS (because of missing ripemd160 it cannot provide full backward compatibility) * kernel userspace API (provided by kernel 2.6.38 and above) (Note that kernel userspace backend is very slow for this type of operation. - But it can be usefull for embedded systems, because you can avoid userspace + But it can be useful for embedded systems, because you can avoid userspace crypto library completely.) Backend is selected during configure time, using --with-crypto_backend option. diff --git a/docs/v1.4.0-ReleaseNotes b/docs/v1.4.0-ReleaseNotes index 6a176d4..bef4e74 100644 --- a/docs/v1.4.0-ReleaseNotes +++ b/docs/v1.4.0-ReleaseNotes @@ -89,7 +89,7 @@ WARNING: This release removes old deprecated API from libcryptsetup (It can be used to simulate trivial hidden disk concepts.) libcryptsetup API changes: - * Added options to suport detached metadata device + * Added options to support detached metadata device crypt_init_by_name_and_header() crypt_set_data_device() * Add crypt_last_error() API call. diff --git a/docs/v1.5.0-ReleaseNotes b/docs/v1.5.0-ReleaseNotes index 16a34cb..9f1e1d1 100644 --- a/docs/v1.5.0-ReleaseNotes +++ b/docs/v1.5.0-ReleaseNotes @@ -46,7 +46,7 @@ Side effect of reencryption is that final device will contain only ciphertext (for all sectors) so even if device was not properly wiped by random data, after reencryption you cannot distinguish which sectors are used. -(Reecryption is done always for the whole device.) +(Reencryption is done always for the whole device.) There are for sure bugs, please TEST IT IN TEST ENVIRONMENT before use for your data. diff --git a/docs/v1.6.8-ReleaseNotes b/docs/v1.6.8-ReleaseNotes new file mode 100644 index 0000000..43b4f2c --- /dev/null +++ b/docs/v1.6.8-ReleaseNotes @@ -0,0 +1,47 @@ +Cryptsetup 1.6.8 Release Notes +============================== + +Changes since version 1.6.7 + +* If the null cipher (no encryption) is used, allow only empty password for LUKS. + (Previously cryptsetup accepted any password in this case.) + + The null cipher can be used only for testing and it is used temporarily during + offline encrypting not yet encrypted device (cryptsetup-reencrypt tool). + + Accepting only empty password prevents situation when someone adds another + LUKS device using the same UUID (UUID of existing LUKS device) with faked + header containing null cipher. + This could force user to use different LUKS device (with no encryption) + without noticing. + (IOW it prevents situation when attacker intentionally forces + user to boot into different system just by LUKS header manipulation.) + + Properly configured systems should have an additional integrity protection + in place here (LUKS here provides only confidentiality) but it is better + to not allow this situation in the first place. + + (For more info see QubesOS Security Bulletin QSB-019-2015.) + +* Properly support stdin "-" handling for luksAddKey for both new and old + keyfile parameters. + +* If encrypted device is file-backed (it uses underlying loop device), + cryptsetup resize will try to resize underlying loop device as well. + (It can be used to grow up file-backed device in one step.) + +* Cryptsetup now allows to use empty password through stdin pipe. + (Intended only for testing in scripts.) + +Cryptsetup API NOTE: + +Direct terminal handling and password calling callback for passphrase +entry will be removed from libcryptsetup in next major (2.x) version +(application should handle it itself). +It means that application have to always provide password in API calls. + +Functions returning last error will be removed in next major version (2.x). +These functions did not work properly for early initialization errors +and application can implement better function easily using own error callback. + +See comments in libcryptsetup.h for more info about deprecated functions. diff --git a/docs/v1.7.0-ReleaseNotes b/docs/v1.7.0-ReleaseNotes new file mode 100644 index 0000000..cd568c1 --- /dev/null +++ b/docs/v1.7.0-ReleaseNotes @@ -0,0 +1,81 @@ +Cryptsetup 1.7.0 Release Notes +============================== + +The cryptsetup 1.7 release changes defaults for LUKS, +there are no API changes. + +Changes since version 1.6.8 + +* Default hash function is now SHA256 (used in key derivation function + and anti-forensic splitter). + + Note that replacing SHA1 with SHA256 is not for security reasons. + (LUKS does not have problems even if collisions are found for SHA1, + for details see FAQ item 5.20). + + Using SHA256 as default is mainly to prevent compatibility problems + on hardened systems where SHA1 is already be phased out. + + Note that all checks (kernel crypto API availability check) now uses + SHA256 as well. + +* Default iteration time for PBKDF2 is now 2 seconds. + + Increasing iteration time is in combination with PBKDF2 benchmark + fixes a try to keep PBKDF2 iteration count still high enough and + also still acceptable for users. + + N.B. Long term is to replace PBKDF2 algorithm with Password Hashing + Competition winner - Argon2. + + Distributions can still change these defaults in compilation time. + + You can change iteration time and used hash function in existing LUKS + header with cryptsetup-reencrypt utility even without full reencryption + of device (see --keep-key option). + +* Fix PBKDF2 iteration benchmark for longer key sizes. + + The previous PBKDF2 benchmark code did not take into account + output key length properly. + + For SHA1 (with 160-bits output) and 256-bit keys (and longer) + it means that the final iteration value was higher than it should be. + + For other hash algorithms (like SHA256 or SHA512) it caused + that iteration count was lower (in comparison to SHA1) than + expected for the requested time period. + + The PBKDF2 benchmark code is now fixed to use the key size for + the formatted device (or default LUKS key size if running in informational + benchmark mode). + + Thanks to A.Visconti, S.Bossi, A.Calo and H.Ragab + (http://www.club.di.unimi.it/) for point this out. + (Based on "What users should know about Full Disk Encryption + based on LUKS" paper to be presented on CANS2015). + +* Remove experimental warning for reencrypt tool. + The strong request for full backup before using reencryption utility + still applies :) + +* Add optional libpasswdqc support for new LUKS passwords. + + If password is entered through terminal (no keyfile specified) and + cryptsetup is compiled with --enable-passwdqc[=/etc/passwdqc.conf], + configured system passwdqc settings are used to check password quality. + +* Update FAQ document. + +Cryptsetup API NOTE: + +Direct terminal handling and password calling callback for passphrase +entry will be removed from libcryptsetup in next major (2.x) version +(application should handle it itself). +It means that application have to always provide password in API calls. + +Functions returning last error will be removed in next major version (2.x). +These functions did not work properly for early initialization errors +and application can implement better function easily using own error callback. + +See comments in libcryptsetup.h for more info about deprecated functions. diff --git a/docs/v1.7.1-ReleaseNotes b/docs/v1.7.1-ReleaseNotes new file mode 100644 index 0000000..057c135 --- /dev/null +++ b/docs/v1.7.1-ReleaseNotes @@ -0,0 +1,36 @@ +Cryptsetup 1.7.1 Release Notes +============================== + +Changes since version 1.7.0 + +* Code now uses kernel crypto API backend according to new + changes introduced in mainline kernel + + While mainline kernel should contain backward compatible + changes, some stable series kernels do not contain fully + backported compatibility patches. + Without these patches most of cryptsetup operations + (like unlocking device) fail. + + This change in cryptsetup ensures that all operations using + kernel crypto API works even on these kernels. + +* The cryptsetup-reencrypt utility now properly detects removal + of underlying link to block device and does not remove + ongoing re-encryption log. + This allows proper recovery (resume) of reencrypt operation later. + + NOTE: Never use /dev/disk/by-uuid/ path for reencryption utility, + this link disappears once the device metadata is temporarily + removed from device. + +* Cryptsetup now allows special "-" (standard input) keyfile handling + even for TCRYPT (TrueCrypt and VeraCrypt compatible) devices. + +* Cryptsetup now fails if there are more keyfiles specified + for non-TCRYPT device. + +* The luksKillSlot command now does not suppress provided password + in batch mode (if password is wrong slot is not destroyed). + Note that not providing password in batch mode means that keyslot + is destroyed unconditionally. diff --git a/docs/v1.7.2-ReleaseNotes b/docs/v1.7.2-ReleaseNotes new file mode 100644 index 0000000..6323430 --- /dev/null +++ b/docs/v1.7.2-ReleaseNotes @@ -0,0 +1,37 @@ +Cryptsetup 1.7.2 Release Notes +============================== + +Changes since version 1.7.1 + +* Update LUKS documentation format. + Clarify fixed sector size and keyslots alignment. + +* Support activation options for error handling modes in Linux kernel + dm-verity module: + + --ignore-corruption - dm-verity just logs detected corruption + + --restart-on-corruption - dm-verity restarts the kernel if corruption is detected + + If the options above are not specified, default behavior for dm-verity remains. + Default is that I/O operation fails with I/O error if corrupted block is detected. + + --ignore-zero-blocks - Instructs dm-verity to not verify blocks that are expected + to contain zeroes and always return zeroes directly instead. + + NOTE that these options could have security or functional impacts, + do not use them without assessing the risks! + +* Fix help text for cipher benchmark specification (mention --cipher option). + +* Fix off-by-one error in maximum keyfile size. + Allow keyfiles up to compiled-in default and not that value minus one. + +* Support resume of interrupted decryption in cryptsetup-reencrypt utility. + To resume decryption, LUKS device UUID (--uuid option) option must be used. + +* Do not use direct-io for LUKS header with unaligned keyslots. + Such headers were used only by the first cryptsetup-luks-1.0.0 release (2005). + +* Fix device block size detection to properly work on particular file-based + containers over underlying devices with 4k sectors. diff --git a/docs/v1.7.3-ReleaseNotes b/docs/v1.7.3-ReleaseNotes new file mode 100644 index 0000000..4a2757c --- /dev/null +++ b/docs/v1.7.3-ReleaseNotes @@ -0,0 +1,20 @@ +Cryptsetup 1.7.3 Release Notes +============================== + +Changes since version 1.7.2 + +* Fix device access to hash offsets located beyond the 2GB device boundary in veritysetup. + +* Set configured (compile-time) default iteration time for devices created directly through + libcryptsetup (default was hardcoded 1 second, the configured value applied only + for cryptsetup application). + +* Fix PBKDF2 benchmark to not double iteration count for specific corner case. + If the measurement function returns exactly 500 ms, the iteration calculation loop + doubled iteration count but instead of repeating measurement it used this value directly. + +* OpenSSL backend: fix memory leak if hash context was repeatedly reused. + +* OpenSSL backend: add support for OpenSSL 1.1.0. + +* Fix several minor spelling errors. diff --git a/docs/v1.7.4-ReleaseNotes b/docs/v1.7.4-ReleaseNotes new file mode 100644 index 0000000..73dbaa7 --- /dev/null +++ b/docs/v1.7.4-ReleaseNotes @@ -0,0 +1,22 @@ +Cryptsetup 1.7.4 Release Notes +============================== + +Changes since version 1.7.3 + +* Allow to specify LUKS1 hash algorithm in Python luksFormat wrapper. + +* Use LUKS1 compiled-in defaults also in Python wrapper. + +* OpenSSL backend: Fix OpenSSL 1.1.0 support without backward compatible API. + +* OpenSSL backend: Fix LibreSSL compatibility. + +* Check for data device and hash device area overlap in veritysetup. + +* Fix a possible race while allocating a free loop device. + +* Fix possible file descriptor leaks if libcryptsetup is run from a forked process. + +* Fix missing same_cpu_crypt flag in status command. + +* Various updates to FAQ and man pages. diff --git a/docs/v1.7.5-ReleaseNotes b/docs/v1.7.5-ReleaseNotes new file mode 100644 index 0000000..eec4315 --- /dev/null +++ b/docs/v1.7.5-ReleaseNotes @@ -0,0 +1,22 @@ +Cryptsetup 1.7.5 Release Notes +============================== + +Changes since version 1.7.4 + +* Fixes to luksFormat to properly support recent kernel running in FIPS mode. + + Cryptsetup must never use a weak key even if it is just used for testing + of algorithm availability. In FIPS mode, weak keys are always rejected. + + A weak key is for example detected if the XTS encryption mode use + the same key for the tweak and the encryption part. + +* Fixes accesses to unaligned hidden legacy TrueCrypt header. + + On a native 4k-sector device the old hidden TrueCrypt header is not + aligned with the hw sector size (this problem was fixed in later TrueCrypt + on-disk format versions). + + Cryptsetup now properly aligns the read so it does not fail. + +* Fixes to optional dracut ramdisk scripts for offline re-encryption on initial boot. diff --git a/docs/v2.0.0-ReleaseNotes b/docs/v2.0.0-ReleaseNotes new file mode 100644 index 0000000..779dcb0 --- /dev/null +++ b/docs/v2.0.0-ReleaseNotes @@ -0,0 +1,605 @@ +Cryptsetup 2.0.0 Release Notes +============================== +Stable release with experimental features. + +This version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +NOTE: This version changes soname of libcryptsetup library and increases +major version for all public symbols. +Most of the old functions are fully backward compatible, so only +recompilation of programs should be needed. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +To provide all security features of authenticated encryption we need +better nonce-reuse resistant algorithm in kernel (see note below). +For now, please use authenticated encryption as experimental feature. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.0-RC1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Limit KDF requested (for format) memory by available physical memory. + On some systems too high requested amount of memory causes OOM killer + to kill the process (instead of returning ENOMEM). + We never try to use more than half of available physical memory. + +* Ignore device alignment if it is not multiple of minimal-io. + Some USB enclosures seems to report bogus topology info that + prevents to use LUKS detached header. + +Changes since version 2.0.0-RC0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Enable to use system libargon2 instead of bundled version. + Renames --disable-argon2 to --disable-internal-argon2 option + and adds --enable-libargon2 flag to allow system libargon2. + +* Changes in build system (Automake) + - The build system now uses non-recursive automake (except for tests). + (Tools binaries are now located in buildroot directory.) + - New --disable-cryptsetup option to disable build of cryptsetup tool. + - Enable build of cryptsetup-reencrypt by default. + +* Install tmpfiles.d configuration for LUKS2 locking directory. + You can overwrite this using --with-tmpfilesdir configure option. + If your distro does not support tmpfiles.d directory, you have + to create locking directory (/run/lock/cryptsetup) in cryptsetup + package (or init scripts). + +* Adds limited support for offline reencryption of LUKS2 format. + +* Decrease size of testing images (and the whole release archive). + +* Fixes for several memory leaks found by Valgrind and Coverity tools. + +* Fixes for several typos in man pages and error messages. + +* LUKS header file in luksFormat is now automatically created + if it does not exist. + +* Do not allow resize if device size is not aligned to sector size. + +Cryptsetup 2.0.0 RC0 Release Notes +================================== + +Important features +~~~~~~~~~~~~~~~~~~ + +* New command integritysetup: support for the new dm-integrity kernel target. + + The dm-integrity is a new kernel device-mapper target that introduces + software emulation of per-sector integrity fields on the disk sector level. + It is available since Linux kernel version 4.12. + + The provided per-sector metadata fields can be used for storing a data + integrity checksum (for example CRC32). + The dm-integrity implements data journal that enforces atomic update + of a sector and its integrity metadata. + + Integritysetup is a CLI utility that can setup standalone dm-integrity + devices (that internally check integrity of data). + + Integritysetup is intended to be used for settings that require + non-cryptographic data integrity protection with no data encryption. + Fo setting integrity protected encrypted devices, see disk authenticated + encryption below. + + Note that after formatting the checksums need to be initialized; + otherwise device reads will fail because of integrity errors. + Integritysetup by default tries to wipe the device with zero blocks + to avoid this problem. Device wipe can be time-consuming, you can skip + this step by specifying --no-wipe option. + (But note that not wiping device can cause some operations to fail + if a write is not multiple of page size and kernel page cache tries + to read sectors with not yet initialized checksums.) + + The default setting is tag size 4 bytes per-sector and CRC32C protection. + To format device with these defaults: + $ integritysetup format + $ integritysetup open + + Note that used algorithm (unlike tag size) is NOT stored in device + kernel superblock and if you use different algorithm, you MUST specify + it in every open command, for example: + $ integritysetup format --tag-size 32 --integrity sha256 + $ integritysetup open --integrity sha256 + + For more info, see integrity man page. + +* Veritysetup command can now format and activate dm-verity devices + that contain Forward Error Correction (FEC) (Reed-Solomon code is used). + This feature is used on most of Android devices already (available since + Linux kernel 4.5). + + There are new options --fec-device, --fec-offset to specify data area + with correction code and --fec-roots that set Redd-Solomon generator roots. + This setting can be used for format command (veritysetup will calculate + and store RS codes) or open command (veritysetup configures kernel + dm-verity to use RS codes). + + For more info see veritysetup man page. + +* Support for larger sector sizes for crypt devices. + + LUKS2 and plain crypt devices can be now configured with larger encryption + sector (typically 4096 bytes, sector size must be the power of two, + maximal sector size is 4096 bytes for portability). + Large sector size can decrease encryption overhead and can also help + with some specific crypto hardware accelerators that perform very + badly with 512 bytes sectors. + + Note that if you configure such a larger sector of the device that does use + smaller physical sector, there is a possibility of a data corruption during + power fail (partial sector writes). + + WARNING: If you use different sector size for a plain device after data were + stored, the decryption will produce garbage. + + For LUKS2, the sector size is stored in metadata and cannot be changed later. + +LUKS2 format and features +~~~~~~~~~~~~~~~~~~~~~~~~~ +The LUKS2 is an on-disk storage format designed to provide simple key +management, primarily intended for Full Disk Encryption based on dm-crypt. + +The LUKS2 is inspired by LUKS1 format and in some specific situations (most +of the default configurations) can be converted in-place from LUKS1. + +The LUKS2 format is designed to allow future updates of various +parts without the need to modify binary structures and internally +uses JSON text format for metadata. Compilation now requires the json-c library +that is used for JSON data processing. + +On-disk format provides redundancy of metadata, detection +of metadata corruption and automatic repair from metadata copy. + +NOTE: For security reasons, there is no redundancy in keyslots binary data +(encrypted keys) but the format allows adding such a feature in future. + +NOTE: to operate correctly, LUKS2 requires locking of metadata. +Locking is performed by using flock() system call for images in file +and for block device by using a specific lock file in /run/lock/cryptsetup. + +This directory must be created by distribution (do not rely on internal +fallback). For systemd-based distribution, you can simply install +scripts/cryptsetup.conf into tmpfiles.d directory. + +For more details see LUKS2-format.txt and LUKS2-locking.txt in the docs +directory. (Please note this is just overview, there will be more formal +documentation later.) + +LUKS2 use +~~~~~~~~~ + +LUKS2 allows using all possible configurations as LUKS1. + +To format device as LUKS2, you have to add "--type luks2" during format: + + $ cryptsetup luksFormat --type luks2 + +All commands issued later will recognize the new format automatically. + +The newly added features in LUKS2 include: + +* Authenticated disk (sector) encryption (EXPERIMENTAL) + + Legacy Full disk encryption (FDE), for example, LUKS1, is a length-preserving + encryption (plaintext is the same size as a ciphertext). + Such FDE can provide data confidentiality, but cannot provide sound data + integrity protection. + + Full disk authenticated encryption is a way how to provide both + confidentiality and data integrity protection. Integrity protection here means + not only detection of random data corruption (silent data corruption) but also + prevention of an unauthorized intentional change of disk sector content. + + NOTE: Integrity protection of this type cannot prevent a replay attack. + An attacker can replace the device or its part of the old content, and it + cannot be detected. + If you need such protection, better use integrity protection on a higher layer. + + For data integrity protection on the sector level, we need additional + per-sector metadata space. In LUKS2 this space is provided by a new + device-mapper dm-integrity target (available since kernel 4.12). + Here the integrity target provides only reliable per-sector metadata store, + and the whole authenticated encryption is performed inside dm-crypt stacked + over the dm-integrity device. + + For encryption, Authenticated Encryption with Additional Data (AEAD) is used. + Every sector is processed as a encryption request of this format: + + |----- AAD -------|------ DATA -------|-- AUTH TAG --| + | (authenticated) | (auth+encryption) | | + | sector_LE | IV | sector in/out | tag in/out | + + AEAD encrypts the whole sector and also authenticates sector number + (to detect sector relocation) and also authenticates Initialization Vector. + + AEAD encryption produces encrypted data and authentication tag. + The authenticated tag is then stored in per-sector metadata space provided + by dm-integrity. + + Most of the current AEAD algorithms requires IV as a nonce, value that is + never reused. Because sector number, as an IV, cannot be used in this + environment, we use a new random IV (IV is a random value generated by system + RNG on every write). This random IV is then stored in the per-sector metadata + as well. + + Because the authentication tag (and IV) requires additional space, the device + provided for a user has less capacity. Also, the data journalling means that + writes are performed twice, decreasing throughput. + + This integrity protection works better with SSDs. If you want to ignore + dm-integrity data journal (because journalling is performed on some higher + layer or you just want to trade-off performance to safe recovery), you can + switch journal off with --integrity-no-journal option. + (This flag can be stored persistently as well.) + + Note that (similar to integritysetup) the device read will fail if + authentication tag is not initialized (no previous write). + By default cryptsetup run wipe of a device (writing zeroes) to initialize + authentication tags. This operation can be very time-consuming. + You can skip device wipe using --integrity-no-wipe option. + + To format LUKS2 device with integrity protection, use new --integrity option. + + For now, there are very few AEAD algorithms that can be used, and some + of them are known to be problematic. In this release we support only + a few of AEAD algorithms (options are for now hard coded), later this + extension will be completely algorithm-agnostic. + + For testing of authenticated encryption, these algorithms work for now: + + 1) aes-xts-plain64 with hmac-sha256 or hmac-sha512 as the authentication tag. + (Common FDE mode + independent authentication tag. Authentication key + for HMAC is independently generated. This mode is very slow.) + $ cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --integrity hmac-sha256 + + 2) aes-gcm-random (native AEAD mode) + DO NOT USE in production! The GCM mode uses only 96-bit nonce, + and possible collision means fatal security problem. + GCM mode has very good hardware support through AES-NI, so it is useful + for performance testing. + $ cryptsetup luksFormat --type luks2 --cipher aes-gcm-random --integrity aead + + 3) ChaCha20 with Poly1305 authenticator (according to RFC7539) + $ cryptsetup luksFormat --type luks2 --cipher chacha20-random --integrity poly1305 + + To specify AES128/AES256 just specify proper key size (without possible + authentication key). Other symmetric ciphers, like Serpent or Twofish, + should work as well. The mode 1) and 2) should be compatible with IEEE 1619.1 + standard recommendation. + + There will be better suitable authenticated modes available soon + For now we are just preparing framework to enable it (and hopefully improve security of FDE). + + FDE authenticated encryption is not a replacement for filesystem layer + authenticated encryption. The goal is to provide at least something because + data integrity protection is often completely ignored in today systems. + +* New memory-hard PBKDF + + LUKS1 introduced Password-Based Key Derivation Function v2 as a tool to + increase attacker cost for a dictionary and brute force attacks. + The PBKDF2 uses iteration count to increase time of key derivation. + Unfortunately, with modern GPUs, the PBKDF2 calculations can be run + in parallel and PBKDF2 can no longer provide the best available protection. + Increasing iteration count just cannot prevent massive parallel dictionary + password attacks in long-term. + + To solve this problem, a new PBKDF, based on so-called memory-hard functions + can be used. Key derivation with memory-hard function requires a certain + amount of memory to compute its output. The memory requirement is very + costly for GPUs and prevents these systems to operate effectively, + increasing cost for attackers. + + LUKS2 introduces support for Argon2i and Argon2id as a PBKDF. + Argon2 is the winner of Password Hashing Competition and is currently + in final RFC draft specification. + + For now, libcryptsetup contains the embedded copy of reference implementation + of Argon2 (that is easily portable to all architectures). + Later, once this function is available in common crypto libraries, it will + switch to external implementation. (This happened for LUKS1 and PBKDF2 + as well years ago.) + With using reference implementation (that is not optimized for speed), there + is some performance penalty. However, using memory-hard PBKDF should still + significantly complicate GPU-optimized dictionary and brute force attacks. + + The Argon2 uses three costs: memory, time (number of iterations) and parallel + (number of threads). + Note that time and memory cost highly influences each other (accessing a lot + of memory takes more time). + + There is a new benchmark that tries to calculate costs to take similar way as + in LUKS1 (where iteration is measured to take 1-2 seconds on user system). + Because now there are more cost variables, it prefers time cost (iterations) + and tries to find required memory that fits. (IOW required memory cost can be + lower if the benchmarks are not able to find required parameters.) + The benchmark cannot run too long, so it tries to approximate next step + for benchmarking. + + For now, default LUKS2 PBKDF algorithm is Argon2i (data independent variant) + with memory cost set to 128MB, time to 800ms and parallel thread according + to available CPU cores but no more than 4. + + All default parameters can be set during compile time and also set on + the command line by using --pbkdf, --pbkdf-memory, --pbkdf-parallel and + --iter-time options. + (Or without benchmark directly by using --pbkdf-force-iterations, see below.) + + You can still use PBKDF2 even for LUKS2 by specifying --pbkdf pbkdf2 option. + (Then only iteration count is applied.) + +* Use of kernel keyring + + Kernel keyring is a storage for sensitive material (like cryptographic keys) + inside Linux kernel. + + LUKS2 uses keyring for two major functions: + + - To store volume key for dm-crypt where it avoids sending volume key in + every device-mapper ioctl structure. Volume key is also no longer directly + visible in a dm-crypt mapping table. The key is not available for the user + after dm-crypt configuration (obviously except direct memory scan). + Use of kernel keyring can be disabled in runtime by --disable-keyring option. + + - As a tool to automatically unlock LUKS device if a passphrase is put into + kernel keyring and proper keyring token is configured. + + This allows storing a secret (passphrase) to kernel per-user keyring by + some external tool (for example some TPM handler) and LUKS2, if configured, + will automatically search in the keyring and unlock the system. + For more info see Tokens section below. + +* Persistent flags + The activation flags (like allow-discards) can be stored in metadata and used + automatically by all later activations (even without using crypttab). + + To store activation flags permanently, use activation command with required + flags and add --persistent option. + + For example, to mark device to always activate with TRIM enabled, + use (for LUKS2 type): + + $ cryptsetup open --allow-discards --persistent + + You can check persistent flags in dump command output: + + $ cryptsetup luksDump + +* Tokens and auto-activation + + A LUKS2 token is an object that can be described "how to get passphrase or key" + to unlock particular keyslot. + (Also it can be used to store any additional metadata, and with + the libcryptsetup interface it can be used to define user token types.) + + Cryptsetup internally implements keyring token. Cryptsetup tries to use + available tokens before asking for the passphrase. For keyring token, + it means that if the passphrase is available under specified identifier + inside kernel keyring, the device is automatically activated using this + stored passphrase. + + Example of using LUKS2 keyring token: + + # Adding token to metadata with "my_token" identifier (by default it applies to all keyslots). + $ cryptsetup token add --key-description "my_token" + + # Storing passphrase to user keyring (this can be done by an external application) + $ echo -n | keyctl padd user my_token @u + + # Now cryptsetup activates automatically if it finds correct passphrase + $ cryptsetup open + + The main reason to use tokens this way is to separate possible hardware + handlers from cryptsetup code. + +* Keyslot priorities + + LUKS2 keyslot can have a new priority attribute. + The default is "normal". The "prefer" priority tell the keyslot to be tried + before other keyslots. Priority "ignore" means that keyslot will never be + used if not specified explicitly (it can be used for backup administrator + passwords that are used only situations when a user forgets own passphrase). + + The priority of keyslot can be set with new config command, for example + $ cryptsetup config --key-slot 1 --priority prefer + + Setting priority to normal will reset slot to normal state. + +* LUKS2 label and subsystem + + The header now contains additional fields for label and subsystem (additional + label). These fields can be used similar to filesystem label and will be + visible in udev rules to possible filtering. (Note that blkid do not yet + contain the LUKS scanning code). + + By default both labels are empty. Label and subsystem are always set together + (no option means clear the label) with the config command: + + $ cryptsetup config --label my_device --subsystem "" + +* In-place conversion form LUKS1 + + To allow easy testing and transition to the new LUKS2 format, there is a new + convert command that allows in-place conversion from the LUKS1 format and, + if there are no incompatible options, also conversion back from LUKS2 + to LUKS1 format. + + Note this command can be used only on some LUKS1 devices (some device header + sizes are not supported). + This command is dangerous, never run it without header backup! + If something fails in the middle of conversion (IO error), the header + is destroyed. (Note that conversion requires move of keyslot data area to + a different offset.) + + To convert header in-place to LUKS2 format, use + $ cryptsetup convert --type luks2 + + To convert it back to LUKS1 format, use + $ cryptsetup convert --type luks1 + + You can verify LUKS version with luksDump command. + $ cryptsetup luksDump + + Note that some LUKS2 features will make header incompatible with LUKS1 and + conversion will be rejected (for example using new Argon2 PBKDF or integrity + extensions). Some minor attributes can be lost in conversion. + +Other changes +~~~~~~~~~~~~~ + +* Explicit KDF iterations count setting + + With new PBKDF interface, there is also the possibility to setup PBKDF costs + directly, avoiding benchmarks. This can be useful if device is formatted to be + primarily used on a different system. + + The option --pbkdf-force-iterations is available for both LUKS1 and LUKS2 + format. Using this option can cause device to have either very low or very + high PBKDF costs. + In the first case it means bad protection to dictionary attacks, in the second + case, it can mean extremely high unlocking time or memory requirements. + Use only if you are sure what you are doing! + + Not that this setting also affects iteration count for the key digest. + For LUKS1 iteration count for digest will be approximately 1/8 of requested + value, for LUKS2 and "pbkdf2" digest minimal PBKDF2 iteration count (1000) + will be used. You cannot set lower iteration count than the internal minimum + (1000 for PBKDF2). + + To format LUKS1 device with forced iteration count (and no benchmarking), use + $ cryptsetup luksFormat --pbkdf-force-iterations 22222 + + For LUKS2 it is always better to specify full settings (do not rely on default + cost values). + For example, we can set to use Argon2id with iteration cost 5, memory 128000 + and parallel set 1: + $ cryptsetup luksFormat --type luks2 \ + --pbkdf argon2id --pbkdf-force-iterations 5 --pbkdf-memory 128000 --pbkdf-parallel 1 + +* VeraCrypt PIM + + Cryptsetup can now also open VeraCrypt device that uses Personal Iteration + Multiplier (PIM). PIM is an integer value that user must remember additionally + to passphrase and influences PBKDF2 iteration count (without it VeraCrypt uses + a fixed number of iterations). + + To open VeraCrypt device with PIM settings, use --veracrypt-pim (to specify + PIM on the command line) or --veracrypt-query-pim to query PIM interactively. + +* Support for plain64be IV + + The plain64be is big-endian variant of plain64 Initialization Vector. It is + used in some images of hardware-based disk encryption systems. Supporting this + variant allows using dm-crypt to map such images through cryptsetup. + +* Deferral removal + + Cryptsetup now can mark device for deferred removal by using a new option + --deferred. This means that close command will not fail if the device is still + in use, but will instruct the kernel to remove the device automatically after + use count drops to zero (for example, once the filesystem is unmounted). + +* A lot of updates to man pages and many minor changes that would make this + release notes too long ;-) + +Libcryptsetup API changes +~~~~~~~~~~~~~~~~~~~~~~~~~ + +These API functions were removed, libcryptsetup no longer handles password +retries from terminal (application should handle terminal operations itself): + crypt_set_password_callback; + crypt_set_timeout; + crypt_set_password_retry; + crypt_set_password_verify; + +This call is removed (no need to keep typo backward compatibility, +the proper function is crypt_set_iteration_time :-) + crypt_set_iterarion_time; + +These calls were removed because are not safe, use per-context +error callbacks instead: + crypt_last_error; + crypt_get_error; + +The PBKDF benchmark was replaced by a new function that uses new KDF structure + crypt_benchmark_kdf; (removed) + crypt_benchmark_pbkdf; (new API call) + +These new calls are now exported, for details see libcryptsetup.h: + crypt_keyslot_add_by_key; + crypt_keyslot_set_priority; + crypt_keyslot_get_priority; + + crypt_token_json_get; + crypt_token_json_set; + crypt_token_status; + crypt_token_luks2_keyring_get; + crypt_token_luks2_keyring_set; + crypt_token_assign_keyslot; + crypt_token_unassign_keyslot; + crypt_token_register; + + crypt_activate_by_token; + crypt_activate_by_keyring; + crypt_deactivate_by_name; + + crypt_metadata_locking; + crypt_volume_key_keyring; + crypt_get_integrity_info; + crypt_get_sector_size; + crypt_persistent_flags_set; + crypt_persistent_flags_get; + crypt_set_pbkdf_type; + crypt_get_pbkdf_type; + + crypt_convert; + crypt_keyfile_read; + crypt_wipe; + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* There will be better documentation and examples. + +* There will be some more formal definition of the threat model for integrity + protection. (And a link to some papers discussing integrity protection, + once it is, hopefully, accepted and published.) + +* Offline re-encrypt tool LUKS2 support is currently limited. + There will be online LUKS2 re-encryption tool in future. + +* Authenticated encryption will use new algorithms from CAESAR competition + (https://competitions.cr.yp.to/caesar.html) once these algorithms are available + in kernel (more on this later). + NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305) + in kernel have too small 96-bit nonces that are problematic with + randomly generated IVs (the collison probability is not negligible). + For the GCM, nonce collision is a fatal problem. + +* Authenticated encryption do not set encryption for dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* Some utilities (blkid, systemd-cryptsetup) have already support for LUKS + but not yet in released version (support in crypttab etc). + +* There are some examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be deprecated soon in favor + of python bindings to libblockdev library (that can already handle LUKS1 devices). diff --git a/docs/v2.0.1-ReleaseNotes b/docs/v2.0.1-ReleaseNotes new file mode 100644 index 0000000..0cc13b9 --- /dev/null +++ b/docs/v2.0.1-ReleaseNotes @@ -0,0 +1,109 @@ +Cryptsetup 2.0.1 Release Notes +============================== +Stable and bug-fix release with experimental features. + +This version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +To provide all security features of authenticated encryption we need +a better nonce-reuse resistant algorithm in the kernel (see note below). +For now, please use authenticated encryption as an experimental feature. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* To store volume key into kernel keyring, kernel 4.15 with dm-crypt 1.18.1 + is required. If a volume key is stored in keyring (LUKS2 only), + the dm-crypt v1.15.0 through v1.18.0 contains a serious bug that may cause + data corruption for ciphers with ESSIV. + (The key for ESSIV is zeroed because of code misplacement.) + This bug is not present for LUKS1 or any other IVs used in LUKS modes. + This change is not visible to the user (except dmsetup output). + +* Increase maximum allowed PBKDF memory-cost limit to 4 GiB. + The Argon2 PBKDF uses 1GiB by default; this is also limited by the amount + of physical memory available (maximum is half of the physical memory). + +* Use /run/cryptsetup as default for cryptsetup locking dir. + There were problems with sharing /run/lock with lockdev, and in the early + boot, the directory was missing. + The directory can be changed with --with-luks2-lock-path and + --with-luks2-lock-dir-perms configure switches. + +* Introduce new 64-bit byte-offset *keyfile_device_offset functions. + + The keyfile interface was designed, well, for keyfiles. Unfortunately, + there are user cases where a keyfile can be placed on a device, and + size_t offset can overflow on 32-bit systems. + + New set of functions that allow 64-bit offsets even on 32bit systems + are now available: + + - crypt_resume_by_keyfile_device_offset + - crypt_keyslot_add_by_keyfile_device_offset + - crypt_activate_by_keyfile_device_offset + - crypt_keyfile_device_read + + The new functions have added the _device_ in name. + Old functions are just internal wrappers around these. + + Also cryptsetup --keyfile-offset and --new-keyfile-offset now allows + 64-bit offsets as parameters. + +* Add error hint for wrongly formatted cipher strings in LUKS1 and + properly fail in luksFormat if cipher format is missing required IV. + For now, crypto API quietly used cipher without IV if a cipher + algorithm without IV specification was used (e.g., aes-xts). + This caused fail later during activation. + +* Configure check for a recent Argon2 lib to support mandatory Argon2id. + +* Fix for the cryptsetup-reencrypt static build if pwquality is enabled. + +* Update LUKS1 standard doc (https links in the bibliography). + + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* There will be better documentation and examples. + +* There will be some more formal definition of the threat model for integrity + protection. (And a link to some papers discussing integrity protection, + once it is, hopefully, accepted and published.) + +* Offline re-encrypt tool LUKS2 support is currently limited. + There will be online LUKS2 re-encryption tool in future. + +* Authenticated encryption will use new algorithms from CAESAR competition + (https://competitions.cr.yp.to/caesar.html) once these algorithms are + available in the kernel (more on this later). + NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305) + in the kernel have too small 96-bit nonces that are problematic with + randomly generated IVs (the collision probability is not negligible). + For the GCM, nonce collision is a fatal problem. + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be deprecated soon in favor + of python bindings to the libblockdev library (that can already handle LUKS1 + devices). diff --git a/docs/v2.0.2-ReleaseNotes b/docs/v2.0.2-ReleaseNotes new file mode 100644 index 0000000..a85a248 --- /dev/null +++ b/docs/v2.0.2-ReleaseNotes @@ -0,0 +1,93 @@ +Cryptsetup 2.0.2 Release Notes +============================== +Stable and bug-fix release with experimental features. + +Cryptsetup 2.x version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +To provide all security features of authenticated encryption, we need +a better nonce-reuse resistant algorithm in the kernel (see note below). +For now, please use authenticated encryption as an experimental feature. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix a regression in early detection of inactive keyslot for luksKillSlot. + It tried to ask for passphrase even for already erased keyslot. + +* Fix a regression in loopaesOpen processing for keyfile on standard input. + Use of "-" argument was not working properly. + +* Add LUKS2 specific options for cryptsetup-reencrypt. + Tokens and persistent flags are now transferred during reencryption; + change of PBKDF keyslot parameters is now supported and allows + to set precalculated values (no benchmarks). + +* Do not allow LUKS2 --persistent and --test-passphrase cryptsetup flags + combination. Persistent flags are now stored only if the device was + successfully activated with the specified flags. + +* Fix integritysetup format after recent Linux kernel changes that + requires to setup key for HMAC in all cases. + Previously integritysetup allowed HMAC with zero key that behaves + like a plain hash. + +* Fix VeraCrypt PIM handling that modified internal iteration counts + even for subsequent activations. The PIM count is no longer printed + in debug log as it is sensitive information. + Also, the code now skips legacy TrueCrypt algorithms if a PIM + is specified (they cannot be used with PIM anyway). + +* PBKDF values cannot be set (even with force parameters) below + hardcoded minimums. For PBKDF2 is it 1000 iterations, for Argon2 + it is 4 iterations and 32 KiB of memory cost. + +* Introduce new crypt_token_is_assigned() API function for reporting + the binding between token and keyslots. + +* Allow crypt_token_json_set() API function to create internal token types. + Do not allow unknown fields in internal token objects. + +* Print message in cryptsetup that about was aborted if a user did not + answer YES in a query. + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* There will be better documentation and examples. + +* There will be some more formal definition of the threat model for integrity + protection. (And a link to some papers discussing integrity protection, + once it is, hopefully, accepted and published.) + +* Authenticated encryption will use new algorithms from CAESAR competition + https://competitions.cr.yp.to/caesar-submissions.html. + We plan to use AEGIS and MORUS, as CAESAR finalists. + + NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305) + in the kernel have too small 96-bit nonces that are problematic with + randomly generated IVs (the collision probability is not negligible). + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be deprecated in version 2.1 + in favor of python bindings to the libblockdev library. diff --git a/docs/v2.0.3-ReleaseNotes b/docs/v2.0.3-ReleaseNotes new file mode 100644 index 0000000..030a1b4 --- /dev/null +++ b/docs/v2.0.3-ReleaseNotes @@ -0,0 +1,121 @@ +Cryptsetup 2.0.3 Release Notes +============================== +Stable bug-fix release with new features. + +Cryptsetup 2.x version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +To provide all security features of authenticated encryption, we need +a better nonce-reuse resistant algorithm in the kernel (see note below). +For now, please use authenticated encryption as an experimental feature. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Expose interface to unbound LUKS2 keyslots. + Unbound LUKS2 keyslot allows storing a key material that is independent + of master volume key (it is not bound to encrypted data segment). + +* New API extensions for unbound keyslots (LUKS2 only) + crypt_keyslot_get_key_size() and crypt_volume_key_get() + These functions allow to get key and key size for unbound keyslots. + +* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only). + +* Add --unbound keyslot option to the cryptsetup luksAddKey command. + +* Add crypt_get_active_integrity_failures() call to get integrity + failure count for dm-integrity devices. + +* Add crypt_get_pbkdf_default() function to get per-type PBKDF default + setting. + +* Add new flag to crypt_keyslot_add_by_key() to force update device + volume key. This call is mainly intended for a wrapped key change. + +* Allow volume key store in a file with cryptsetup. + The --dump-master-key together with --master-key-file allows cryptsetup + to store the binary volume key to a file instead of standard output. + +* Add support detached header for cryptsetup-reencrypt command. + +* Fix VeraCrypt PIM handling - use proper iterations count formula + for PBKDF2-SHA512 and PBKDF2-Whirlpool used in system volumes. + +* Fix cryptsetup tcryptDump for VeraCrypt PIM (support --veracrypt-pim). + +* Add --with-default-luks-format configure time option. + (Option to override default LUKS format version.) + +* Fix LUKS version conversion for detached (and trimmed) LUKS headers. + +* Add luksConvertKey cryptsetup command that converts specific keyslot + from one PBKDF to another. + +* Do not allow conversion to LUKS2 if LUKSMETA (external tool metadata) + header is detected. + +* More cleanup and hardening of LUKS2 keyslot specific validation options. + Add more checks for cipher validity before writing metadata on-disk. + +* Do not allow LUKS1 version downconversion if the header contains tokens. + +* Add "paes" family ciphers (AES wrapped key scheme for mainframes) + to allowed ciphers. + Specific wrapped ley configuration logic must be done by 3rd party tool, + LUKS2 stores only keyslot material and allow activation of the device. + +* Add support for --check-at-most-once option (kernel 4.17) to veritysetup. + This flag can be dangerous; if you can control underlying device + (you can change its content after it was verified) it will no longer + prevent reading tampered data and also it does not prevent silent + data corruptions that appear after the block was once read. + +* Fix return code (EPERM instead of EINVAL) and retry count for bad + passphrase on non-tty input. + +* Enable support for FEC decoding in veritysetup to check dm-verity devices + with additional Reed-Solomon code in userspace (verify command). + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* There will be better documentation and examples (planned for 2.0.4). + +* There will be some more formal definition of the threat model for integrity + protection. (And a link to some papers discussing integrity protection, + once it is, hopefully, accepted and published.) + +* Authenticated encryption will use new algorithms from CAESAR competition + https://competitions.cr.yp.to/caesar-submissions.html. + We plan to use AEGIS and MORUS, as CAESAR finalists. + + NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305) + in the kernel have too small 96-bit nonces that are problematic with + randomly generated IVs (the collision probability is not negligible). + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be REMOVED in version 2.1 + in favor of python bindings to the libblockdev library. + See https://github.com/storaged-project/libblockdev/releases/tag/2.17-1 that + already supports LUKS2 and VeraCrypt devices handling through libcryptsetup. diff --git a/docs/v2.0.4-ReleaseNotes b/docs/v2.0.4-ReleaseNotes new file mode 100644 index 0000000..9731f59 --- /dev/null +++ b/docs/v2.0.4-ReleaseNotes @@ -0,0 +1,119 @@ +Cryptsetup 2.0.4 Release Notes +============================== +Stable bug-fix release with new features. + +Cryptsetup 2.x version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +To provide all security features of authenticated encryption, we need +a better nonce-reuse resistant algorithm in the kernel (see note below). +For now, please use authenticated encryption as an experimental feature. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Use the libblkid (blockid) library to detect foreign signatures + on a device before LUKS format and LUKS2 auto-recovery. + + This change fixes an unexpected recovery using the secondary + LUKS2 header after a device was already overwritten with + another format (filesystem or LVM physical volume). + + LUKS2 will not recreate a primary header if it detects a valid + foreign signature. In this situation, a user must always + use cryptsetup repair command for the recovery. + + Note that libcryptsetup and utilities are now linked to libblkid + as a new dependence. + + To compile code without blockid support (strongly discouraged), + use --disable-blkid configure switch. + +* Add prompt for format and repair actions in cryptsetup and + integritysetup if foreign signatures are detected on the device + through the blockid library. + + After the confirmation, all known signatures are then wiped as + part of the format or repair procedure. + +* Print consistent verbose message about keyslot and token numbers. + For keyslot actions: Key slot unlocked/created/removed. + For token actions: Token created/removed. + +* Print error, if a non-existent token is tried to be removed. + +* Add support for LUKS2 token definition export and import. + + The token command now can export/import customized token JSON file + directly from command line. See the man page for more details. + +* Add support for new dm-integrity superblock version 2. + +* Add an error message when nothing was read from a key file. + +* Update cryptsetup man pages, including --type option usage. + +* Add a snapshot of LUKS2 format specification to documentation + and accordingly fix supported secondary header offsets. + +* Add bundled optimized Argon2 SSE (X86_64 platform) code. + + If the bundled Argon2 code is used and the new configure switch + --enable-internal-sse-argon2 option is present, and compiler flags + support required optimization, the code will try to use optimized + and faster variant. + + Always use the shared library (--enable-libargon2) if possible. + + This option was added because an enterprise distribution + rejected to support the shared Argon2 library and native support + in generic cryptographic libraries is not ready yet. + +* Fix compilation with crypto backend for LibreSSL >= 2.7.0. + LibreSSL introduced OpenSSL 1.1.x API functions, so compatibility + wrapper must be commented out. + +* Fix on-disk header size calculation for LUKS2 format if a specific + data alignment is requested. Until now, the code used default size + that could be wrong for converted devices. + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Authenticated encryption will use new algorithms from CAESAR competition + https://competitions.cr.yp.to/caesar-submissions.html. + We plan to use AEGIS and MORUS (in kernel 4.18), as CAESAR finalists. + + NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305) + in the kernel have too small 96-bit nonces that are problematic with + randomly generated IVs (the collision probability is not negligible). + + For more info about LUKS2 authenticated encryption, please see our paper + https://arxiv.org/abs/1807.00309 + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be REMOVED in version 2.1 + in favor of python bindings to the libblockdev library. + See https://github.com/storaged-project/libblockdev/releases that + already supports LUKS2 and VeraCrypt devices handling through libcryptsetup. + diff --git a/docs/v2.0.5-ReleaseNotes b/docs/v2.0.5-ReleaseNotes new file mode 100644 index 0000000..907d5aa --- /dev/null +++ b/docs/v2.0.5-ReleaseNotes @@ -0,0 +1,102 @@ +Cryptsetup 2.0.5 Release Notes +============================== +Stable bug-fix release with new features. + +Cryptsetup 2.x version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Wipe full header areas (including unused) during LUKS format. + + Since this version, the whole area up to the data offset is zeroed, + and subsequently, all keyslots areas are wiped with random data. + This ensures that no remaining old data remains in the LUKS header + areas, but it could slow down format operation on some devices. + Previously only first 4k (or 32k for LUKS2) and the used keyslot + was overwritten in the format operation. + +* Several fixes to error messages that were unintentionally replaced + in previous versions with a silent exit code. + More descriptive error messages were added, including error + messages if + - a device is unusable (not a block device, no access, etc.), + - a LUKS device is not detected, + - LUKS header load code detects unsupported version, + - a keyslot decryption fails (also happens in the cipher check), + - converting an inactive keyslot. + +* Device activation fails if data area overlaps with LUKS header. + +* Code now uses explicit_bzero to wipe memory if available + (instead of own implementation). + +* Additional VeraCrypt modes are now supported, including Camellia + and Kuznyechik symmetric ciphers (and cipher chains) and Streebog + hash function. These were introduced in a recent VeraCrypt upstream. + + Note that Kuznyechik requires out-of-tree kernel module and + Streebog hash function is available only with the gcrypt cryptographic + backend for now. + +* Fixes static build for integritysetup if the pwquality library is used. + +* Allows passphrase change for unbound keyslots. + +* Fixes removed keyslot number in verbose message for luksKillSlot, + luksRemoveKey and erase command. + +* Adds blkid scan when attempting to open a plain device and warn the user + about existing device signatures in a ciphertext device. + +* Remove LUKS header signature if luksFormat fails to add the first keyslot. + +* Remove O_SYNC from device open and use fsync() to speed up + wipe operation considerably. + +* Create --master-key-file in luksDump and fail if the file already exists. + +* Fixes a bug when LUKS2 authenticated encryption with a detached header + wiped the header device instead of dm-integrity data device area (causing + unnecessary LUKS2 header auto recovery). + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Authenticated encryption should use new algorithms from CAESAR competition + https://competitions.cr.yp.to/caesar-submissions.html. + AEGIS and MORUS are already available in kernel 4.18. + + For more info about LUKS2 authenticated encryption, please see our paper + https://arxiv.org/abs/1807.00309 + + Please note that authenticated encryption is still an experimental feature + and can have performance problems for hish-speed devices and device + with larger IO blocks (like RAID). + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be REMOVED in version 2.1 + in favor of python bindings to the libblockdev library. + See https://github.com/storaged-project/libblockdev/releases that + already supports LUKS2 and VeraCrypt devices handling through libcryptsetup. diff --git a/docs/v2.0.6-ReleaseNotes b/docs/v2.0.6-ReleaseNotes new file mode 100644 index 0000000..7fe276a --- /dev/null +++ b/docs/v2.0.6-ReleaseNotes @@ -0,0 +1,97 @@ +Cryptsetup 2.0.6 Release Notes +============================== +Stable bug-fix release. +All users of cryptsetup 2.0.x should upgrade to this version. + +Cryptsetup 2.x version introduces a new on-disk LUKS2 format. + +The legacy LUKS (referenced as LUKS1) will be fully supported +forever as well as a traditional and fully backward compatible format. + +Please note that authenticated disk encryption, non-cryptographic +data integrity protection (dm-integrity), use of Argon2 Password-Based +Key Derivation Function and the LUKS2 on-disk format itself are new +features and can contain some bugs. + +Please do not use LUKS2 without properly configured backup or in +production systems that need to be compatible with older systems. + +Changes since version 2.0.5 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix support of larger metadata areas in LUKS2 header. + + This release properly supports all specified metadata areas, as documented + in LUKS2 format description (see docs/on-disk-format-luks2.pdf in archive). + + Currently, only default metadata area size is used (in format or convert). + Later cryptsetup versions will allow increasing this metadata area size. + +* If AEAD (authenticated encryption) is used, cryptsetup now tries to check + if the requested AEAD algorithm with specified key size is available + in kernel crypto API. + This change avoids formatting a device that cannot be later activated. + + For this function, the kernel must be compiled with the + CONFIG_CRYPTO_USER_API_AEAD option enabled. + Note that kernel user crypto API options (CONFIG_CRYPTO_USER_API and + CONFIG_CRYPTO_USER_API_SKCIPHER) are already mandatory for LUKS2. + +* Fix setting of integrity no-journal flag. + Now you can store this flag to metadata using --persistent option. + +* Fix cryptsetup-reencrypt to not keep temporary reencryption headers + if interrupted during initial password prompt. + +* Adds early check to plain and LUKS2 formats to disallow device format + if device size is not aligned to requested sector size. + Previously it was possible, and the device was rejected to activate by + kernel later. + +* Fix checking of hash algorithms availability for PBKDF early. + Previously LUKS2 format allowed non-existent hash algorithm with + invalid keyslot preventing the device from activation. + +* Allow Adiantum cipher construction (a non-authenticated length-preserving + fast encryption scheme), so it can be used both for data encryption and + keyslot encryption in LUKS1/2 devices. + + For benchmark, use: + # cryptsetup benchmark -c xchacha12,aes-adiantum + # cryptsetup benchmark -c xchacha20,aes-adiantum + + For LUKS format: + # cryptsetup luksFormat -c xchacha20,aes-adiantum-plain64 -s 256 + + The support for Adiantum will be merged in Linux kernel 4.21. + For more info see the paper https://eprint.iacr.org/2018/720. + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Authenticated encryption should use new algorithms from CAESAR competition + https://competitions.cr.yp.to/caesar-submissions.html. + AEGIS and MORUS are already available in kernel 4.18. + + For more info about LUKS2 authenticated encryption, please see our paper + https://arxiv.org/abs/1807.00309 + + Please note that authenticated encryption is still an experimental feature + and can have performance problems for high-speed devices and device + with larger IO blocks (like RAID). + +* Authenticated encryption do not set encryption for a dm-integrity journal. + + While it does not influence data confidentiality or integrity protection, + an attacker can get some more information from data journal or cause that + system will corrupt sectors after journal replay. (That corruption will be + detected though.) + +* There are examples of user-defined tokens inside misc/luks2_keyslot_example + directory (like a simple external program that uses libssh to unlock LUKS2 + using remote keyfile). + +* The python binding (pycryptsetup) contains only basic functionality for LUKS1 + (it is not updated for new features) and will be REMOVED in version 2.1 + in favor of python bindings to the libblockdev library. + See https://github.com/storaged-project/libblockdev/releases that + already supports LUKS2 and VeraCrypt devices handling through libcryptsetup. diff --git a/docs/v2.1.0-ReleaseNotes b/docs/v2.1.0-ReleaseNotes new file mode 100644 index 0000000..36d2247 --- /dev/null +++ b/docs/v2.1.0-ReleaseNotes @@ -0,0 +1,210 @@ +Cryptsetup 2.1.0 Release Notes +============================== +Stable release with new features and bug fixes. + +Cryptsetup 2.1 version uses a new on-disk LUKS2 format as the default +LUKS format and increases default LUKS2 header size. + +The legacy LUKS (referenced as LUKS1) will be fully supported forever +as well as a traditional and fully backward compatible format. + +When upgrading a stable distribution, please use configure option +--with-default-luks-format=LUKS1 to maintain backward compatibility. + +This release also switches to OpenSSL as a default cryptographic +backend for LUKS header processing. Use --with-crypto_backend=gcrypt +configure option if you need to preserve legacy libgcrypt backend. + +Please do not use LUKS2 without properly configured backup or +in production systems that need to be compatible with older systems. + +Changes since version 2.0.6 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* The default for cryptsetup LUKS format action is now LUKS2. + You can use LUKS1 with cryptsetup option --type luks1. + +* The default size of the LUKS2 header is increased to 16 MB. + It includes metadata and the area used for binary keyslots; + it means that LUKS header backup is now 16MB in size. + + Note, that used keyslot area is much smaller, but this increase + of reserved space allows implementation of later extensions + (like online reencryption). + It is fully compatible with older cryptsetup 2.0.x versions. + If you require to create LUKS2 header with the same size as + in the 2.0.x version, use --offset 8192 option for luksFormat + (units are in 512-bytes sectors; see notes below). + +* Cryptsetup now doubles LUKS default key size if XTS mode is used + (XTS mode uses two internal keys). This does not apply if key size + is explicitly specified on the command line and it does not apply + for the plain mode. + This fixes a confusion with AES and 256bit key in XTS mode where + code used AES128 and not AES256 as often expected. + + Also, the default keyslot encryption algorithm (if cannot be derived + from data encryption algorithm) is now available as configure + options --with-luks2-keyslot-cipher and --with-luks2-keyslot-keybits. + The default is aes-xts-plain64 with 2 * 256-bits key. + +* Default cryptographic backend used for LUKS header processing is now + OpenSSL. For years, OpenSSL provided better performance for PBKDF. + + NOTE: Cryptsetup/libcryptsetup supports several cryptographic + library backends. The fully supported are libgcrypt, OpenSSL and + kernel crypto API. FIPS mode extensions are maintained only for + libgcrypt and OpenSSL. Nettle and NSS are usable only for some + subset of algorithms and cannot provide full backward compatibility. + You can always switch to other backends by using a configure switch, + for libgcrypt (compatibility for older distributions) use: + --with-crypto_backend=gcrypt + +* The Python bindings are no longer supported and the code was removed + from cryptsetup distribution. Please use the libblockdev project + that already covers most of the libcryptsetup functionality + including LUKS2. + +* Cryptsetup now allows using --offset option also for luksFormat. + It means that the specified offset value is used for data offset. + LUKS2 header areas are automatically adjusted according to this value. + (Note units are in 512-byte sectors due to the previous definition + of this option in plain mode.) + This option can replace --align-payload with absolute alignment value. + +* Cryptsetup now supports new refresh action (that is the alias for + "open --refresh"). + It allows changes of parameters for an active device (like root + device mapping), for example, it can enable or disable TRIM support + on-the-fly. + It is supported for LUKS1, LUKS2, plain and loop-AES devices. + +* Integritysetup now supports mode with detached data device through + new --data-device option. + Since kernel 4.18 there is a possibility to specify external data + device for dm-integrity that stores all integrity tags. + +* Integritysetup now supports automatic integrity recalculation + through new --integrity-recalculate option. + Linux kernel since version 4.18 supports automatic background + recalculation of integrity tags for dm-integrity. + +Other changes and fixes +~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix for crypt_wipe call to allocate space if the header is backed + by a file. This means that if you use detached header file, it will + now have always the full size after luksFormat, even if only + a few keyslots are used. + +* Fixes to offline cryptsetup-reencrypt to preserve LUKS2 keyslots + area sizes after reencryption and fixes for some other issues when + creating temporary reencryption headers. + +* Added some FIPS mode workarounds. We cannot (yet) use Argon2 in + FIPS mode, libcryptsetup now fallbacks to use PBKDF2 in FIPS mode. + +* Rejects conversion to LUKS1 if PBKDF2 hash algorithms + in keyslots differ. + +* The hash setting on command line now applies also to LUKS2 PBKDF2 + digest. In previous versions, the LUKS2 key digest used PBKDF2-SHA256 + (except for converted headers). + +* Allow LUKS2 keyslots area to increase if data offset allows it. + Cryptsetup can fine-tune LUKS2 metadata area sizes through + --luks2-metadata-size=BYTES and --luks2-keyslots-size=BYTES. + Please DO NOT use these low-level options until you need it for + some very specific additional feature. + Also, the code now prints these LUKS2 header area sizes in dump + command. + +* For LUKS2, keyslot can use different encryption that data with + new options --keyslot-key-size=BITS and --keyslot-cipher=STRING + in all commands that create new LUKS keyslot. + Please DO NOT use these low-level options until you need it for + some very specific additional feature. + +* Code now avoids data flush when reading device status through + device-mapper. + +* The Nettle crypto backend and the userspace kernel crypto API + backend were enhanced to allow more available hash functions + (like SHA3 variants). + +* Upstream code now does not require libgcrypt-devel + for autoconfigure, because OpenSSL is the default. + The libgcrypt does not use standard pkgconfig detection and + requires specific macro (part of libgcrypt development files) + to be always present during autoconfigure. + With other crypto backends, like OpenSSL, this makes no sense, + so this part of autoconfigure is now optional. + +* Cryptsetup now understands new --debug-json option that allows + an additional dump of some JSON information. These are no longer + present in standard debug output because it could contain some + specific LUKS header parameters. + +* The luksDump contains the hash algorithm used in Anti-Forensic + function. + +* All debug messages are now sent through configured log callback + functions, so an application can easily use own debug messages + handling. In previous versions debug messages were printed directly + to standard output.) + +Libcryptsetup API additions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These new calls are now exported, for details see libcryptsetup.h: + + * crypt_init_data_device + * crypt_get_metadata_device_name + functions to init devices with separate metadata and data device + before a format function is called. + + * crypt_set_data_offset + sets the data offset for LUKS to the specified value + in 512-byte sectors. + It should replace alignment calculation in LUKS param structures. + + * crypt_get_metadata_size + * crypt_set_metadata_size + allows to set/get area sizes in LUKS header + (according to specification). + + * crypt_get_default_type + get default compiled-in LUKS type (version). + + * crypt_get_pbkdf_type_params + allows to get compiled-in PBKDF parameters. + + * crypt_keyslot_set_encryption + * crypt_keyslot_get_encryption + allows to set/get per-keyslot encryption algorithm for LUKS2. + + * crypt_keyslot_get_pbkdf + allows to get PBKDF parameters per-keyslot. + + and these new defines: + * CRYPT_LOG_DEBUG_JSON (message type for JSON debug) + * CRYPT_DEBUG_JSON (log level for JSON debug) + * CRYPT_ACTIVATE_RECALCULATE (dm-integrity recalculate flag) + * CRYPT_ACTIVATE_REFRESH (new open with refresh flag) + +All existing API calls should remain backward compatible. + +Unfinished things & TODO for next releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Optional authenticated encryption is still an experimental feature + and can have performance problems for high-speed devices and device + with larger IO blocks (like RAID). + +* Authenticated encryption does not use encryption for a dm-integrity + journal. While it does not influence data confidentiality or + integrity protection, an attacker can get some more information + from data journal or cause that system will corrupt sectors after + journal replay. (That corruption will be detected though.) + +* The LUKS2 metadata area increase is mainly needed for the new online + reencryption as the major feature for the next release. diff --git a/docs/v2.2.0-ReleaseNotes b/docs/v2.2.0-ReleaseNotes new file mode 100644 index 0000000..b1fd363 --- /dev/null +++ b/docs/v2.2.0-ReleaseNotes @@ -0,0 +1,279 @@ +Cryptsetup 2.2.0 Release Notes +============================== +Stable release with new experimental features and bug fixes. + +Cryptsetup 2.2 version introduces a new LUKS2 online reencryption +extension that allows reencryption of mounted LUKS2 devices +(device in use) in the background. + +Online reencryption is a complex feature. Please be sure you +have a full data backup before using this feature. + +Changes since version 2.1.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LUKS2 online reencryption +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The reencryption is intended to provide a reliable way to change +volume key or an algorithm change while the encrypted device is still +in use. + +It is based on userspace-only approach (no kernel changes needed) +that uses the device-mapper subsystem to remap active devices on-the-fly +dynamically. The device is split into several segments (encrypted by old +key, new key and so-called hotzone, where reencryption is actively running). + +The flexible LUKS2 metadata format is used to store intermediate states +(segment mappings) and both version of keyslots (old and new keys). +Also, it provides a binary area (in the unused keyslot area space) +to provide recovery metadata in the case of unexpected failure during +reencryption. LUKS2 header is during the reencryption marked with +"online-reencryption" keyword. After the reencryption is finished, +this keyword is removed, and the device is backward compatible with all +older cryptsetup tools (that support LUKS2). + +The recovery supports three resilience modes: + + - checksum: default mode, where individual checksums of ciphertext hotzone + sectors are stored, so the recovery process can detect which sectors were + already reencrypted. It requires that the device sector write is atomic. + + - journal: the hotzone is journaled in the binary area + (so the data are written twice) + + - none: performance mode; there is no protection + (similar to old offline reencryption) + +These resilience modes are not available if reencryption uses data shift. + +Note: until we have full documentation (both of the process and metadata), +please refer to Ondrej's slides (some slight details are no longer relevant) +https://okozina.fedorapeople.org/online-disk-reencryption-with-luks2-compact.pdf + +The offline reencryption tool (cryptsetup-reencrypt) is still supported +for both LUKS1 and LUKS2 format. + +Cryptsetup examples for reencryption +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The reencryption feature is integrated directly into cryptsetup utility +as the new "reencrypt" action (command). + +There are three basic modes - to perform reencryption (change of already +existing LUKS2 device), to add encryption to plaintext device and to remove +encryption from a device (decryption). + +In all cases, if existing LUKS2 metadata contains information about +the ongoing reencryption process, following reencrypt command continues +with the ongoing reencryption process until it is finished. + +You can activate a device with ongoing reencryption as the standard LUKS2 +device, but the reencryption process will not continue until the cryptsetup +reencrypt command is issued. + + +1) Reencryption +~~~~~~~~~~~~~~~ +This mode is intended to change any attribute of the data encryption +(change of the volume key, algorithm or sector size). +Note that authenticated encryption is not yet supported. + +You can start the reencryption process by specifying a LUKS2 device or with +a detached LUKS2 header. +The code should automatically recognize if the device is in use (and if it +should use online mode of reencryption). + +If you do not specify parameters, only volume key is changed +(a new random key is generated). + +# cryptsetup reencrypt [--header ] + +You can also start reencryption using active mapped device name: + # cryptsetup reencrypt --active-name + +You can also specify the resilience mode (none, checksum, journal) with +--resilience= option, for checksum mode also the hash algorithm with +--resilience-hash= (only hash algorithms supported by cryptographic +backend are available). + +The maximal size of reencryption hotzone can be limited by +--hotzone-size= option and applies to all reencryption modes. +Note that for checksum and journal mode hotzone size is also limited +by available space in binary keyslot area. + +2) Encryption +~~~~~~~~~~~~~ +This mode provides a way to encrypt a plaintext device to LUKS2 format. +This option requires reduction of device size (for LUKS2 header) or new +detached header. + + # cryptsetup reencrypt --encrypt --reduce-device-size + +Or with detached header: + # cryptsetup reencrypt --encrypt --header + +3) Decryption +~~~~~~~~~~~~~ +This mode provides the removal of existing LUKS2 encryption and replacing +a device with plaintext content only. +For now, we support only decryption with a detached header. + + # cryptsetup reencrypt --decrypt --header + +For all three modes, you can split the process to metadata initialization +(prepare keyslots and segments but do not run reencryption yet) and the data +reencryption step by using --init-only option. + +Prepares metadata: + # cryptsetup reencrypt --init-only + +Starts the data processing: + # cryptsetup reencrypt + +Please note, that due to the Linux kernel limitation, the encryption or +decryption process cannot be run entirely online - there must be at least +short offline window where operation adds/removes device-mapper crypt (LUKS2) layer. +This step should also include modification of /etc/crypttab and fstab UUIDs, +but it is out of the scope of cryptsetup tools. + +Limitations +~~~~~~~~~~~ +Most of these limitations will be (hopefully) fixed in next versions. + +* Only one active keyslot is supported (all old keyslots will be removed + after reencryption). + +* Only block devices are now supported as parameters. As a workaround + for images in a file, please explicitly map a loop device over the image + and use the loop device as the parameter. + +* Devices with authenticated encryption are not supported. (Later it will + be limited by the fixed per-sector metadata, per-sector metadata size + cannot be changed without a new device format operation.) + +* The reencryption uses userspace crypto library, with fallback to + the kernel (if available). There can be some specific configurations + where the fallback does not provide optimal performance. + +* There are no translations of error messages until the final release + (some messages can be rephrased as well). + +* The repair command is not finished; the recovery of interrupted + reencryption is made automatically on the first device activation. + +* Reencryption triggers too many udev scans on metadata updates (on closing + write enabled file descriptors). This has a negative performance impact on the whole + reencryption and generates excessive I/O load on the system. + +New libcryptsetup reencryption API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The libcryptsetup contains new API calls that are used to setup and +run the reencryption. + +Note that there can be some changes in API implementation of these functions +and/or some new function can be introduced in final cryptsetup 2.2 release. + +New API symbols (see documentation in libcryptsetup.h) +* struct crypt_params_reencrypt - reencryption parameters + +* crypt_reencrypt_init_by_passphrase +* crypt_reencrypt_init_by_keyring + - function to configure LUKS2 metadata for reencryption; + if metadata already exists, it configures the context from this metadata + +* crypt_reencrypt + - run the reencryption process (processing the data) + - the optional callback function can be used to interrupt the reencryption + or report the progress. + +* crypt_reencrypt_status + - function to query LUKS2 metadata about the reencryption state + +Other changes and fixes +~~~~~~~~~~~~~~~~~~~~~~~ +* Add optional global serialization lock for memory hard PBKDF. + (The --serialize-memory-hard-pbkdf option in cryptsetup and + CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF in activation flag.) + + This is an "ugly" optional workaround for a situation when multiple devices + are being activated in parallel (like systemd crypttab activation). + The system instead of returning ENOMEM (no memory available) starts + out-of-memory (OOM) killer to kill processes randomly. + + Until we find a reliable way how to work with memory-hard function + in these situations, cryptsetup provide a way how to serialize memory-hard + unlocking among parallel cryptsetup instances to workaround this problem. + This flag is intended to be used only in very specific situations, + never use it directly :-) + +* Abort conversion to LUKS1 with incompatible sector size that is + not supported in LUKS1. + +* Report error (-ENOENT) if no LUKS keyslots are available. User can now + distinguish between a wrong passphrase and no keyslot available. + +* Fix a possible segfault in detached header handling (double free). + +* Add integritysetup support for bitmap mode introduced in Linux kernel 5.2. + Integritysetup now supports --integrity-bitmap-mode option and + --bitmap-sector-per-bit and --bitmap-flush-time commandline options. + + In the bitmap operation mode, if a bit in the bitmap is 1, the corresponding + region's data and integrity tags are not synchronized - if the machine + crashes, the unsynchronized regions will be recalculated. + The bitmap mode is faster than the journal mode because we don't have + to write the data twice, but it is also less reliable, because if data + corruption happens when the machine crashes, it may not be detected. + This can be used only for standalone devices, not with dm-crypt. + +* The libcryptsetup now keeps all file descriptors to underlying device + open during the whole lifetime of crypt device context to avoid excessive + scanning in udev (udev run scan on every descriptor close). + +* The luksDump command now prints more info for reencryption keyslot + (when a device is in-reencryption). + +* New --device-size parameter is supported for LUKS2 reencryption. + It may be used to encrypt/reencrypt only the initial part of the data + device if the user is aware that the rest of the device is empty. + + Note: This change causes API break since the last rc0 release + (crypt_params_reencrypt structure contains additional field). + +* New --resume-only parameter is supported for LUKS2 reencryption. + This flag resumes reencryption process if it exists (not starting + new reencryption). + +* The repair command now tries LUKS2 reencryption recovery if needed. + +* If reencryption device is a file image, an interactive dialog now + asks if reencryption should be run safely in offline mode + (if autodetection of active devices failed). + +* Fix activation through a token where dm-crypt volume key was not + set through keyring (but using old device-mapper table parameter mode). + +* Online reencryption can now retain all keyslots (if all passphrases + are provided). Note that keyslot numbers will change in this case. + +* Allow volume key file to be used if no LUKS2 keyslots are present. + If all keyslots are removed, LUKS2 has no longer information about + the volume key size (there is only key digest present). + Please use --key-size option to open the device or add a new keyslot + in these cases. + +* Print a warning if online reencrypt is called over LUKS1 (not supported). + +* Fix TCRYPT KDF failure in FIPS mode. + Some crypto backends support plain hash in FIPS mode but not for PBKDF2. + +* Remove FIPS mode restriction for crypt_volume_key_get. + It is an application responsibility to use this API in the proper context. + +* Reduce keyslots area size in luksFormat when the header device is too small. + Unless user explicitly asks for keyslots areas size (either via + --luks2-keyslots-size or --offset) reduce keyslots size so that it fits + in metadata device. + +* Make resize action accept --device-size parameter (supports units suffix). diff --git a/docs/v2.2.1-ReleaseNotes b/docs/v2.2.1-ReleaseNotes new file mode 100644 index 0000000..34bacc1 --- /dev/null +++ b/docs/v2.2.1-ReleaseNotes @@ -0,0 +1,36 @@ +Cryptsetup 2.2.1 Release Notes +============================== +Stable bug-fix release. + +This version contains a fix for a possible data corruption bug +on 32-bit platforms. +All users of cryptsetup 2.1 and 2.2 should upgrade to this version. + +Changes since version 2.2.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix possible data length and IV offset overflow on 32bit architectures. + Other 64-bit architectures are not affected. + + The flawed helper function prototypes (introduced in version 2.1.0) used + size_t type, that is 32-bit integer on 32-bit systems. + This patch fixes the problem to properly use 64-bit types. + + If the offset parameter addresses devices larger than 2TB, the value + overflows and stores incorrect information in the metadata. + For example, integrity device is smaller than expected size if used + over large disk on 32-bit architecture. + + This issue is not present with the standard LUKS1/LUKS2 devices without + integrity extensions. + +* Fix a regression in TrueCrypt/VeraCrypt system partition activation. + +* Reinstate missing backing file hint for loop device. + + If the encrypted device is backed by a file (loopback), cryptsetup now + shows the path to the backing file in passphrase query (as in 1.x version). + +* LUKS2 reencryption block size is now aligned to reported optimal IO size. + This change eliminates possible non-aligned device warnings in kernel log + during reencryption. diff --git a/docs/v2.2.2-ReleaseNotes b/docs/v2.2.2-ReleaseNotes new file mode 100644 index 0000000..9e68641 --- /dev/null +++ b/docs/v2.2.2-ReleaseNotes @@ -0,0 +1,56 @@ +Cryptsetup 2.2.2 Release Notes +============================== +Stable bug-fix release. + +All users of cryptsetup 2.1 and 2.2 should upgrade to this version. + +Changes since version 2.2.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Print error message if a keyslot open failed for a different reason + than wrong passwords (for example there is not enough memory). + Only an exit code was present in this case. + +* The progress function switches unit sizes (B/s to GiB/s) according + to the actual speed. Also, it properly calculates speed in the case + of a resumed reencryption operation. + +* The --version now supports short -V short option and better handles + common option priorities. + +* If cryptsetup wipes signatures during format actions through blkid, + it also prints signature device offsets. + +* Compilation now properly uses LTLIBINTL gettext setting in Makefiles. + +* Device-mapper backend now supports new DM_GET_TARGET_VERSION ioctl + (available since Linux kernel 5.4). + This should help to detect some kernel/userspace incompatibilities + earlier later after a failed device activation. + +* Fixes LUKS2 reencryption on systems without kernel keyring. + +* Fixes unlocking prompt for partitions mapped through loop devices + (to properly show the backing device). + +* For LUKS2 decryption, a device is now marked for deferred removal + to be automatically deactivated. + +* Reencryption now limits hotzone size to be maximal 1 GiB or 1/4 + system memory (if lower). + +* Reencryption now retains activation flags during online reencryption. + +* Reencryption now allows LUKS2 device to activate device right after + LUKS2 encryption is initialized through optional active device name + for cryptsetup reencrypt --encrypt command. + This could help with automated encryption during boot. + + NOTE: It means that part of the device is still not encrypted during + activation. Use with care! + +* Fixes failure in resize and plain format activation if activated device + size was not aligned to underlying logical device size. + +* Fixes conversion to LUKS2 format with detached header if a detached + header size was smaller than the expected aligned LUKS1 header size. diff --git a/docs/v2.3.0-ReleaseNotes b/docs/v2.3.0-ReleaseNotes new file mode 100644 index 0000000..2b582c3 --- /dev/null +++ b/docs/v2.3.0-ReleaseNotes @@ -0,0 +1,209 @@ +Cryptsetup 2.3.0 Release Notes +============================== +Stable release with new experimental features and bug fixes. + +Cryptsetup 2.3 version introduces support for BitLocker-compatible +devices (BITLK format). This format is used in Windows systems, +and in combination with a filesystem driver, cryptsetup now provides +native read-write access to BitLocker Full Disk Encryption devices. + +The BITLK implementation is based on publicly available information +and it is an independent and opensource implementation that allows +to access this proprietary disk encryption. + +Changes since version 2.2.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* BITLK (Windows BitLocker compatible) device access + + BITLK userspace implementation is based on the master thesis and code + provided by Vojtech Trefny. Also, thanks to other opensource projects + like libbde (that provide alternative approach to decode this format) + we were able to verify cryptsetup implementation. + + NOTE: Support for the BITLK device is EXPERIMENTAL and will require + a lot of testing. If you get some error message (mainly unsupported + metadata in the on-disk header), please help us by submitting an issue + to cryptsetup project, so we can fix it. Thank you! + + Cryptsetup supports BITLK activation through passphrase or recovery + passphrase for existing devices (BitLocker and Bitlocker to Go). + + Activation through TPM, SmartCard, or any other key protector + is not supported. And in some situations, mainly for TPM bind to some + PCR registers, it could be even impossible on Linux in the future. + + All metadata (key protectors) are handled read-only, cryptsetup cannot + create or modify them. Except for old devices (created in old Vista + systems), all format variants should be recognized. + + Data devices can be activated read-write (followed by mounting through + the proper filesystem driver). To access filesystem on the decrypted device + you need properly installed driver (vfat, NTFS or exFAT). + + Foe AES-XTS, activation is supported on all recent Linux kernels. + + For older AES-CBC encryption, Linux Kernel version 5.3 is required + (support for special IV variant); for AES-CBC with Elephant diffuser, + Linux Kernel 5.6 is required. + + Please note that CBC variants are legacy, and we provide it only + for backward compatibility (to be able to access old drives). + + Cryptsetup command now supports the new "bitlk" format and implement dump, + open, status, and close actions. + + To activate a BITLK device, use + + # cryptsetup open --type bitlk + or with alias + # cryptsetup bitlkOpen + + Then with properly installed fs driver (usually NTFS, vfat or exFAT), + you can mount the plaintext device /dev/mapper device as a common + filesystem. + + To print metadata information about BITLK device, use + # crypotsetup bitlkDump + + To print information about the active device, use + # cryptsetup status + + Example (activation of disk image): + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # Recent blkid recognizes BitLocker device,just to verity + # blkid bitlocker_xts_ntfs.img + bitlocker_xts_ntfs.img: TYPE="BitLocker" + + # Print visible metadata information (on-disk, form the image) + # cryptsetup bitlkDump bitlocker_xts_ntfs.img + Info for BITLK device bitlocker_xts_ntfs.img. + Version: 2 + GUID: ... + Created: Wed Oct 23 17:38:15 2019 + Description: DESKTOP-xxxxxxx E: 23.10.2019 + Cipher name: aes + Cipher mode: xts-plain64 + Cipher key: 128 bits + + Keyslots: + 0: VMK + GUID: ... + Protection: VMK protected with passphrase + Salt: ... + Key data size: 44 [bytes] + 1: VMK + GUID: ... + Protection: VMK protected with recovery passphrase + Salt: ... + Key data size: 44 [bytes] + 2: FVEK + Key data size: 44 [bytes] + + # Activation (recovery passphrase works the same as password) + # cryptsetup bitlkOpen bitlocker_xts_ntfs.img test -v + Enter passphrase for bitlocker_xts_ntfs.img: + Command successful. + + # Information about the active device + # cryptsetup status test + /dev/mapper/test is active. + type: BITLK + cipher: aes-xts-plain64 + keysize: 128 bits + ... + + # Plaintext device should now contain decrypted NTFS filesystem + # blkid /dev/mapper/test + /dev/mapper/test: UUID="..." TYPE="ntfs" + + # And can be mounted + # mount /dev/mapper/test /mnt/tst + + # Deactivation + # umount /mnt/tst + # cryptsetup close test + +* Veritysetup now supports activation with additional PKCS7 signature + of root hash through --root-hash-signature option. + The signature uses an in-kernel trusted key to validate the signature + of the root hash during activation. This option requires Linux kernel + 5.4 with DM_VERITY_VERIFY_ROOTHASH_SIG option. + + Verity devices activated with signature now has a special flag + (with signature) active in device status (veritysetup status ). + + Usage: + # veritysetup open name \ + --root-hash-signature= + +* Integritysetup now calculates hash integrity size according to algorithm + instead of requiring an explicit tag size. + + Previously, when integritysetup formats a device with hash or + HMAC integrity checksums, it required explicitly tag size entry from + a user (or used default value). + This led to confusion and unexpected shortened tag sizes. + + Now, libcryptsetup calculates tag size according to real hash output. + Tag size can also be specified, then it warns if these values differ. + +* Integritysetup now supports fixed padding for dm-integrity devices. + + There was an in-kernel bug that wasted a lot of space when using metadata + areas for integrity-protected devices if a larger sector size than + 512 bytes was used. + This problem affects both stand-alone dm-integrity and also LUKS2 with + authenticated encryption and larger sector size. + + The new extension to dm-integrity superblock is needed, so devices + with the new optimal padding cannot be activated on older systems. + + Integritysetup/Cryptsetup will use new padding automatically if it + detects the proper kernel. To create a compatible device with + the old padding, use --integrity-legacy-padding option. + +* A lot of fixes to online LUKS2 reecryption. + +* Add crypt_resume_by_volume_key() function to libcryptsetup. + If a user has a volume key available, the LUKS device can be resumed + directly using the provided volume key. + No keyslot derivation is needed, only the key digest is checked. + +* Implement active device suspend info. + Add CRYPT_ACTIVATE_SUSPENDED bit to crypt_get_active_device() flags + that informs the caller that device is suspended (luksSuspend). + +* Allow --test-passphrase for a detached header. + Before this fix, we required a data device specified on the command + line even though it was not necessary for the passphrase check. + +* Allow --key-file option in legacy offline encryption. + The option was ignored for LUKS1 encryption initialization. + +* Export memory safe functions. + To make developing of some extensions simpler, we now export + functions to handle memory with proper wipe on deallocation. + +* Fail crypt_keyslot_get_pbkdf for inactive LUKS1 keyslot. + +Libcryptsetup API extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The libcryptsetup API is backward compatible for existing symbols. + +New symbols + crypt_set_compatibility + crypt_get_compatibility; + crypt_resume_by_volume_key; + crypt_activate_by_signed_key; + crypt_safe_alloc; + crypt_safe_realloc; + crypt_safe_free; + crypt_safe_memzero; + +New defines introduced : + CRYPT_BITLK "BITLK" - BITLK (BitLocker-compatible mode + CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING - dm-integrity legacy padding + CRYPT_VERITY_ROOT_HASH_SIGNATURE - dm-verity root hash signature + CRYPT_ACTIVATE_SUSPENDED - device suspended info flag diff --git a/docs/v2.3.1-ReleaseNotes b/docs/v2.3.1-ReleaseNotes new file mode 100644 index 0000000..1c1d365 --- /dev/null +++ b/docs/v2.3.1-ReleaseNotes @@ -0,0 +1,45 @@ +Cryptsetup 2.3.1 Release Notes +============================== +Stable bug-fix release. + +All users of cryptsetup 2.x should upgrade to this version. + +Changes since version 2.3.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Support VeraCrypt 128 bytes passwords. + VeraCrypt now allows passwords of maximal length 128 bytes + (compared to legacy TrueCrypt where it was limited by 64 bytes). + +* Strip extra newline from BitLocker recovery keys + There might be a trailing newline added by the text editor when + the recovery passphrase was passed using the --key-file option. + +* Detect separate libiconv library. + It should fix compilation issues on distributions with iconv + implemented in a separate library. + +* Various fixes and workarounds to build on old Linux distributions. + +* Split lines with hexadecimal digest printing for large key-sizes. + +* Do not wipe the device with no integrity profile. + With --integrity none we performed useless full device wipe. + +* Workaround for dm-integrity kernel table bug. + Some kernels show an invalid dm-integrity mapping table + if superblock contains the "recalculate" bit. This causes + integritysetup to not recognize the dm-integrity device. + Integritysetup now specifies kernel options such a way that + even on unpatched kernels mapping table is correct. + +* Print error message if LUKS1 keyslot cannot be processed. + If the crypto backend is missing support for hash algorithms + used in PBKDF2, the error message was not visible. + +* Properly align LUKS2 keyslots area on conversion. + If the LUKS1 payload offset (data offset) is not aligned + to 4 KiB boundary, new LUKS2 keyslots area in now aligned properly. + +* Validate LUKS2 earlier on conversion to not corrupt the device + if binary keyslots areas metadata are not correct. diff --git a/docs/v2.3.2-ReleaseNotes b/docs/v2.3.2-ReleaseNotes new file mode 100644 index 0000000..eb0d447 --- /dev/null +++ b/docs/v2.3.2-ReleaseNotes @@ -0,0 +1,42 @@ +Cryptsetup 2.3.2 Release Notes +============================== +Stable bug-fix release. + +All users of cryptsetup 2.x should upgrade to this version. + +Changes since version 2.3.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Support compilation with json-c library version 0.14. + +* Update FAQ document for some LUKS2 specific information. + +* Add option to dump content of LUKS2 unbound keyslot: + cryptsetup luksDump --unbound -S + or optionally with --master-key-file option. + + The slot number --key-slot (-S) option is mandatory here. + + An unbound keyslot store a key is that is not assigned to data + area on disk (LUKS2 allows to store arbitrary keys). + +* Rephrase some error messages and remove redundant end-of-lines. + +* Add support for discards (TRIM) for standalone dm-integrity devices. + Linux kernel 5.7 adds support for optional discard/TRIM operation + over dm-integrity devices. + + It is now supported through --allow-discards integritysetup option. + Note you need to add this flag in all activation calls. + + Note that this option cannot be used for LUKS2 authenticated encryption + (that uses dm-integrity for storing additional per-sector metadata). + +* Fix cryptsetup-reencrypt to work on devices that do not allow + direct-io device access. + +* Fix a crash in the BitLocker-compatible code error path. + +* Fix Veracrypt compatible support for longer (>64 bytes) passphrases. + It allows some older images to be correctly opened again. + The issue was introduced in version 2.3.1. diff --git a/docs/v2.3.3-ReleaseNotes b/docs/v2.3.3-ReleaseNotes new file mode 100644 index 0000000..75471ac --- /dev/null +++ b/docs/v2.3.3-ReleaseNotes @@ -0,0 +1,42 @@ +Cryptsetup 2.3.3 Release Notes +============================== +Stable bug-fix release. + +All users of cryptsetup 2.x should upgrade to this version. + +Changes since version 2.3.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix BitLocker compatible device access that uses native 4kB sectors. + + Devices formatted with storage that natively support 4096-bytes + sectors can also use this sector size for encryption units. + +* Support large IV count (--iv-large-sectors) cryptsetup option + for plain device mapping. + + The large IV count is supported in dm-crypt together with larger + sector encryption. It counts the Initialization Vector (IV) in + a larger sector size instead of 512-bytes sectors. + + This option does not have any performance or security impact, + but it can be used for accessing incompatible existing disk images + from other systems. + + Only open action with plain device type and sector size > 512 bytes + are supported. + +* Fix a memory leak in BitLocker compatible handling. + +* Allow EBOIV (Initialization Vector algorithm) use. + + The EBOIV initialization vector is intended to be used internally + with BitLocker devices (for CBC mode). It can now be used also + outside of the BitLocker compatible code. + +* Require both keyslot cipher and key size options. + + If these LUKS2 keyslot parameters were not specified together, + cryptsetup silently failed. + +* Update to man pages and FAQ. diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index 6662568..0000000 --- a/lib/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -SUBDIRS = crypto_backend luks1 loopaes verity tcrypt - -moduledir = $(libdir)/cryptsetup - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libcryptsetup.pc - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir) \ - -I$(top_srcdir)/lib/crypto_backend \ - -I$(top_srcdir)/lib/luks1 \ - -I$(top_srcdir)/lib/loopaes \ - -I$(top_srcdir)/lib/verity \ - -I$(top_srcdir)/lib/tcrypt \ - -DDATADIR=\""$(datadir)"\" \ - -DLIBDIR=\""$(libdir)"\" \ - -DPREFIX=\""$(prefix)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DVERSION=\""$(VERSION)"\" - -lib_LTLIBRARIES = libcryptsetup.la - -common_ldadd = \ - crypto_backend/libcrypto_backend.la \ - luks1/libluks1.la \ - loopaes/libloopaes.la \ - verity/libverity.la \ - tcrypt/libtcrypt.la - -libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym - -libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ - -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \ - -version-info @LIBCRYPTSETUP_VERSION_INFO@ - -libcryptsetup_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ - -libcryptsetup_la_LIBADD = \ - @UUID_LIBS@ \ - @DEVMAPPER_LIBS@ \ - @CRYPTO_LIBS@ \ - $(common_ldadd) - - -libcryptsetup_la_SOURCES = \ - setup.c \ - internal.h \ - bitops.h \ - nls.h \ - libcryptsetup.h \ - utils.c \ - utils_benchmark.c \ - utils_crypt.c \ - utils_crypt.h \ - utils_loop.c \ - utils_loop.h \ - utils_devpath.c \ - utils_wipe.c \ - utils_fips.c \ - utils_fips.h \ - utils_device.c \ - libdevmapper.c \ - utils_dm.h \ - volumekey.c \ - random.c \ - crypt_plain.c - -include_HEADERS = libcryptsetup.h - -EXTRA_DIST = libcryptsetup.pc.in libcryptsetup.sym diff --git a/lib/Makefile.in b/lib/Makefile.in deleted file mode 100644 index ca389bc..0000000 --- a/lib/Makefile.in +++ /dev/null @@ -1,1023 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(srcdir)/libcryptsetup.pc.in $(top_srcdir)/depcomp \ - $(include_HEADERS) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = libcryptsetup.pc -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ - "$(DESTDIR)$(includedir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -am_libcryptsetup_la_OBJECTS = libcryptsetup_la-setup.lo \ - libcryptsetup_la-utils.lo libcryptsetup_la-utils_benchmark.lo \ - libcryptsetup_la-utils_crypt.lo libcryptsetup_la-utils_loop.lo \ - libcryptsetup_la-utils_devpath.lo \ - libcryptsetup_la-utils_wipe.lo libcryptsetup_la-utils_fips.lo \ - libcryptsetup_la-utils_device.lo \ - libcryptsetup_la-libdevmapper.lo libcryptsetup_la-volumekey.lo \ - libcryptsetup_la-random.lo libcryptsetup_la-crypt_plain.lo -libcryptsetup_la_OBJECTS = $(am_libcryptsetup_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libcryptsetup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(libcryptsetup_la_CFLAGS) $(CFLAGS) \ - $(libcryptsetup_la_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libcryptsetup_la_SOURCES) -DIST_SOURCES = $(libcryptsetup_la_SOURCES) -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -DATA = $(pkgconfig_DATA) -HEADERS = $(include_HEADERS) -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - distdir -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -SUBDIRS = crypto_backend luks1 loopaes verity tcrypt -moduledir = $(libdir)/cryptsetup -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libcryptsetup.pc -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir) \ - -I$(top_srcdir)/lib/crypto_backend \ - -I$(top_srcdir)/lib/luks1 \ - -I$(top_srcdir)/lib/loopaes \ - -I$(top_srcdir)/lib/verity \ - -I$(top_srcdir)/lib/tcrypt \ - -DDATADIR=\""$(datadir)"\" \ - -DLIBDIR=\""$(libdir)"\" \ - -DPREFIX=\""$(prefix)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DVERSION=\""$(VERSION)"\" - -lib_LTLIBRARIES = libcryptsetup.la -common_ldadd = \ - crypto_backend/libcrypto_backend.la \ - luks1/libluks1.la \ - loopaes/libloopaes.la \ - verity/libverity.la \ - tcrypt/libtcrypt.la - -libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym -libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ - -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \ - -version-info @LIBCRYPTSETUP_VERSION_INFO@ - -libcryptsetup_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ -libcryptsetup_la_LIBADD = \ - @UUID_LIBS@ \ - @DEVMAPPER_LIBS@ \ - @CRYPTO_LIBS@ \ - $(common_ldadd) - -libcryptsetup_la_SOURCES = \ - setup.c \ - internal.h \ - bitops.h \ - nls.h \ - libcryptsetup.h \ - utils.c \ - utils_benchmark.c \ - utils_crypt.c \ - utils_crypt.h \ - utils_loop.c \ - utils_loop.h \ - utils_devpath.c \ - utils_wipe.c \ - utils_fips.c \ - utils_fips.h \ - utils_device.c \ - libdevmapper.c \ - utils_dm.h \ - volumekey.c \ - random.c \ - crypt_plain.c - -include_HEADERS = libcryptsetup.h -EXTRA_DIST = libcryptsetup.pc.in libcryptsetup.sym -all: all-recursive - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -libcryptsetup.pc: $(top_builddir)/config.status $(srcdir)/libcryptsetup.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libcryptsetup.la: $(libcryptsetup_la_OBJECTS) $(libcryptsetup_la_DEPENDENCIES) $(EXTRA_libcryptsetup_la_DEPENDENCIES) - $(AM_V_CCLD)$(libcryptsetup_la_LINK) -rpath $(libdir) $(libcryptsetup_la_OBJECTS) $(libcryptsetup_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-crypt_plain.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-libdevmapper.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-random.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-setup.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_crypt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_device.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_devpath.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_fips.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_loop.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-utils_wipe.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcryptsetup_la-volumekey.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libcryptsetup_la-setup.lo: setup.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-setup.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-setup.Tpo -c -o libcryptsetup_la-setup.lo `test -f 'setup.c' || echo '$(srcdir)/'`setup.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-setup.Tpo $(DEPDIR)/libcryptsetup_la-setup.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='setup.c' object='libcryptsetup_la-setup.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-setup.lo `test -f 'setup.c' || echo '$(srcdir)/'`setup.c - -libcryptsetup_la-utils.lo: utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils.Tpo -c -o libcryptsetup_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils.Tpo $(DEPDIR)/libcryptsetup_la-utils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='libcryptsetup_la-utils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils.lo `test -f 'utils.c' || echo '$(srcdir)/'`utils.c - -libcryptsetup_la-utils_benchmark.lo: utils_benchmark.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_benchmark.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_benchmark.Tpo -c -o libcryptsetup_la-utils_benchmark.lo `test -f 'utils_benchmark.c' || echo '$(srcdir)/'`utils_benchmark.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_benchmark.Tpo $(DEPDIR)/libcryptsetup_la-utils_benchmark.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_benchmark.c' object='libcryptsetup_la-utils_benchmark.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_benchmark.lo `test -f 'utils_benchmark.c' || echo '$(srcdir)/'`utils_benchmark.c - -libcryptsetup_la-utils_crypt.lo: utils_crypt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_crypt.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_crypt.Tpo -c -o libcryptsetup_la-utils_crypt.lo `test -f 'utils_crypt.c' || echo '$(srcdir)/'`utils_crypt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_crypt.Tpo $(DEPDIR)/libcryptsetup_la-utils_crypt.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_crypt.c' object='libcryptsetup_la-utils_crypt.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_crypt.lo `test -f 'utils_crypt.c' || echo '$(srcdir)/'`utils_crypt.c - -libcryptsetup_la-utils_loop.lo: utils_loop.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_loop.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_loop.Tpo -c -o libcryptsetup_la-utils_loop.lo `test -f 'utils_loop.c' || echo '$(srcdir)/'`utils_loop.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_loop.Tpo $(DEPDIR)/libcryptsetup_la-utils_loop.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_loop.c' object='libcryptsetup_la-utils_loop.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_loop.lo `test -f 'utils_loop.c' || echo '$(srcdir)/'`utils_loop.c - -libcryptsetup_la-utils_devpath.lo: utils_devpath.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_devpath.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_devpath.Tpo -c -o libcryptsetup_la-utils_devpath.lo `test -f 'utils_devpath.c' || echo '$(srcdir)/'`utils_devpath.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_devpath.Tpo $(DEPDIR)/libcryptsetup_la-utils_devpath.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_devpath.c' object='libcryptsetup_la-utils_devpath.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_devpath.lo `test -f 'utils_devpath.c' || echo '$(srcdir)/'`utils_devpath.c - -libcryptsetup_la-utils_wipe.lo: utils_wipe.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_wipe.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_wipe.Tpo -c -o libcryptsetup_la-utils_wipe.lo `test -f 'utils_wipe.c' || echo '$(srcdir)/'`utils_wipe.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_wipe.Tpo $(DEPDIR)/libcryptsetup_la-utils_wipe.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_wipe.c' object='libcryptsetup_la-utils_wipe.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_wipe.lo `test -f 'utils_wipe.c' || echo '$(srcdir)/'`utils_wipe.c - -libcryptsetup_la-utils_fips.lo: utils_fips.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_fips.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_fips.Tpo -c -o libcryptsetup_la-utils_fips.lo `test -f 'utils_fips.c' || echo '$(srcdir)/'`utils_fips.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_fips.Tpo $(DEPDIR)/libcryptsetup_la-utils_fips.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_fips.c' object='libcryptsetup_la-utils_fips.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_fips.lo `test -f 'utils_fips.c' || echo '$(srcdir)/'`utils_fips.c - -libcryptsetup_la-utils_device.lo: utils_device.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-utils_device.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-utils_device.Tpo -c -o libcryptsetup_la-utils_device.lo `test -f 'utils_device.c' || echo '$(srcdir)/'`utils_device.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-utils_device.Tpo $(DEPDIR)/libcryptsetup_la-utils_device.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils_device.c' object='libcryptsetup_la-utils_device.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-utils_device.lo `test -f 'utils_device.c' || echo '$(srcdir)/'`utils_device.c - -libcryptsetup_la-libdevmapper.lo: libdevmapper.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-libdevmapper.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-libdevmapper.Tpo -c -o libcryptsetup_la-libdevmapper.lo `test -f 'libdevmapper.c' || echo '$(srcdir)/'`libdevmapper.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-libdevmapper.Tpo $(DEPDIR)/libcryptsetup_la-libdevmapper.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libdevmapper.c' object='libcryptsetup_la-libdevmapper.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-libdevmapper.lo `test -f 'libdevmapper.c' || echo '$(srcdir)/'`libdevmapper.c - -libcryptsetup_la-volumekey.lo: volumekey.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-volumekey.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-volumekey.Tpo -c -o libcryptsetup_la-volumekey.lo `test -f 'volumekey.c' || echo '$(srcdir)/'`volumekey.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-volumekey.Tpo $(DEPDIR)/libcryptsetup_la-volumekey.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='volumekey.c' object='libcryptsetup_la-volumekey.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-volumekey.lo `test -f 'volumekey.c' || echo '$(srcdir)/'`volumekey.c - -libcryptsetup_la-random.lo: random.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-random.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-random.Tpo -c -o libcryptsetup_la-random.lo `test -f 'random.c' || echo '$(srcdir)/'`random.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-random.Tpo $(DEPDIR)/libcryptsetup_la-random.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='random.c' object='libcryptsetup_la-random.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-random.lo `test -f 'random.c' || echo '$(srcdir)/'`random.c - -libcryptsetup_la-crypt_plain.lo: crypt_plain.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT libcryptsetup_la-crypt_plain.lo -MD -MP -MF $(DEPDIR)/libcryptsetup_la-crypt_plain.Tpo -c -o libcryptsetup_la-crypt_plain.lo `test -f 'crypt_plain.c' || echo '$(srcdir)/'`crypt_plain.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcryptsetup_la-crypt_plain.Tpo $(DEPDIR)/libcryptsetup_la-crypt_plain.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypt_plain.c' object='libcryptsetup_la-crypt_plain.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o libcryptsetup_la-crypt_plain.lo `test -f 'crypt_plain.c' || echo '$(srcdir)/'`crypt_plain.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-pkgconfigDATA: $(pkgconfig_DATA) - @$(NORMAL_INSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ - done - -uninstall-pkgconfigDATA: - @$(NORMAL_UNINSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) -install-includeHEADERS: $(include_HEADERS) - @$(NORMAL_INSTALL) - @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ - done - -uninstall-includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) - -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ - fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-recursive - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-recursive - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-recursive -all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) -installdirs: installdirs-recursive -installdirs-am: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-recursive -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-recursive - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-recursive - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-recursive - -dvi-am: - -html: html-recursive - -html-am: - -info: info-recursive - -info-am: - -install-data-am: install-includeHEADERS install-pkgconfigDATA - -install-dvi: install-dvi-recursive - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-recursive - -install-html-am: - -install-info: install-info-recursive - -install-info-am: - -install-man: - -install-pdf: install-pdf-recursive - -install-pdf-am: - -install-ps: install-ps-recursive - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-recursive - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-recursive - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-recursive - -pdf-am: - -ps: ps-recursive - -ps-am: - -uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \ - uninstall-pkgconfigDATA - -.MAKE: $(am__recursive_targets) install-am install-strip - -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ - check-am clean clean-generic clean-libLTLIBRARIES \ - clean-libtool cscopelist-am ctags ctags-am distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-includeHEADERS install-info \ - install-info-am install-libLTLIBRARIES install-man install-pdf \ - install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-includeHEADERS uninstall-libLTLIBRARIES \ - uninstall-pkgconfigDATA - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/Makemodule.am b/lib/Makemodule.am new file mode 100644 index 0000000..bf4230b --- /dev/null +++ b/lib/Makemodule.am @@ -0,0 +1,115 @@ +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lib/libcryptsetup.pc + +lib_LTLIBRARIES = libcryptsetup.la + +noinst_LTLIBRARIES += libutils_io.la + +include_HEADERS = lib/libcryptsetup.h + +EXTRA_DIST += lib/libcryptsetup.pc.in lib/libcryptsetup.sym + +libutils_io_la_CFLAGS = $(AM_CFLAGS) + +libutils_io_la_SOURCES = \ + lib/utils_io.c \ + lib/utils_io.h + +libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) \ + -I $(top_srcdir)/lib/crypto_backend \ + -I $(top_srcdir)/lib/luks1 \ + -I $(top_srcdir)/lib/luks2 \ + -I $(top_srcdir)/lib/loopaes \ + -I $(top_srcdir)/lib/verity \ + -I $(top_srcdir)/lib/tcrypt \ + -I $(top_srcdir)/lib/integrity \ + -I $(top_srcdir)/lib/bitlk + +libcryptsetup_la_DEPENDENCIES = libutils_io.la libcrypto_backend.la lib/libcryptsetup.sym + +libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ + -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \ + -version-info @LIBCRYPTSETUP_VERSION_INFO@ + +libcryptsetup_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@ + +libcryptsetup_la_LIBADD = \ + @UUID_LIBS@ \ + @DEVMAPPER_LIBS@ \ + @CRYPTO_LIBS@ \ + @LIBARGON2_LIBS@ \ + @JSON_C_LIBS@ \ + @BLKID_LIBS@ \ + $(LTLIBICONV) \ + libcrypto_backend.la \ + libutils_io.la + +libcryptsetup_la_SOURCES = \ + lib/setup.c \ + lib/internal.h \ + lib/bitops.h \ + lib/nls.h \ + lib/libcryptsetup.h \ + lib/utils.c \ + lib/utils_benchmark.c \ + lib/utils_crypt.c \ + lib/utils_crypt.h \ + lib/utils_loop.c \ + lib/utils_loop.h \ + lib/utils_devpath.c \ + lib/utils_wipe.c \ + lib/utils_fips.c \ + lib/utils_fips.h \ + lib/utils_device.c \ + lib/utils_keyring.c \ + lib/utils_keyring.h \ + lib/utils_device_locking.c \ + lib/utils_device_locking.h \ + lib/utils_pbkdf.c \ + lib/utils_safe_memory.c \ + lib/utils_storage_wrappers.c \ + lib/utils_storage_wrappers.h \ + lib/libdevmapper.c \ + lib/utils_dm.h \ + lib/volumekey.c \ + lib/random.c \ + lib/crypt_plain.c \ + lib/base64.h \ + lib/base64.c \ + lib/integrity/integrity.h \ + lib/integrity/integrity.c \ + lib/loopaes/loopaes.h \ + lib/loopaes/loopaes.c \ + lib/tcrypt/tcrypt.h \ + lib/tcrypt/tcrypt.c \ + lib/luks1/af.h \ + lib/luks1/af.c \ + lib/luks1/keyencryption.c \ + lib/luks1/keymanage.c \ + lib/luks1/luks.h \ + lib/verity/verity_hash.c \ + lib/verity/verity_fec.c \ + lib/verity/verity.c \ + lib/verity/verity.h \ + lib/verity/rs_encode_char.c \ + lib/verity/rs_decode_char.c \ + lib/verity/rs.h \ + lib/luks2/luks2_disk_metadata.c \ + lib/luks2/luks2_json_format.c \ + lib/luks2/luks2_json_metadata.c \ + lib/luks2/luks2_luks1_convert.c \ + lib/luks2/luks2_digest.c \ + lib/luks2/luks2_digest_pbkdf2.c \ + lib/luks2/luks2_keyslot.c \ + lib/luks2/luks2_keyslot_luks2.c \ + lib/luks2/luks2_keyslot_reenc.c \ + lib/luks2/luks2_reencrypt.c \ + lib/luks2/luks2_segment.c \ + lib/luks2/luks2_token_keyring.c \ + lib/luks2/luks2_token.c \ + lib/luks2/luks2_internal.h \ + lib/luks2/luks2.h \ + lib/utils_blkid.c \ + lib/utils_blkid.h \ + lib/bitlk/bitlk.h \ + lib/bitlk/bitlk.c diff --git a/lib/base64.c b/lib/base64.c new file mode 100644 index 0000000..aafb901 --- /dev/null +++ b/lib/base64.c @@ -0,0 +1,605 @@ +/* base64.c -- Encode binary data using printable characters. + Copyright (C) 1999-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Simon Josefsson. Partially adapted from GNU MailUtils + * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review + * from Paul Eggert, Bruno Haible, and Stepan Kasal. + * + * See also RFC 4648 . + * + * Be careful with error checking. Here is how you would typically + * use these functions: + * + * bool ok = base64_decode_alloc (in, inlen, &out, &outlen); + * if (!ok) + * FAIL: input was not valid base64 + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN + * + * size_t outlen = base64_encode_alloc (in, inlen, &out); + * if (out == NULL && outlen == 0 && inlen != 0) + * FAIL: input too long + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN. + * + */ + +#include + +/* Get prototype. */ +#include "base64.h" + +/* Get malloc. */ +#include + +/* Get UCHAR_MAX. */ +#include + +#include + +/* C89 compliant way to cast 'char' to 'unsigned char'. */ +static unsigned char +to_uchar (char ch) +{ + return ch; +} + +static const char b64c[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Base64 encode IN array of size INLEN into OUT array. OUT needs + to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be + a multiple of 3. */ +static void +base64_encode_fast (const char *restrict in, size_t inlen, char *restrict out) +{ + while (inlen) + { + *out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f]; + *out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f]; + *out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f]; + *out++ = b64c[to_uchar (in[2]) & 0x3f]; + + inlen -= 3; + in += 3; + } +} + +/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN. + If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as + possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero + terminate the output buffer. */ +void +base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen) +{ + /* Note this outlen constraint can be enforced at compile time. + I.E. that the output buffer is exactly large enough to hold + the encoded inlen bytes. The inlen constraints (of corresponding + to outlen, and being a multiple of 3) can change at runtime + at the end of input. However the common case when reading + large inputs is to have both constraints satisfied, so we depend + on both in base_encode_fast(). */ + if (outlen % 4 == 0 && inlen == outlen / 4 * 3) + { + base64_encode_fast (in, inlen, out); + return; + } + + while (inlen && outlen) + { + *out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f]; + if (!--outlen) + break; + *out++ = b64c[((to_uchar (in[0]) << 4) + + (--inlen ? to_uchar (in[1]) >> 4 : 0)) + & 0x3f]; + if (!--outlen) + break; + *out++ = + (inlen + ? b64c[((to_uchar (in[1]) << 2) + + (--inlen ? to_uchar (in[2]) >> 6 : 0)) + & 0x3f] + : '='); + if (!--outlen) + break; + *out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '='; + if (!--outlen) + break; + if (inlen) + inlen--; + if (inlen) + in += 3; + } + + if (outlen) + *out = '\0'; +} + +/* Allocate a buffer and store zero terminated base64 encoded data + from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e., + the length of the encoded data, excluding the terminating zero. On + return, the OUT variable will hold a pointer to newly allocated + memory that must be deallocated by the caller. If output string + length would overflow, 0 is returned and OUT is set to NULL. If + memory allocation failed, OUT is set to NULL, and the return value + indicates length of the requested memory block, i.e., + BASE64_LENGTH(inlen) + 1. */ +size_t +base64_encode_alloc (const char *in, size_t inlen, char **out) +{ + size_t outlen = 1 + BASE64_LENGTH (inlen); + + /* Check for overflow in outlen computation. + * + * If there is no overflow, outlen >= inlen. + * + * If the operation (inlen + 2) overflows then it yields at most +1, so + * outlen is 0. + * + * If the multiplication overflows, we lose at least half of the + * correct value, so the result is < ((inlen + 2) / 3) * 2, which is + * less than (inlen + 2) * 0.66667, which is less than inlen as soon as + * (inlen > 4). + */ + if (inlen > outlen) + { + *out = NULL; + return 0; + } + + *out = malloc (outlen); + if (!*out) + return outlen; + + base64_encode (in, inlen, *out, outlen); + + return outlen - 1; +} + +/* With this approach this file works independent of the charset used + (think EBCDIC). However, it does assume that the characters in the + Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX + 1003.1-2001 require that char and unsigned char are 8-bit + quantities, though, taking care of that problem. But this may be a + potential problem on non-POSIX C99 platforms. + + IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" + as the formal parameter rather than "x". */ +#define B64(_) \ + ((_) == 'A' ? 0 \ + : (_) == 'B' ? 1 \ + : (_) == 'C' ? 2 \ + : (_) == 'D' ? 3 \ + : (_) == 'E' ? 4 \ + : (_) == 'F' ? 5 \ + : (_) == 'G' ? 6 \ + : (_) == 'H' ? 7 \ + : (_) == 'I' ? 8 \ + : (_) == 'J' ? 9 \ + : (_) == 'K' ? 10 \ + : (_) == 'L' ? 11 \ + : (_) == 'M' ? 12 \ + : (_) == 'N' ? 13 \ + : (_) == 'O' ? 14 \ + : (_) == 'P' ? 15 \ + : (_) == 'Q' ? 16 \ + : (_) == 'R' ? 17 \ + : (_) == 'S' ? 18 \ + : (_) == 'T' ? 19 \ + : (_) == 'U' ? 20 \ + : (_) == 'V' ? 21 \ + : (_) == 'W' ? 22 \ + : (_) == 'X' ? 23 \ + : (_) == 'Y' ? 24 \ + : (_) == 'Z' ? 25 \ + : (_) == 'a' ? 26 \ + : (_) == 'b' ? 27 \ + : (_) == 'c' ? 28 \ + : (_) == 'd' ? 29 \ + : (_) == 'e' ? 30 \ + : (_) == 'f' ? 31 \ + : (_) == 'g' ? 32 \ + : (_) == 'h' ? 33 \ + : (_) == 'i' ? 34 \ + : (_) == 'j' ? 35 \ + : (_) == 'k' ? 36 \ + : (_) == 'l' ? 37 \ + : (_) == 'm' ? 38 \ + : (_) == 'n' ? 39 \ + : (_) == 'o' ? 40 \ + : (_) == 'p' ? 41 \ + : (_) == 'q' ? 42 \ + : (_) == 'r' ? 43 \ + : (_) == 's' ? 44 \ + : (_) == 't' ? 45 \ + : (_) == 'u' ? 46 \ + : (_) == 'v' ? 47 \ + : (_) == 'w' ? 48 \ + : (_) == 'x' ? 49 \ + : (_) == 'y' ? 50 \ + : (_) == 'z' ? 51 \ + : (_) == '0' ? 52 \ + : (_) == '1' ? 53 \ + : (_) == '2' ? 54 \ + : (_) == '3' ? 55 \ + : (_) == '4' ? 56 \ + : (_) == '5' ? 57 \ + : (_) == '6' ? 58 \ + : (_) == '7' ? 59 \ + : (_) == '8' ? 60 \ + : (_) == '9' ? 61 \ + : (_) == '+' ? 62 \ + : (_) == '/' ? 63 \ + : -1) + +static const signed char b64[0x100] = { + B64 (0), B64 (1), B64 (2), B64 (3), + B64 (4), B64 (5), B64 (6), B64 (7), + B64 (8), B64 (9), B64 (10), B64 (11), + B64 (12), B64 (13), B64 (14), B64 (15), + B64 (16), B64 (17), B64 (18), B64 (19), + B64 (20), B64 (21), B64 (22), B64 (23), + B64 (24), B64 (25), B64 (26), B64 (27), + B64 (28), B64 (29), B64 (30), B64 (31), + B64 (32), B64 (33), B64 (34), B64 (35), + B64 (36), B64 (37), B64 (38), B64 (39), + B64 (40), B64 (41), B64 (42), B64 (43), + B64 (44), B64 (45), B64 (46), B64 (47), + B64 (48), B64 (49), B64 (50), B64 (51), + B64 (52), B64 (53), B64 (54), B64 (55), + B64 (56), B64 (57), B64 (58), B64 (59), + B64 (60), B64 (61), B64 (62), B64 (63), + B64 (64), B64 (65), B64 (66), B64 (67), + B64 (68), B64 (69), B64 (70), B64 (71), + B64 (72), B64 (73), B64 (74), B64 (75), + B64 (76), B64 (77), B64 (78), B64 (79), + B64 (80), B64 (81), B64 (82), B64 (83), + B64 (84), B64 (85), B64 (86), B64 (87), + B64 (88), B64 (89), B64 (90), B64 (91), + B64 (92), B64 (93), B64 (94), B64 (95), + B64 (96), B64 (97), B64 (98), B64 (99), + B64 (100), B64 (101), B64 (102), B64 (103), + B64 (104), B64 (105), B64 (106), B64 (107), + B64 (108), B64 (109), B64 (110), B64 (111), + B64 (112), B64 (113), B64 (114), B64 (115), + B64 (116), B64 (117), B64 (118), B64 (119), + B64 (120), B64 (121), B64 (122), B64 (123), + B64 (124), B64 (125), B64 (126), B64 (127), + B64 (128), B64 (129), B64 (130), B64 (131), + B64 (132), B64 (133), B64 (134), B64 (135), + B64 (136), B64 (137), B64 (138), B64 (139), + B64 (140), B64 (141), B64 (142), B64 (143), + B64 (144), B64 (145), B64 (146), B64 (147), + B64 (148), B64 (149), B64 (150), B64 (151), + B64 (152), B64 (153), B64 (154), B64 (155), + B64 (156), B64 (157), B64 (158), B64 (159), + B64 (160), B64 (161), B64 (162), B64 (163), + B64 (164), B64 (165), B64 (166), B64 (167), + B64 (168), B64 (169), B64 (170), B64 (171), + B64 (172), B64 (173), B64 (174), B64 (175), + B64 (176), B64 (177), B64 (178), B64 (179), + B64 (180), B64 (181), B64 (182), B64 (183), + B64 (184), B64 (185), B64 (186), B64 (187), + B64 (188), B64 (189), B64 (190), B64 (191), + B64 (192), B64 (193), B64 (194), B64 (195), + B64 (196), B64 (197), B64 (198), B64 (199), + B64 (200), B64 (201), B64 (202), B64 (203), + B64 (204), B64 (205), B64 (206), B64 (207), + B64 (208), B64 (209), B64 (210), B64 (211), + B64 (212), B64 (213), B64 (214), B64 (215), + B64 (216), B64 (217), B64 (218), B64 (219), + B64 (220), B64 (221), B64 (222), B64 (223), + B64 (224), B64 (225), B64 (226), B64 (227), + B64 (228), B64 (229), B64 (230), B64 (231), + B64 (232), B64 (233), B64 (234), B64 (235), + B64 (236), B64 (237), B64 (238), B64 (239), + B64 (240), B64 (241), B64 (242), B64 (243), + B64 (244), B64 (245), B64 (246), B64 (247), + B64 (248), B64 (249), B64 (250), B64 (251), + B64 (252), B64 (253), B64 (254), B64 (255) +}; + +#if UCHAR_MAX == 255 +# define uchar_in_range(c) true +#else +# define uchar_in_range(c) ((c) <= 255) +#endif + +/* Return true if CH is a character from the Base64 alphabet, and + false otherwise. Note that '=' is padding and not considered to be + part of the alphabet. */ +bool +isbase64 (char ch) +{ + return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)]; +} + +/* Initialize decode-context buffer, CTX. */ +void +base64_decode_ctx_init (struct base64_decode_context *ctx) +{ + ctx->i = 0; +} + +/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and + none of those four is a newline, then return *IN. Otherwise, copy up to + 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at + index CTX->i and setting CTX->i to reflect the number of bytes copied, + and return CTX->buf. In either case, advance *IN to point to the byte + after the last one processed, and set *N_NON_NEWLINE to the number of + verified non-newline bytes accessible through the returned pointer. */ +static const char * +get_4 (struct base64_decode_context *ctx, + char const *restrict *in, char const *restrict in_end, + size_t *n_non_newline) +{ + if (ctx->i == 4) + ctx->i = 0; + + if (ctx->i == 0) + { + char const *t = *in; + if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL) + { + /* This is the common case: no newline. */ + *in += 4; + *n_non_newline = 4; + return (const char *) t; + } + } + + { + /* Copy non-newline bytes into BUF. */ + char const *p = *in; + while (p < in_end) + { + char c = *p++; + if (c != '\n') + { + ctx->buf[ctx->i++] = c; + if (ctx->i == 4) + break; + } + } + + *in = p; + *n_non_newline = ctx->i; + return ctx->buf; + } +} + +#define return_false \ + do \ + { \ + *outp = out; \ + return false; \ + } \ + while (false) + +/* Decode up to four bytes of base64-encoded data, IN, of length INLEN + into the output buffer, *OUT, of size *OUTLEN bytes. Return true if + decoding is successful, false otherwise. If *OUTLEN is too small, + as many bytes as possible are written to *OUT. On return, advance + *OUT to point to the byte after the last one written, and decrement + *OUTLEN to reflect the number of bytes remaining in *OUT. */ +static bool +decode_4 (char const *restrict in, size_t inlen, + char *restrict *outp, size_t *outleft) +{ + char *out = *outp; + if (inlen < 2) + return false; + + if (!isbase64 (in[0]) || !isbase64 (in[1])) + return false; + + if (*outleft) + { + *out++ = ((b64[to_uchar (in[0])] << 2) + | (b64[to_uchar (in[1])] >> 4)); + --*outleft; + } + + if (inlen == 2) + return_false; + + if (in[2] == '=') + { + if (inlen != 4) + return_false; + + if (in[3] != '=') + return_false; + } + else + { + if (!isbase64 (in[2])) + return_false; + + if (*outleft) + { + *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0) + | (b64[to_uchar (in[2])] >> 2)); + --*outleft; + } + + if (inlen == 3) + return_false; + + if (in[3] == '=') + { + if (inlen != 4) + return_false; + } + else + { + if (!isbase64 (in[3])) + return_false; + + if (*outleft) + { + *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0) + | b64[to_uchar (in[3])]); + --*outleft; + } + } + } + + *outp = out; + return true; +} + +/* Decode base64-encoded input array IN of length INLEN to output array + OUT that can hold *OUTLEN bytes. The input data may be interspersed + with newlines. Return true if decoding was successful, i.e. if the + input was valid base64 data, false otherwise. If *OUTLEN is too + small, as many bytes as possible will be written to OUT. On return, + *OUTLEN holds the length of decoded bytes in OUT. Note that as soon + as any non-alphabet, non-newline character is encountered, decoding + is stopped and false is returned. If INLEN is zero, then process + only whatever data is stored in CTX. + + Initially, CTX must have been initialized via base64_decode_ctx_init. + Subsequent calls to this function must reuse whatever state is recorded + in that buffer. It is necessary for when a quadruple of base64 input + bytes spans two input buffers. + + If CTX is NULL then newlines are treated as garbage and the input + buffer is processed as a unit. */ + +bool +base64_decode_ctx (struct base64_decode_context *ctx, + const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen) +{ + size_t outleft = *outlen; + bool ignore_newlines = ctx != NULL; + bool flush_ctx = false; + unsigned int ctx_i = 0; + + if (ignore_newlines) + { + ctx_i = ctx->i; + flush_ctx = inlen == 0; + } + + + while (true) + { + size_t outleft_save = outleft; + if (ctx_i == 0 && !flush_ctx) + { + while (true) + { + /* Save a copy of outleft, in case we need to re-parse this + block of four bytes. */ + outleft_save = outleft; + if (!decode_4 (in, inlen, &out, &outleft)) + break; + + in += 4; + inlen -= 4; + } + } + + if (inlen == 0 && !flush_ctx) + break; + + /* Handle the common case of 72-byte wrapped lines. + This also handles any other multiple-of-4-byte wrapping. */ + if (inlen && *in == '\n' && ignore_newlines) + { + ++in; + --inlen; + continue; + } + + /* Restore OUT and OUTLEFT. */ + out -= outleft_save - outleft; + outleft = outleft_save; + + { + char const *in_end = in + inlen; + char const *non_nl; + + if (ignore_newlines) + non_nl = get_4 (ctx, &in, in_end, &inlen); + else + non_nl = in; /* Might have nl in this case. */ + + /* If the input is empty or consists solely of newlines (0 non-newlines), + then we're done. Likewise if there are fewer than 4 bytes when not + flushing context and not treating newlines as garbage. */ + if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) + { + inlen = 0; + break; + } + if (!decode_4 (non_nl, inlen, &out, &outleft)) + break; + + inlen = in_end - in; + } + } + + *outlen -= outleft; + + return inlen == 0; +} + +/* Allocate an output buffer in *OUT, and decode the base64 encoded + data stored in IN of size INLEN to the *OUT buffer. On return, the + size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL, + if the caller is not interested in the decoded length. *OUT may be + NULL to indicate an out of memory error, in which case *OUTLEN + contains the size of the memory block needed. The function returns + true on successful decoding and memory allocation errors. (Use the + *OUT and *OUTLEN parameters to differentiate between successful + decoding and memory error.) The function returns false if the + input was invalid, in which case *OUT is NULL and *OUTLEN is + undefined. */ +bool +base64_decode_alloc_ctx (struct base64_decode_context *ctx, + const char *in, size_t inlen, char **out, + size_t *outlen) +{ + /* This may allocate a few bytes too many, depending on input, + but it's not worth the extra CPU time to compute the exact size. + The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the + input ends with "=" and minus another 1 if the input ends with "==". + Dividing before multiplying avoids the possibility of overflow. */ + size_t needlen = 3 * (inlen / 4) + 3; + + *out = malloc (needlen); + if (!*out) + return true; + + if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen)) + { + free (*out); + *out = NULL; + return false; + } + + if (outlen) + *outlen = needlen; + + return true; +} diff --git a/lib/base64.h b/lib/base64.h new file mode 100644 index 0000000..a0360dc --- /dev/null +++ b/lib/base64.h @@ -0,0 +1,68 @@ +/* base64.h -- Encode binary data using printable characters. + Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef BASE64_H +# define BASE64_H + +/* Get size_t. */ +# include + +/* Get bool. */ +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/* This uses that the expression (n+(k-1))/k means the smallest + integer >= n/k, i.e., the ceiling of n/k. */ +# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) + +struct base64_decode_context +{ + unsigned int i; + char buf[4]; +}; + +extern bool isbase64 (char ch) __attribute__ ((__const__)); + +extern void base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen); + +extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out); + +extern void base64_decode_ctx_init (struct base64_decode_context *ctx); + +extern bool base64_decode_ctx (struct base64_decode_context *ctx, + const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen); + +extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx, + const char *in, size_t inlen, + char **out, size_t *outlen); + +#define base64_decode(in, inlen, out, outlen) \ + base64_decode_ctx (NULL, in, inlen, out, outlen) + +#define base64_decode_alloc(in, inlen, out, outlen) \ + base64_decode_alloc_ctx (NULL, in, inlen, out, outlen) + +# ifdef __cplusplus +} +# endif + +#endif /* BASE64_H */ diff --git a/lib/bitlk/bitlk.c b/lib/bitlk/bitlk.c new file mode 100644 index 0000000..2ce3a94 --- /dev/null +++ b/lib/bitlk/bitlk.c @@ -0,0 +1,1217 @@ +/* + * BITLK (BitLocker-compatible) volume handling + * + * Copyright (C) 2019-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2019-2020 Milan Broz + * Copyright (C) 2019-2020 Vojtech Trefny + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "bitlk.h" +#include "internal.h" + +#define BITLK_BOOTCODE_V1 "\xeb\x52\x90" +#define BITLK_BOOTCODE_V2 "\xeb\x58\x90" +#define BITLK_SIGNATURE "-FVE-FS-" +#define BITLK_SIGNATURE_TOGO "MSWIN4.1" +#define BITLK_HEADER_METADATA_OFFSET 160 +#define BITLK_HEADER_METADATA_OFFSET_TOGO 424 + +/* FVE metadata header is split into two parts */ +#define BITLK_FVE_METADATA_BLOCK_HEADER_LEN 64 +#define BITLK_FVE_METADATA_HEADER_LEN 48 +#define BITLK_FVE_METADATA_HEADERS_LEN BITLK_FVE_METADATA_BLOCK_HEADER_LEN + BITLK_FVE_METADATA_HEADER_LEN + +/* total size of the FVE area (64 KiB) */ +#define BITLK_FVE_METADATA_SIZE 64 * 1024 + +#define BITLK_ENTRY_HEADER_LEN 8 +#define BITLK_VMK_HEADER_LEN 28 + +#define BITLK_OPEN_KEY_METADATA_LEN 12 + +#define BITLK_RECOVERY_KEY_LEN 55 +#define BITLK_RECOVERY_PARTS 8 +#define BITLK_RECOVERY_PART_LEN 6 + +#define BITLK_KDF_HASH "sha256" +#define BITLK_KDF_ITERATION_COUNT 0x100000 + +/* maximum number of segments for the DM device */ +#define MAX_BITLK_SEGMENTS 10 + +/* January 1, 1970 as MS file time */ +#define EPOCH_AS_FILETIME 116444736000000000 +#define HUNDREDS_OF_NANOSECONDS 10000000 + +/* not available in older version of libuuid */ +#ifndef UUID_STR_LEN +#define UUID_STR_LEN 37 +#endif + +/* known types of GUIDs from the BITLK superblock */ +const uint8_t BITLK_GUID_NORMAL[16] = { 0x3b, 0xd6, 0x67, 0x49, 0x29, 0x2e, 0xd8, 0x4a, + 0x83, 0x99, 0xf6, 0xa3, 0x39, 0xe3, 0xd0, 0x01 }; +const uint8_t BITLK_GUID_EOW[16] = { 0x3b, 0x4d, 0xa8, 0x92, 0x80, 0xdd, 0x0e, 0x4d, + 0x9e, 0x4e, 0xb1, 0xe3, 0x28, 0x4e, 0xae, 0xd8 }; + +/* taken from libfdisk gpt.c -- TODO: this is a good candidate for adding to libuuid */ +struct bitlk_guid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi; + uint8_t clock_seq_low; + uint8_t node[6]; +} __attribute__ ((packed)); + +static void swap_guid(struct bitlk_guid *guid) { + guid->time_low = swab32(guid->time_low); + guid->time_mid = swab16(guid->time_mid); + guid->time_hi_and_version = swab16(guid->time_hi_and_version); +} + +static void guid_to_string(struct bitlk_guid *guid, char *out) { + swap_guid(guid); + uuid_unparse((unsigned char *) guid, out); +} + +typedef enum { + BITLK_SEGTYPE_CRYPT, + BITLK_SEGTYPE_ZERO, +} BitlkSegmentType; + +struct segment { + uint64_t offset; + uint64_t length; + uint64_t iv_offset; + BitlkSegmentType type; +}; + +struct bitlk_signature { + uint8_t boot_code[3]; + uint8_t signature[8]; + uint16_t sector_size; +} __attribute__ ((packed)); + +struct bitlk_superblock { + struct bitlk_guid guid; + uint64_t fve_offset[3]; +} __attribute__ ((packed)); + +struct bitlk_fve_metadata { + /* FVE metadata block header */ + uint8_t signature[8]; + uint16_t fve_size; + uint16_t fve_version; + uint16_t curr_state; + uint16_t next_state; + uint64_t volume_size; + uint32_t unknown2; + uint32_t volume_header_size; + uint64_t fve_offset[3]; + uint64_t volume_header_offset; + /* FVE metadata header */ + uint32_t metadata_size; + uint32_t metadata_version; + uint32_t metadata_header_size; + uint32_t metada_size_copy; + struct bitlk_guid guid; + uint32_t next_nonce; + uint16_t encryption; + uint16_t unknown3; + uint64_t creation_time; +} __attribute__ ((packed)); + +struct bitlk_entry_header_block { + uint64_t offset; + uint64_t size; +} __attribute__ ((packed)); + +struct bitlk_entry_vmk { + struct bitlk_guid guid; + uint8_t modified[8]; + uint16_t _unknown; + uint16_t protection; +} __attribute__ ((packed)); + +struct bitlk_kdf_data { + char last_sha256[32]; + char initial_sha256[32]; + char salt[16]; + uint64_t count; +}; + +static BITLKVMKProtection get_vmk_protection(uint16_t protection) +{ + switch (protection) { + case 0x0000: + return BITLK_PROTECTION_CLEAR_KEY; + case 0x0100: + return BITLK_PROTECTION_TPM; + case 0x0200: + return BITLK_PROTECTION_STARTUP_KEY; + case 0x0500: + return BITLK_PROTECTION_TPM_PIN; + case 0x0800: + return BITLK_PROTECTION_RECOVERY_PASSPHRASE; + case 0x1000: + return BITLK_PROTECTION_SMART_CARD; + case 0x2000: + return BITLK_PROTECTION_PASSPHRASE; + default: + return BITLK_PROTECTION_UNKNOWN; + } +} + +static const char* get_vmk_protection_string(BITLKVMKProtection protection) +{ + switch (protection) { + case BITLK_PROTECTION_CLEAR_KEY: + return "VMK protected with clear key"; + case BITLK_PROTECTION_TPM: + return "VMK protected with TPM"; + case BITLK_PROTECTION_STARTUP_KEY: + return "VMK protected with startup key"; + case BITLK_PROTECTION_TPM_PIN: + return "VMK protected with TPM and PIN"; + case BITLK_PROTECTION_PASSPHRASE: + return "VMK protected with passphrase"; + case BITLK_PROTECTION_RECOVERY_PASSPHRASE: + return "VMK protected with recovery passphrase"; + case BITLK_PROTECTION_SMART_CARD: + return "VMK protected with smart card"; + default: + return "VMK with unknown protection"; + } +} + +static const char* get_bitlk_type_string(BITLKEncryptionType type) +{ + switch (type) + { + case BITLK_ENCRYPTION_TYPE_NORMAL: + return "normal"; + case BITLK_ENCRYPTION_TYPE_EOW: + return "encrypt-on-write"; + default: + return "unknown"; + } +} + +/* TODO -- move to some utils file */ +static void hexprint(struct crypt_device *cd, const char *d, int n, const char *sep) +{ + int i; + for(i = 0; i < n; i++) + log_std(cd, "%02hhx%s", (const char)d[i], sep); +} + +static uint64_t filetime_to_unixtime(uint64_t time) +{ + return (time - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS; +} + +static int convert_to_utf8(struct crypt_device *cd, uint8_t *input, size_t inlen, char **out) +{ + char *outbuf = NULL; + iconv_t ic; + size_t ic_inlen = inlen; + size_t ic_outlen = inlen; + char *ic_outbuf = NULL; + size_t r = 0; + + outbuf = malloc(inlen); + if (outbuf == NULL) + return -ENOMEM; + + memset(outbuf, 0, inlen); + ic_outbuf = outbuf; + + ic = iconv_open("UTF-8", "UTF-16LE"); + r = iconv(ic, (char **) &input, &ic_inlen, &ic_outbuf, &ic_outlen); + iconv_close(ic); + + if (r == 0) + *out = strdup(outbuf); + else { + *out = NULL; + log_dbg(cd, "Failed to convert volume description: %s", strerror(errno)); + r = 0; + } + + free(outbuf); + return r; +} + +static int passphrase_to_utf16(struct crypt_device *cd, char *input, size_t inlen, char **out) +{ + char *outbuf = NULL; + iconv_t ic; + size_t ic_inlen = inlen; + size_t ic_outlen = inlen * 2; + char *ic_outbuf = NULL; + size_t r = 0; + + if (inlen == 0) + return r; + + outbuf = crypt_safe_alloc(inlen * 2); + if (outbuf == NULL) + return -ENOMEM; + + memset(outbuf, 0, inlen * 2); + ic_outbuf = outbuf; + + ic = iconv_open("UTF-16LE", "UTF-8"); + r = iconv(ic, &input, &ic_inlen, &ic_outbuf, &ic_outlen); + iconv_close(ic); + + if (r == 0) { + *out = outbuf; + } else { + *out = NULL; + crypt_safe_free(outbuf); + log_dbg(cd, "Failed to convert passphrase: %s", strerror(errno)); + r = -errno; + } + + return r; +} + +static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, int end, struct bitlk_vmk **vmk) +{ + uint16_t key_entry_size = 0; + uint16_t key_entry_type = 0; + uint16_t key_entry_value = 0; + size_t key_size = 0; + char *string = NULL; + const char *key = NULL; + struct volume_key *vk = NULL; + bool supported = false; + + /* only passphrase or recovery passphrase vmks are supported (can be used to activate) */ + supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE || (*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE; + + while (end - start > 2) { + /* size of this entry */ + memcpy(&key_entry_size, data + start, sizeof(key_entry_size)); + key_entry_size = le16_to_cpu(key_entry_size); + if (key_entry_size == 0) + break; + + /* type and value of this entry */ + memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type)); + memcpy(&key_entry_value, + data + start + sizeof(key_entry_size) + sizeof(key_entry_type), + sizeof(key_entry_value)); + key_entry_type = le16_to_cpu(key_entry_type); + key_entry_value = le16_to_cpu(key_entry_value); + + if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) { + if (supported) { + log_err(cd, _("Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."), key_entry_type); + return -EINVAL; + } else { + log_dbg(cd, "Unexpected metadata entry type '%u' found when parsing unsupported VMK.", key_entry_type); + } + } + + /* stretch key with salt, skip 4 B (encryption method of the stretch key) */ + if (key_entry_value == BITLK_ENTRY_VALUE_STRETCH_KEY) + memcpy((*vmk)->salt, + data + start + BITLK_ENTRY_HEADER_LEN + 4, + sizeof((*vmk)->salt)); + /* AES-CCM encrypted key */ + else if (key_entry_value == BITLK_ENTRY_VALUE_ENCRYPTED_KEY) { + /* nonce */ + memcpy((*vmk)->nonce, + data + start + BITLK_ENTRY_HEADER_LEN, + sizeof((*vmk)->nonce)); + /* MAC tag */ + memcpy((*vmk)->mac_tag, + data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE, + sizeof((*vmk)->mac_tag)); + /* AES-CCM encrypted key */ + key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE); + key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE; + vk = crypt_alloc_volume_key(key_size, key); + if (vk == NULL) + return -ENOMEM; + crypt_volume_key_add_next(&((*vmk)->vk), vk); + /* clear key for a partially decrypted volume */ + } else if (key_entry_value == BITLK_ENTRY_VALUE_KEY) { + /* We currently don't want to support opening a partially decrypted + * device so we don't need to store this key. + * + * key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4); + * key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4; + * vk = crypt_alloc_volume_key(key_size, key); + * if (vk == NULL) + * return -ENOMEM; + * crypt_volume_key_add_next(&((*vmk)->vk), vk); + */ + log_dbg(cd, "Skipping clear key metadata entry."); + /* unknown timestamps in recovery protected VMK */ + } else if (key_entry_value == BITLK_ENTRY_VALUE_RECOVERY_TIME) { + ; + } else if (key_entry_value == BITLK_ENTRY_VALUE_STRING) { + if (convert_to_utf8(cd, data + start + BITLK_ENTRY_HEADER_LEN, key_entry_size - BITLK_ENTRY_HEADER_LEN, &string) < 0) { + log_err(cd, _("Invalid string found when parsing Volume Master Key.")); + free(string); + return -EINVAL; + } else if ((*vmk)->name != NULL) { + if (supported) { + log_err(cd, _("Unexpected string ('%s') found when parsing supported Volume Master Key."), string); + free(string); + return -EINVAL; + } + log_dbg(cd, "Unexpected string ('%s') found when parsing unsupported VMK.", string); + free(string); + string = NULL; + } else { + /* Assume that strings in VMK are the name of the VMK */ + (*vmk)->name = string; + string = NULL; + } + } else { + if (supported) { + log_err(cd, _("Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."), key_entry_value); + return -EINVAL; + } else { + log_dbg(cd, "Unexpected metadata entry value '%u' found when parsing unsupported VMK.", key_entry_value); + } + } + + start += key_entry_size; + } + + return 0; +} + +void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek) +{ + if (!fvek) + return; + + crypt_free_volume_key(fvek->vk); + free(fvek); +} + +void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk) +{ + struct bitlk_vmk *vmk_next = NULL; + + while (vmk) { + if (vmk->guid) + free(vmk->guid); + if (vmk->name) + free(vmk->name); + crypt_free_volume_key(vmk->vk); + vmk_next = vmk->next; + free(vmk); + vmk = vmk_next; + } +} + +void BITLK_bitlk_metadata_free(struct bitlk_metadata *metadata) +{ + free(metadata->guid); + if (metadata->description) + free(metadata->description); + BITLK_bitlk_vmk_free(metadata->vmks); + BITLK_bitlk_fvek_free(metadata->fvek); +} + +int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params) +{ + int devfd; + struct device *device = crypt_metadata_device(cd); + struct bitlk_signature sig = {}; + struct bitlk_superblock sb = {}; + struct bitlk_fve_metadata fve = {}; + struct bitlk_entry_vmk entry_vmk = {}; + uint8_t *fve_entries = NULL; + uint32_t fve_metadata_size = 0; + int fve_offset = 0; + char guid_buf[UUID_STR_LEN] = {0}; + uint16_t entry_size = 0; + uint16_t entry_type = 0; + int i = 0; + int r = 0; + int start = 0; + int end = 0; + size_t key_size = 0; + const char *key = NULL; + + struct bitlk_vmk *vmk = NULL; + struct bitlk_vmk *vmk_p = params->vmks; + + devfd = device_open(cd, crypt_data_device(cd), O_RDONLY); + if (devfd < 0) { + r = -EINVAL; + goto out; + } + + /* read and check the signature */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &sig, sizeof(sig), 0) != sizeof(sig)) { + log_err(cd, _("Failed to read BITLK signature from %s."), device_path(device)); + r = -EINVAL; + goto out; + } + + if (memcmp(sig.boot_code, BITLK_BOOTCODE_V1, sizeof(sig.boot_code)) == 0) { + log_err(cd, _("BITLK version 1 is currently not supported.")); + r = -ENOTSUP; + goto out; + } else if (memcmp(sig.boot_code, BITLK_BOOTCODE_V2, sizeof(sig.boot_code)) == 0) + ; + else { + log_err(cd, _("Invalid or unknown boot signature for BITLK device.")); + r = -EINVAL; + goto out; + } + + if (memcmp(sig.signature, BITLK_SIGNATURE, sizeof(sig.signature)) == 0) { + params->togo = false; + fve_offset = BITLK_HEADER_METADATA_OFFSET; + } else if (memcmp(sig.signature, BITLK_SIGNATURE_TOGO, sizeof(sig.signature)) == 0) { + params->togo = true; + fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO; + } else { + log_err(cd, _("Invalid or unknown signature for BITLK device.")); + r = -EINVAL; + goto out; + } + + params->sector_size = le16_to_cpu(sig.sector_size); + if (!(params->sector_size == 512 || params->sector_size == 4096)) { + log_err(cd, _("Unsupported sector size %" PRIu16 "."), params->sector_size); + r = -EINVAL; + goto out; + } + + /* read GUID and FVE metadata offsets */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &sb, sizeof(sb), fve_offset) != sizeof(sb)) { + log_err(cd, _("Failed to read BITLK header from %s."), device_path(device)); + r = -EINVAL; + goto out; + } + + /* get encryption "type" based on the GUID from BITLK superblock */ + if (memcmp(&sb.guid, BITLK_GUID_NORMAL, 16) == 0) + params->type = BITLK_ENCRYPTION_TYPE_NORMAL; + else if (memcmp(&sb.guid, BITLK_GUID_EOW, 16) == 0) + params->type = BITLK_ENCRYPTION_TYPE_EOW; + else + params->type = BITLK_ENCRYPTION_TYPE_UNKNOWN; + log_dbg(cd, "BITLK type from GUID: %s.", get_bitlk_type_string(params->type)); + + for (i = 0; i < 3; i++) + params->metadata_offset[i] = le64_to_cpu(sb.fve_offset[i]); + + log_dbg(cd, "Reading BITLK FVE metadata of size %zu on device %s, offset %" PRIu64 ".", + sizeof(fve), device_path(device), params->metadata_offset[0]); + + /* read FVE metadata from the first metadata area */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &fve, sizeof(fve), params->metadata_offset[0]) != sizeof(fve) || + memcmp(fve.signature, BITLK_SIGNATURE, sizeof(fve.signature)) || + le16_to_cpu(fve.fve_version) != 2) { + log_err(cd, _("Failed to read BITLK FVE metadata from %s."), device_path(device)); + r = -EINVAL; + goto out; + } + + /* check encryption state for the device */ + params->state = true; + if (le16_to_cpu(fve.curr_state) != BITLK_STATE_NORMAL || le16_to_cpu(fve.next_state) != BITLK_STATE_NORMAL) { + params->state = false; + log_dbg(cd, "Unknown/unsupported state detected. Current state: %"PRIu16", next state: %"PRIu16".", + le16_to_cpu(fve.curr_state), le16_to_cpu(fve.next_state)); + } + + params->metadata_version = le16_to_cpu(fve.fve_version); + fve_metadata_size = le32_to_cpu(fve.metadata_size); + + switch (le16_to_cpu(fve.encryption)) { + /* AES-CBC with Elephant difuser */ + case 0x8000: + params->key_size = 128; + params->cipher = "aes"; + params->cipher_mode = "cbc-elephant"; + break; + case 0x8001: + params->key_size = 256; + params->cipher = "aes"; + params->cipher_mode = "cbc-elephant"; + break; + /* AES-CBC */ + case 0x8002: + params->key_size = 128; + params->cipher = "aes"; + params->cipher_mode = "cbc-eboiv"; + break; + case 0x8003: + params->key_size = 256; + params->cipher = "aes"; + params->cipher_mode = "cbc-eboiv"; + break; + /* AES-XTS */ + case 0x8004: + params->key_size = 128; + params->cipher = "aes"; + params->cipher_mode = "xts-plain64"; + break; + case 0x8005: + params->key_size = 256; + params->cipher = "aes"; + params->cipher_mode = "xts-plain64"; + break; + default: + log_err(cd, _("Unknown or unsupported encryption type.")); + params->key_size = 0; + params->cipher = NULL; + params->cipher_mode = NULL; + r = -ENOTSUP; + goto out; + }; + + /* device GUID */ + guid_to_string(&fve.guid, guid_buf); + params->guid = strdup(guid_buf); + if (!params->guid) { + r = -ENOMEM; + goto out; + } + + params->creation_time = filetime_to_unixtime(le64_to_cpu(fve.creation_time)); + + /* read and parse all FVE metadata entries */ + fve_entries = malloc(fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN); + if (!fve_entries) { + r = -ENOMEM; + goto out; + } + memset(fve_entries, 0, (fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN)); + + log_dbg(cd, "Reading BITLK FVE metadata entries of size %" PRIu32 " on device %s, offset %" PRIu64 ".", + fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN, device_path(device), + params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN); + + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), fve_entries, fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN, + params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN) { + log_err(cd, _("Failed to read BITLK metadata entries from %s."), device_path(device)); + r = -EINVAL; + goto out; + } + + end = fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN; + while (end - start > 2) { + /* size of this entry */ + memcpy(&entry_size, fve_entries + start, sizeof(entry_size)); + entry_size = le16_to_cpu(entry_size); + if (entry_size == 0) + break; + + /* type of this entry */ + memcpy(&entry_type, fve_entries + start + sizeof(entry_size), sizeof(entry_type)); + entry_type = le16_to_cpu(entry_type); + + /* VMK */ + if (entry_type == BITLK_ENTRY_TYPE_VMK) { + /* skip first four variables in the entry (entry size, type, value and version) */ + memcpy(&entry_vmk, + fve_entries + start + BITLK_ENTRY_HEADER_LEN, + sizeof(entry_vmk)); + + vmk = malloc(sizeof(struct bitlk_vmk)); + memset(vmk, 0, sizeof(struct bitlk_vmk)); + + guid_to_string(&entry_vmk.guid, guid_buf); + vmk->guid = strdup (guid_buf); + + vmk->name = NULL; + + vmk->protection = get_vmk_protection(le16_to_cpu(entry_vmk.protection)); + + /* more data in another entry list */ + r = parse_vmk_entry(cd, fve_entries, + start + BITLK_ENTRY_HEADER_LEN + BITLK_VMK_HEADER_LEN, + start + entry_size, &vmk); + if (r < 0) { + BITLK_bitlk_vmk_free(vmk); + goto out; + } + + if (params->vmks == NULL) + params->vmks = vmk; + else + vmk_p->next = vmk; + + vmk_p = vmk; + vmk = vmk->next; + /* FVEK */ + } else if (entry_type == BITLK_ENTRY_TYPE_FVEK) { + params->fvek = malloc(sizeof(struct bitlk_fvek)); + memcpy(params->fvek->nonce, + fve_entries + start + BITLK_ENTRY_HEADER_LEN, + sizeof(params->fvek->nonce)); + /* MAC tag */ + memcpy(params->fvek->mac_tag, + fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE, + sizeof(params->fvek->mac_tag)); + /* AES-CCM encrypted key */ + key_size = entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE); + key = (const char *) fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE; + params->fvek->vk = crypt_alloc_volume_key(key_size, key); + if (params->fvek->vk == NULL) { + r = -ENOMEM; + goto out; + } + /* volume header info (location and size) */ + } else if (entry_type == BITLK_ENTRY_TYPE_VOLUME_HEADER) { + struct bitlk_entry_header_block entry_header; + memcpy(&entry_header, + fve_entries + start + BITLK_ENTRY_HEADER_LEN, + sizeof(entry_header)); + params->volume_header_offset = le64_to_cpu(entry_header.offset); + params->volume_header_size = le64_to_cpu(entry_header.size); + /* volume description (utf-16 string) */ + } else if (entry_type == BITLK_ENTRY_TYPE_DESCRIPTION) { + r = convert_to_utf8(cd, fve_entries + start + BITLK_ENTRY_HEADER_LEN, + entry_size - BITLK_ENTRY_HEADER_LEN, + &(params->description)); + if (r < 0) { + BITLK_bitlk_vmk_free(vmk); + goto out; + } + } + + start += entry_size; + } + +out: + if (fve_entries) + free(fve_entries); + return r; +} + +int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params) +{ + struct volume_key *vk_p; + struct bitlk_vmk *vmk_p; + int next_id = 0; + int i = 0; + + log_std(cd, "Info for BITLK%s device %s.\n", params->togo ? " To Go" : "", device_path(device)); + log_std(cd, "Version: \t%u\n", params->metadata_version); + log_std(cd, "GUID: \t%s\n", params->guid); + log_std(cd, "Sector size: \t%u [bytes]\n", params->sector_size); + log_std(cd, "Created: \t%s", ctime((time_t *)&(params->creation_time))); + log_std(cd, "Description: \t%s\n", params->description); + log_std(cd, "Cipher name: \t%s\n", params->cipher); + log_std(cd, "Cipher mode: \t%s\n", params->cipher_mode); + log_std(cd, "Cipher key: \t%u bits\n", params->key_size); + + log_std(cd, "\n"); + + log_std(cd, "Keyslots:\n"); + vmk_p = params->vmks; + while (vmk_p) { + log_std(cd, " %d: VMK\n", next_id); + if (vmk_p->name != NULL) { + log_std(cd, "\tName: \t%s\n", vmk_p->name); + } + log_std(cd, "\tGUID: \t%s\n", vmk_p->guid); + log_std(cd, "\tProtection: \t%s\n", get_vmk_protection_string (vmk_p->protection)); + log_std(cd, "\tSalt: \t"); + hexprint(cd, (const char *) vmk_p->salt, 16, ""); + log_std(cd, "\n"); + + vk_p = vmk_p->vk; + while (vk_p) { + log_std(cd, "\tKey data size:\t%zu [bytes]\n", vk_p->keylength); + vk_p = vk_p->next; + } + vmk_p = vmk_p->next; + next_id++; + } + + log_std(cd, " %d: FVEK\n", next_id); + log_std(cd, "\tKey data size:\t%zu [bytes]\n", params->fvek->vk->keylength); + + log_std(cd, "\n"); + + log_std(cd, "Metadata segments:\n"); + + for (i = 0; i < 3; i++) { + log_std(cd, " %d: FVE metadata area\n", i); + log_std(cd, "\tOffset: \t%" PRIu64 " [bytes]\n", params->metadata_offset[i]); + log_std(cd, "\tSize: \t%d [bytes]\n", BITLK_FVE_METADATA_SIZE); + } + + log_std(cd, " %d: Volume header\n", i); + log_std(cd, "\tOffset: \t%" PRIu64 " [bytes]\n", params->volume_header_offset); + log_std(cd, "\tSize: \t%" PRIu64 " [bytes]\n", params->volume_header_size); + log_std(cd, "\tCipher: \t%s-%s\n", params->cipher, params->cipher_mode); + + return 0; +} + +/* check if given passphrase can be a recovery key (has right format) and convert it */ +static int get_recovery_key(struct crypt_device *cd, + const char *password, + size_t passwordLen, + struct volume_key **rc_key) +{ + unsigned int i, j = 0; + uint16_t parts[BITLK_RECOVERY_PARTS] = {0}; + char part_str[BITLK_RECOVERY_PART_LEN + 1] = {0}; + long part_num = 0; + + /* check the passphrase it should be: + - 55 characters + - 8 groups of 6 divided by '-' + - each part is a number dividable by 11 + */ + if (passwordLen != BITLK_RECOVERY_KEY_LEN) { + if (passwordLen == BITLK_RECOVERY_KEY_LEN + 1 && password[passwordLen - 1] == '\n') { + /* looks like a recovery key with an extra newline, possibly from a key file */ + passwordLen--; + log_dbg(cd, "Possible extra EOL stripped from the recovery key."); + } else + return 0; + } + + for (i = BITLK_RECOVERY_PART_LEN; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1) { + if (password[i] != '-') + return 0; + } + + for (i = 0, j = 0; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1, j++) { + strncpy(part_str, password + i, BITLK_RECOVERY_PART_LEN); + + errno = 0; + part_num = strtol(part_str, NULL, 10); + if ((errno == ERANGE && (part_num == LONG_MAX || part_num == LONG_MIN)) || + (errno != 0 && part_num == 0)) + return -errno; + + if (part_num % 11 != 0) + return 0; + parts[j] = cpu_to_le16(part_num / 11); + } + + *rc_key = crypt_alloc_volume_key(16, (const char*) parts); + if (*rc_key == NULL) + return -ENOMEM; + + return 0; +} + +static int bitlk_kdf(struct crypt_device *cd, + const char *password, + size_t passwordLen, + bool recovery, + const uint8_t *salt, + struct volume_key **vk) +{ + struct bitlk_kdf_data kdf = {}; + struct crypt_hash *hd = NULL; + int len = 0; + char *utf16Password = NULL; + int i = 0; + int r = 0; + + memcpy(kdf.salt, salt, 16); + + r = crypt_hash_init(&hd, BITLK_KDF_HASH); + if (r < 0) + return r; + len = crypt_hash_size(BITLK_KDF_HASH); + if (len < 0) { + crypt_hash_destroy(hd); + return len; + } + + if (!recovery) { + /* passphrase: convert to UTF-16 first, then sha256(sha256(pw)) */ + r = passphrase_to_utf16(cd, CONST_CAST(char*)password, passwordLen, &utf16Password); + if (r < 0) + goto out; + + crypt_hash_write(hd, utf16Password, passwordLen * 2); + r = crypt_hash_final(hd, kdf.initial_sha256, len); + if (r < 0) + goto out; + + crypt_hash_write(hd, kdf.initial_sha256, len); + r = crypt_hash_final(hd, kdf.initial_sha256, len); + if (r < 0) + goto out; + } else { + /* recovery passphrase: already converted in #get_recovery_key, now just sha256(rpw) */ + crypt_hash_write(hd, password, passwordLen); + r = crypt_hash_final(hd, kdf.initial_sha256, len); + if (r < 0) + goto out; + } + + for (i = 0; i < BITLK_KDF_ITERATION_COUNT; i++) { + crypt_hash_write(hd, (const char*) &kdf, sizeof(kdf)); + r = crypt_hash_final(hd, kdf.last_sha256, len); + if (r < 0) + goto out; + kdf.count = cpu_to_le64(le64_to_cpu(kdf.count) + 1); + } + + *vk = crypt_alloc_volume_key(len, kdf.last_sha256); + +out: + crypt_safe_free(utf16Password); + if (hd) + crypt_hash_destroy(hd); + return r; +} + +static int decrypt_key(struct crypt_device *cd, + struct volume_key **vk, + struct volume_key *enc_key, + struct volume_key *key, + const uint8_t *tag, size_t tag_size, + const uint8_t *iv, size_t iv_size, + bool is_fvek) +{ + char *outbuf; + int r; + uint32_t key_size = 0; + + outbuf = crypt_safe_alloc(enc_key->keylength); + if (!outbuf) + return -ENOMEM; + + r = crypt_bitlk_decrypt_key(key->key, key->keylength, enc_key->key, outbuf, enc_key->keylength, + (const char*)iv, iv_size, (const char*)tag, tag_size); + if (r < 0) { + if (r == -ENOTSUP) + log_err(cd, _("This operation is not supported.")); + goto out; + } + + /* key_data has it's size as part of the metadata */ + memcpy(&key_size, outbuf, 4); + key_size = le32_to_cpu(key_size); + if (enc_key->keylength != key_size) { + log_err(cd, _("Wrong key size.")); + r = -EINVAL; + goto out; + } + + if (is_fvek && strcmp(crypt_get_cipher_mode(cd), "cbc-elephant") == 0 && + crypt_get_volume_key_size(cd) == 16) { + /* 128bit AES-CBC with Elephant -- key size is 256 bit (2 keys) but key data is 512 bits, + data: 16B CBC key, 16B empty, 16B elephant key, 16B empty */ + memcpy(outbuf + 16 + BITLK_OPEN_KEY_METADATA_LEN, + outbuf + 2 * 16 + BITLK_OPEN_KEY_METADATA_LEN, 16); + key_size = 32 + BITLK_OPEN_KEY_METADATA_LEN; + } + + + *vk = crypt_alloc_volume_key(key_size - BITLK_OPEN_KEY_METADATA_LEN, + (const char *)(outbuf + BITLK_OPEN_KEY_METADATA_LEN)); + r = *vk ? 0 : -ENOMEM; +out: + crypt_safe_free(outbuf); + return r; +} + +int BITLK_activate(struct crypt_device *cd, + const char *name, + const char *password, + size_t passwordLen, + const struct bitlk_metadata *params, + uint32_t flags) +{ + int r = 0; + int i = 0; + int j = 0; + int min = 0; + int num_segments = 0; + struct crypt_dm_active_device dmd = { + .flags = flags, + }; + struct dm_target *next_segment = NULL; + struct volume_key *open_vmk_key = NULL; + struct volume_key *open_fvek_key = NULL; + struct volume_key *vmk_dec_key = NULL; + struct volume_key *recovery_key = NULL; + const struct bitlk_vmk *next_vmk = NULL; + struct segment segments[MAX_BITLK_SEGMENTS] = {}; + struct segment temp; + uint64_t next_start = 0; + uint64_t next_end = 0; + uint64_t last_segment = 0; + uint32_t dmt_flags; + + if (!params->state) { + log_err(cd, _("This BITLK device is in an unsupported state and cannot be activated.")); + r = -ENOTSUP; + goto out; + } + + if (params->type != BITLK_ENCRYPTION_TYPE_NORMAL) { + log_err(cd, _("BITLK devices with type '%s' cannot be activated."), get_bitlk_type_string(params->type)); + r = -ENOTSUP; + goto out; + } + + next_vmk = params->vmks; + while (next_vmk) { + if (next_vmk->protection == BITLK_PROTECTION_PASSPHRASE) { + r = bitlk_kdf(cd, password, passwordLen, false, next_vmk->salt, &vmk_dec_key); + if (r) + return r; + } else if (next_vmk->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE) { + r = get_recovery_key(cd, password, passwordLen, &recovery_key); + if (r) + return r; + if (recovery_key == NULL) { + /* r = 0 but no key -> given passphrase is not a recovery passphrase */ + r = -EPERM; + next_vmk = next_vmk->next; + continue; + } + log_dbg(cd, "Trying to use given password as a recovery key."); + r = bitlk_kdf(cd, recovery_key->key, recovery_key->keylength, + true, next_vmk->salt, &vmk_dec_key); + crypt_free_volume_key(recovery_key); + if (r) + return r; + } else { + /* only passphrase and recovery passphrase VMKs supported right now */ + log_dbg(cd, "Skipping %s", get_vmk_protection_string(next_vmk->protection)); + next_vmk = next_vmk->next; + if (r == 0) + /* we need to set error code in case we have only unsupported VMKs */ + r = -ENOTSUP; + continue; + } + + log_dbg(cd, "Trying to decrypt %s.", get_vmk_protection_string(next_vmk->protection)); + r = decrypt_key(cd, &open_vmk_key, next_vmk->vk, vmk_dec_key, + next_vmk->mac_tag, BITLK_VMK_MAC_TAG_SIZE, + next_vmk->nonce, BITLK_NONCE_SIZE, false); + if (r < 0) { + log_dbg(cd, "Failed to decrypt VMK using provided passphrase."); + crypt_free_volume_key(vmk_dec_key); + if (r == -ENOTSUP) + return r; + next_vmk = next_vmk->next; + continue; + } + crypt_free_volume_key(vmk_dec_key); + + r = decrypt_key(cd, &open_fvek_key, params->fvek->vk, open_vmk_key, + params->fvek->mac_tag, BITLK_VMK_MAC_TAG_SIZE, + params->fvek->nonce, BITLK_NONCE_SIZE, true); + if (r < 0) { + log_dbg(cd, "Failed to decrypt FVEK using VMK."); + crypt_free_volume_key(open_vmk_key); + if (r == -ENOTSUP) + return r; + } else { + crypt_free_volume_key(open_vmk_key); + break; + } + + next_vmk = next_vmk->next; + } + + if (r) { + log_dbg(cd, "No more VMKs to try."); + return r; + } + + /* Password verify only */ + if (!name) { + crypt_free_volume_key(open_fvek_key); + return r; + } + + next_vmk = params->vmks; + while (next_vmk) { + if (next_vmk->protection == BITLK_PROTECTION_CLEAR_KEY) { + crypt_free_volume_key(open_fvek_key); + log_err(cd, _("Activation of partially decrypted BITLK device is not supported.")); + return -ENOTSUP; + } + next_vmk = next_vmk->next; + } + + r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL, + 0, &dmd.size, &dmd.flags); + if (r) { + crypt_free_volume_key(open_fvek_key); + return r; + } + + /* there will be always 4 dm-zero segments: 3x metadata, 1x FS header */ + for (i = 0; i < 3; i++) { + segments[num_segments].offset = params->metadata_offset[i] / SECTOR_SIZE; + segments[num_segments].length = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE; + segments[num_segments].iv_offset = 0; + segments[num_segments].type = BITLK_SEGTYPE_ZERO; + num_segments++; + } + segments[num_segments].offset = params->volume_header_offset / SECTOR_SIZE; + segments[num_segments].length = params->volume_header_size / SECTOR_SIZE; + segments[num_segments].iv_offset = 0; + segments[num_segments].type = BITLK_SEGTYPE_ZERO; + num_segments++; + + /* filesystem header (moved from the special location) */ + segments[num_segments].offset = 0; + segments[num_segments].length = params->volume_header_size / SECTOR_SIZE; + segments[num_segments].iv_offset = params->volume_header_offset / SECTOR_SIZE; + segments[num_segments].type = BITLK_SEGTYPE_CRYPT; + num_segments++; + + /* now fill gaps between the dm-zero segments with dm-crypt */ + last_segment = params->volume_header_size / SECTOR_SIZE; + while (true) { + next_start = dmd.size; + next_end = dmd.size; + + /* start of the next segment: end of the first existing segment after the last added */ + for (i = 0; i < num_segments; i++) + if (segments[i].offset + segments[i].length < next_start && segments[i].offset + segments[i].length >= last_segment) + next_start = segments[i].offset + segments[i].length; + + /* end of the next segment: start of the next segment after start we found above */ + for (i = 0; i < num_segments; i++) + if (segments[i].offset < next_end && segments[i].offset >= next_start) + next_end = segments[i].offset; + + /* two zero segments next to each other, just bump the last_segment + so the algorithm moves */ + if (next_end - next_start == 0) { + last_segment = next_end + 1; + continue; + } + + segments[num_segments].offset = next_start; + segments[num_segments].length = next_end - next_start; + segments[num_segments].iv_offset = next_start; + segments[num_segments].type = BITLK_SEGTYPE_CRYPT; + last_segment = next_end; + num_segments++; + + if (next_end == dmd.size) + break; + + if (num_segments == 10) { + log_dbg(cd, "Failed to calculate number of dm-crypt segments for open."); + r = -EINVAL; + goto out; + } + } + + /* device mapper needs the segment sorted */ + for (i = 0; i < num_segments - 1; i++) { + min = i; + for (j = i + 1; j < num_segments; j++) + if (segments[j].offset < segments[min].offset) + min = j; + + if (min != i) { + temp.offset = segments[min].offset; + temp.length = segments[min].length; + temp.iv_offset = segments[min].iv_offset; + temp.type = segments[min].type; + + segments[min].offset = segments[i].offset; + segments[min].length = segments[i].length; + segments[min].iv_offset = segments[i].iv_offset; + segments[min].type = segments[i].type; + + segments[i].offset = temp.offset; + segments[i].length = temp.length; + segments[i].iv_offset = temp.iv_offset; + segments[i].type = temp.type; + } + } + + if (params->sector_size != SECTOR_SIZE) + dmd.flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS; + + r = dm_targets_allocate(&dmd.segment, num_segments); + if (r) + goto out; + next_segment = &dmd.segment; + + for (i = 0; i < num_segments; i++) { + if (segments[i].type == BITLK_SEGTYPE_ZERO) + r = dm_zero_target_set(next_segment, + segments[i].offset, + segments[i].length); + else if (segments[i].type == BITLK_SEGTYPE_CRYPT) + r = dm_crypt_target_set(next_segment, + segments[i].offset, + segments[i].length, + crypt_data_device(cd), + open_fvek_key, + crypt_get_cipher_spec(cd), + segments[i].iv_offset, + segments[i].iv_offset, + NULL, 0, + params->sector_size); + if (r) + goto out; + + next_segment = next_segment->next; + } + + log_dbg(cd, "Trying to activate BITLK on device %s%s%s.", + device_path(crypt_data_device(cd)), name ? " with name " :"", name ?: ""); + + r = dm_create_device(cd, name, CRYPT_BITLK, &dmd); + if (r < 0) { + dm_flags(cd, DM_CRYPT, &dmt_flags); + if (!strcmp(params->cipher_mode, "cbc-eboiv") && !(dmt_flags & DM_BITLK_EBOIV_SUPPORTED)) { + log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for BITLK IV.")); + r = -ENOTSUP; + } + if (!strcmp(params->cipher_mode, "cbc-elephant") && !(dmt_flags & DM_BITLK_ELEPHANT_SUPPORTED)) { + log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser.")); + r = -ENOTSUP; + } + } +out: + dm_targets_free(cd, &dmd); + crypt_free_volume_key(open_fvek_key); + return r; +} diff --git a/lib/bitlk/bitlk.h b/lib/bitlk/bitlk.h new file mode 100644 index 0000000..a784883 --- /dev/null +++ b/lib/bitlk/bitlk.h @@ -0,0 +1,131 @@ +/* + * BITLK (BitLocker-compatible) header definition + * + * Copyright (C) 2019-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2019-2020 Milan Broz + * Copyright (C) 2019-2020 Vojtech Trefny + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_BITLK_H +#define _CRYPTSETUP_BITLK_H + +#include +#include +#include + +struct crypt_device; +struct device; + +#define BITLK_NONCE_SIZE 12 +#define BITLK_SALT_SIZE 16 +#define BITLK_VMK_MAC_TAG_SIZE 16 + +#define BITLK_STATE_NORMAL 0x0004 + +typedef enum { + BITLK_ENCRYPTION_TYPE_NORMAL = 0, + BITLK_ENCRYPTION_TYPE_EOW, + BITLK_ENCRYPTION_TYPE_UNKNOWN, +} BITLKEncryptionType; + +typedef enum { + BITLK_PROTECTION_CLEAR_KEY = 0, + BITLK_PROTECTION_TPM, + BITLK_PROTECTION_STARTUP_KEY, + BITLK_PROTECTION_TPM_PIN, + BITLK_PROTECTION_RECOVERY_PASSPHRASE, + BITLK_PROTECTION_PASSPHRASE, + BITLK_PROTECTION_SMART_CARD, + BITLK_PROTECTION_UNKNOWN, +} BITLKVMKProtection; + +typedef enum { + BITLK_ENTRY_TYPE_PROPERTY = 0x0000, + BITLK_ENTRY_TYPE_VMK = 0x0002, + BITLK_ENTRY_TYPE_FVEK = 0x0003, + BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006, + BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007, + BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f, +} BITLKFVEEntryType; + +typedef enum { + BITLK_ENTRY_VALUE_ERASED = 0x0000, + BITLK_ENTRY_VALUE_KEY = 0x0001, + BITLK_ENTRY_VALUE_STRING = 0x0002, + BITLK_ENTRY_VALUE_STRETCH_KEY = 0x0003, + BITLK_ENTRY_VALUE_USE_KEY = 0x0004, + BITLK_ENTRY_VALUE_ENCRYPTED_KEY = 0x0005, + BITLK_ENTRY_VALUE_TPM_KEY = 0x0006, + BITLK_ENTRY_VALUE_VALIDATION = 0x0007, + BITLK_ENTRY_VALUE_VMK = 0x0008, + BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009, + BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f, + BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015, +} BITLKFVEEntryValue; + +struct bitlk_vmk { + char *guid; + char *name; + BITLKVMKProtection protection; + uint8_t salt[BITLK_SALT_SIZE]; + uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE]; + uint8_t nonce[BITLK_NONCE_SIZE]; + struct volume_key *vk; + struct bitlk_vmk *next; +}; + +struct bitlk_fvek { + uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE]; + uint8_t nonce[BITLK_NONCE_SIZE]; + struct volume_key *vk; +}; + +struct bitlk_metadata { + uint16_t sector_size; + bool togo; + bool state; + BITLKEncryptionType type; + const char *cipher; + const char *cipher_mode; + uint16_t key_size; + char *guid; + uint64_t creation_time; + char *description; + uint64_t metadata_offset[3]; + uint32_t metadata_version; + uint64_t volume_header_offset; + uint64_t volume_header_size; + struct bitlk_vmk *vmks; + struct bitlk_fvek *fvek; +}; + +int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params); + +int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params); + +int BITLK_activate(struct crypt_device *cd, + const char *name, + const char *password, + size_t passwordLen, + const struct bitlk_metadata *params, + uint32_t flags); + +void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek); +void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk); +void BITLK_bitlk_metadata_free(struct bitlk_metadata *params); + +#endif diff --git a/lib/crypt_plain.c b/lib/crypt_plain.c index 3f8e96b..77d72fc 100644 --- a/lib/crypt_plain.c +++ b/lib/crypt_plain.c @@ -1,9 +1,9 @@ /* * cryptsetup plain device helper functions * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2012, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -64,7 +64,7 @@ static int hash(const char *hash_name, size_t key_size, char *key, #define PLAIN_HASH_LEN_MAX 256 -int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)), +int crypt_plain_hash(struct crypt_device *cd, const char *hash_name, char *key, size_t key_size, const char *passphrase, size_t passphrase_size) @@ -73,7 +73,7 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)), size_t hash_size, pad_size; int r; - log_dbg("Plain: hashing passphrase using %s.", hash_name); + log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name); if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX) return -EINVAL; @@ -85,11 +85,11 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)), *s = '\0'; s++; if (!*s || sscanf(s, "%zd", &hash_size) != 1) { - log_dbg("Hash length is not a number"); + log_dbg(cd, "Hash length is not a number"); return -EINVAL; } if (hash_size > key_size) { - log_dbg("Hash length %zd > key length %zd", + log_dbg(cd, "Hash length %zd > key length %zd", hash_size, key_size); return -EINVAL; } @@ -102,7 +102,7 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)), /* No hash, copy passphrase directly */ if (!strcmp(hash_name_buf, "plain")) { if (passphrase_size < hash_size) { - log_dbg("Too short plain passphrase."); + log_dbg(cd, "Too short plain passphrase."); return -EINVAL; } memcpy(key, passphrase, hash_size); diff --git a/lib/crypto_backend/Makefile.am b/lib/crypto_backend/Makefile.am deleted file mode 100644 index 942d258..0000000 --- a/lib/crypto_backend/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -moduledir = $(libdir)/cryptsetup - -noinst_LTLIBRARIES = libcrypto_backend.la - -libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@ - -libcrypto_backend_la_SOURCES = crypto_backend.h \ - crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c - -if CRYPTO_BACKEND_GCRYPT -libcrypto_backend_la_SOURCES += crypto_gcrypt.c -endif -if CRYPTO_BACKEND_OPENSSL -libcrypto_backend_la_SOURCES += crypto_openssl.c -endif -if CRYPTO_BACKEND_NSS -libcrypto_backend_la_SOURCES += crypto_nss.c -endif -if CRYPTO_BACKEND_KERNEL -libcrypto_backend_la_SOURCES += crypto_kernel.c -endif -if CRYPTO_BACKEND_NETTLE -libcrypto_backend_la_SOURCES += crypto_nettle.c -endif - -if CRYPTO_INTERNAL_PBKDF2 -libcrypto_backend_la_SOURCES += pbkdf2_generic.c -endif - -AM_CPPFLAGS = -include config.h -I$(top_srcdir)/lib diff --git a/lib/crypto_backend/Makefile.in b/lib/crypto_backend/Makefile.in deleted file mode 100644 index cb6dcfc..0000000 --- a/lib/crypto_backend/Makefile.in +++ /dev/null @@ -1,738 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@CRYPTO_BACKEND_GCRYPT_TRUE@am__append_1 = crypto_gcrypt.c -@CRYPTO_BACKEND_OPENSSL_TRUE@am__append_2 = crypto_openssl.c -@CRYPTO_BACKEND_NSS_TRUE@am__append_3 = crypto_nss.c -@CRYPTO_BACKEND_KERNEL_TRUE@am__append_4 = crypto_kernel.c -@CRYPTO_BACKEND_NETTLE_TRUE@am__append_5 = crypto_nettle.c -@CRYPTO_INTERNAL_PBKDF2_TRUE@am__append_6 = pbkdf2_generic.c -subdir = lib/crypto_backend -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libcrypto_backend_la_LIBADD = -am__libcrypto_backend_la_SOURCES_DIST = crypto_backend.h \ - crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c \ - crypto_gcrypt.c crypto_openssl.c crypto_nss.c crypto_kernel.c \ - crypto_nettle.c pbkdf2_generic.c -@CRYPTO_BACKEND_GCRYPT_TRUE@am__objects_1 = libcrypto_backend_la-crypto_gcrypt.lo -@CRYPTO_BACKEND_OPENSSL_TRUE@am__objects_2 = libcrypto_backend_la-crypto_openssl.lo -@CRYPTO_BACKEND_NSS_TRUE@am__objects_3 = \ -@CRYPTO_BACKEND_NSS_TRUE@ libcrypto_backend_la-crypto_nss.lo -@CRYPTO_BACKEND_KERNEL_TRUE@am__objects_4 = libcrypto_backend_la-crypto_kernel.lo -@CRYPTO_BACKEND_NETTLE_TRUE@am__objects_5 = libcrypto_backend_la-crypto_nettle.lo -@CRYPTO_INTERNAL_PBKDF2_TRUE@am__objects_6 = libcrypto_backend_la-pbkdf2_generic.lo -am_libcrypto_backend_la_OBJECTS = \ - libcrypto_backend_la-crypto_cipher_kernel.lo \ - libcrypto_backend_la-crypto_storage.lo \ - libcrypto_backend_la-pbkdf_check.lo \ - libcrypto_backend_la-crc32.lo $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) $(am__objects_6) -libcrypto_backend_la_OBJECTS = $(am_libcrypto_backend_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libcrypto_backend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(libcrypto_backend_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libcrypto_backend_la_SOURCES) -DIST_SOURCES = $(am__libcrypto_backend_la_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -moduledir = $(libdir)/cryptsetup -noinst_LTLIBRARIES = libcrypto_backend.la -libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@ -libcrypto_backend_la_SOURCES = crypto_backend.h crypto_cipher_kernel.c \ - crypto_storage.c pbkdf_check.c crc32.c $(am__append_1) \ - $(am__append_2) $(am__append_3) $(am__append_4) \ - $(am__append_5) $(am__append_6) -AM_CPPFLAGS = -include config.h -I$(top_srcdir)/lib -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/crypto_backend/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/crypto_backend/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libcrypto_backend.la: $(libcrypto_backend_la_OBJECTS) $(libcrypto_backend_la_DEPENDENCIES) $(EXTRA_libcrypto_backend_la_DEPENDENCIES) - $(AM_V_CCLD)$(libcrypto_backend_la_LINK) $(libcrypto_backend_la_OBJECTS) $(libcrypto_backend_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crc32.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libcrypto_backend_la-crypto_cipher_kernel.lo: crypto_cipher_kernel.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_cipher_kernel.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Tpo -c -o libcrypto_backend_la-crypto_cipher_kernel.lo `test -f 'crypto_cipher_kernel.c' || echo '$(srcdir)/'`crypto_cipher_kernel.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_cipher_kernel.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_cipher_kernel.c' object='libcrypto_backend_la-crypto_cipher_kernel.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_cipher_kernel.lo `test -f 'crypto_cipher_kernel.c' || echo '$(srcdir)/'`crypto_cipher_kernel.c - -libcrypto_backend_la-crypto_storage.lo: crypto_storage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_storage.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_storage.Tpo -c -o libcrypto_backend_la-crypto_storage.lo `test -f 'crypto_storage.c' || echo '$(srcdir)/'`crypto_storage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_storage.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_storage.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_storage.c' object='libcrypto_backend_la-crypto_storage.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_storage.lo `test -f 'crypto_storage.c' || echo '$(srcdir)/'`crypto_storage.c - -libcrypto_backend_la-pbkdf_check.lo: pbkdf_check.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-pbkdf_check.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-pbkdf_check.Tpo -c -o libcrypto_backend_la-pbkdf_check.lo `test -f 'pbkdf_check.c' || echo '$(srcdir)/'`pbkdf_check.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-pbkdf_check.Tpo $(DEPDIR)/libcrypto_backend_la-pbkdf_check.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pbkdf_check.c' object='libcrypto_backend_la-pbkdf_check.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-pbkdf_check.lo `test -f 'pbkdf_check.c' || echo '$(srcdir)/'`pbkdf_check.c - -libcrypto_backend_la-crc32.lo: crc32.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crc32.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crc32.Tpo -c -o libcrypto_backend_la-crc32.lo `test -f 'crc32.c' || echo '$(srcdir)/'`crc32.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crc32.Tpo $(DEPDIR)/libcrypto_backend_la-crc32.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crc32.c' object='libcrypto_backend_la-crc32.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crc32.lo `test -f 'crc32.c' || echo '$(srcdir)/'`crc32.c - -libcrypto_backend_la-crypto_gcrypt.lo: crypto_gcrypt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_gcrypt.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Tpo -c -o libcrypto_backend_la-crypto_gcrypt.lo `test -f 'crypto_gcrypt.c' || echo '$(srcdir)/'`crypto_gcrypt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_gcrypt.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_gcrypt.c' object='libcrypto_backend_la-crypto_gcrypt.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_gcrypt.lo `test -f 'crypto_gcrypt.c' || echo '$(srcdir)/'`crypto_gcrypt.c - -libcrypto_backend_la-crypto_openssl.lo: crypto_openssl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_openssl.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_openssl.Tpo -c -o libcrypto_backend_la-crypto_openssl.lo `test -f 'crypto_openssl.c' || echo '$(srcdir)/'`crypto_openssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_openssl.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_openssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_openssl.c' object='libcrypto_backend_la-crypto_openssl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_openssl.lo `test -f 'crypto_openssl.c' || echo '$(srcdir)/'`crypto_openssl.c - -libcrypto_backend_la-crypto_nss.lo: crypto_nss.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_nss.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_nss.Tpo -c -o libcrypto_backend_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_nss.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_nss.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_nss.c' object='libcrypto_backend_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c - -libcrypto_backend_la-crypto_kernel.lo: crypto_kernel.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_kernel.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_kernel.Tpo -c -o libcrypto_backend_la-crypto_kernel.lo `test -f 'crypto_kernel.c' || echo '$(srcdir)/'`crypto_kernel.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_kernel.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_kernel.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_kernel.c' object='libcrypto_backend_la-crypto_kernel.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_kernel.lo `test -f 'crypto_kernel.c' || echo '$(srcdir)/'`crypto_kernel.c - -libcrypto_backend_la-crypto_nettle.lo: crypto_nettle.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-crypto_nettle.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-crypto_nettle.Tpo -c -o libcrypto_backend_la-crypto_nettle.lo `test -f 'crypto_nettle.c' || echo '$(srcdir)/'`crypto_nettle.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-crypto_nettle.Tpo $(DEPDIR)/libcrypto_backend_la-crypto_nettle.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto_nettle.c' object='libcrypto_backend_la-crypto_nettle.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-crypto_nettle.lo `test -f 'crypto_nettle.c' || echo '$(srcdir)/'`crypto_nettle.c - -libcrypto_backend_la-pbkdf2_generic.lo: pbkdf2_generic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -MT libcrypto_backend_la-pbkdf2_generic.lo -MD -MP -MF $(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Tpo -c -o libcrypto_backend_la-pbkdf2_generic.lo `test -f 'pbkdf2_generic.c' || echo '$(srcdir)/'`pbkdf2_generic.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Tpo $(DEPDIR)/libcrypto_backend_la-pbkdf2_generic.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pbkdf2_generic.c' object='libcrypto_backend_la-pbkdf2_generic.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcrypto_backend_la_CFLAGS) $(CFLAGS) -c -o libcrypto_backend_la-pbkdf2_generic.lo `test -f 'pbkdf2_generic.c' || echo '$(srcdir)/'`pbkdf2_generic.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/crypto_backend/Makemodule.am b/lib/crypto_backend/Makemodule.am new file mode 100644 index 0000000..f33cd45 --- /dev/null +++ b/lib/crypto_backend/Makemodule.am @@ -0,0 +1,39 @@ +noinst_LTLIBRARIES += libcrypto_backend.la + +libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@ + +libcrypto_backend_la_SOURCES = \ + lib/crypto_backend/crypto_backend.h \ + lib/crypto_backend/crypto_backend_internal.h \ + lib/crypto_backend/crypto_cipher_kernel.c \ + lib/crypto_backend/crypto_storage.c \ + lib/crypto_backend/pbkdf_check.c \ + lib/crypto_backend/crc32.c \ + lib/crypto_backend/argon2_generic.c \ + lib/crypto_backend/cipher_generic.c \ + lib/crypto_backend/cipher_check.c + +if CRYPTO_BACKEND_GCRYPT +libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_gcrypt.c +endif +if CRYPTO_BACKEND_OPENSSL +libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_openssl.c +endif +if CRYPTO_BACKEND_NSS +libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nss.c +endif +if CRYPTO_BACKEND_KERNEL +libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_kernel.c +endif +if CRYPTO_BACKEND_NETTLE +libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nettle.c +endif + +if CRYPTO_INTERNAL_PBKDF2 +libcrypto_backend_la_SOURCES += lib/crypto_backend/pbkdf2_generic.c +endif + +if CRYPTO_INTERNAL_ARGON2 +libcrypto_backend_la_DEPENDENCIES = libargon2.la +libcrypto_backend_la_LIBADD = libargon2.la +endif diff --git a/lib/crypto_backend/argon2/LICENSE b/lib/crypto_backend/argon2/LICENSE new file mode 100644 index 0000000..de14cd2 --- /dev/null +++ b/lib/crypto_backend/argon2/LICENSE @@ -0,0 +1,30 @@ + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + moral rights retained by the original author(s) and/or performer(s); + publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + rights protecting the extraction, dissemination, use and reuse of data in a Work; + database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. diff --git a/lib/crypto_backend/argon2/Makemodule.am b/lib/crypto_backend/argon2/Makemodule.am new file mode 100644 index 0000000..6fef2f1 --- /dev/null +++ b/lib/crypto_backend/argon2/Makemodule.am @@ -0,0 +1,30 @@ +noinst_LTLIBRARIES += libargon2.la + +libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3 +libargon2_la_CPPFLAGS = $(AM_CPPFLAGS) \ + -I lib/crypto_backend/argon2 \ + -I lib/crypto_backend/argon2/blake2 + +libargon2_la_SOURCES = \ + lib/crypto_backend/argon2/blake2/blake2b.c \ + lib/crypto_backend/argon2/blake2/blake2.h \ + lib/crypto_backend/argon2/blake2/blake2-impl.h \ + lib/crypto_backend/argon2/argon2.c \ + lib/crypto_backend/argon2/argon2.h \ + lib/crypto_backend/argon2/core.c \ + lib/crypto_backend/argon2/core.h \ + lib/crypto_backend/argon2/encoding.c \ + lib/crypto_backend/argon2/encoding.h \ + lib/crypto_backend/argon2/thread.c \ + lib/crypto_backend/argon2/thread.h + +if CRYPTO_INTERNAL_SSE_ARGON2 +libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-opt.h \ + lib/crypto_backend/argon2/opt.c +else +libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-ref.h \ + lib/crypto_backend/argon2/ref.c +endif + +EXTRA_DIST += lib/crypto_backend/argon2/LICENSE +EXTRA_DIST += lib/crypto_backend/argon2/README diff --git a/lib/crypto_backend/argon2/README b/lib/crypto_backend/argon2/README new file mode 100644 index 0000000..5376b52 --- /dev/null +++ b/lib/crypto_backend/argon2/README @@ -0,0 +1,5 @@ +This is bundled Argon2 algorithm library, copied from + https://github.com/P-H-C/phc-winner-argon2 + +For more info see Password Hashing Competition site: + https://password-hashing.net/ diff --git a/lib/crypto_backend/argon2/argon2.c b/lib/crypto_backend/argon2/argon2.c new file mode 100644 index 0000000..f748bcc --- /dev/null +++ b/lib/crypto_backend/argon2/argon2.c @@ -0,0 +1,456 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include + +#include "argon2.h" +#include "encoding.h" +#include "core.h" + +/* to silent gcc -Wcast-qual for const cast */ +#define CONST_CAST(x) (x)(uintptr_t) + +const char *argon2_type2string(argon2_type type, int uppercase) { + switch (type) { + case Argon2_d: + return uppercase ? "Argon2d" : "argon2d"; + case Argon2_i: + return uppercase ? "Argon2i" : "argon2i"; + case Argon2_id: + return uppercase ? "Argon2id" : "argon2id"; + } + + return NULL; +} + +int argon2_ctx(argon2_context *context, argon2_type type) { + /* 1. Validate all inputs */ + int result = validate_inputs(context); + uint32_t memory_blocks, segment_length; + argon2_instance_t instance; + + if (ARGON2_OK != result) { + return result; + } + + if (Argon2_d != type && Argon2_i != type && Argon2_id != type) { + return ARGON2_INCORRECT_TYPE; + } + + /* 2. Align memory size */ + /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */ + memory_blocks = context->m_cost; + + if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { + memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes; + } + + segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS); + /* Ensure that all segments have equal length */ + memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS); + + instance.version = context->version; + instance.memory = NULL; + instance.passes = context->t_cost; + instance.memory_blocks = memory_blocks; + instance.segment_length = segment_length; + instance.lane_length = segment_length * ARGON2_SYNC_POINTS; + instance.lanes = context->lanes; + instance.threads = context->threads; + instance.type = type; + + if (instance.threads > instance.lanes) { + instance.threads = instance.lanes; + } + + /* 3. Initialization: Hashing inputs, allocating memory, filling first + * blocks + */ + result = initialize(&instance, context); + + if (ARGON2_OK != result) { + return result; + } + + /* 4. Filling memory */ + result = fill_memory_blocks(&instance); + + if (ARGON2_OK != result) { + return result; + } + /* 5. Finalization */ + finalize(context, &instance); + + return ARGON2_OK; +} + +int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, const size_t saltlen, + void *hash, const size_t hashlen, char *encoded, + const size_t encodedlen, argon2_type type, + const uint32_t version){ + + argon2_context context; + int result; + uint8_t *out; + + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } + + if (saltlen > ARGON2_MAX_SALT_LENGTH) { + return ARGON2_SALT_TOO_LONG; + } + + if (hashlen > ARGON2_MAX_OUTLEN) { + return ARGON2_OUTPUT_TOO_LONG; + } + + if (hashlen < ARGON2_MIN_OUTLEN) { + return ARGON2_OUTPUT_TOO_SHORT; + } + + out = malloc(hashlen); + if (!out) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + context.out = (uint8_t *)out; + context.outlen = (uint32_t)hashlen; + context.pwd = CONST_CAST(uint8_t *)pwd; + context.pwdlen = (uint32_t)pwdlen; + context.salt = CONST_CAST(uint8_t *)salt; + context.saltlen = (uint32_t)saltlen; + context.secret = NULL; + context.secretlen = 0; + context.ad = NULL; + context.adlen = 0; + context.t_cost = t_cost; + context.m_cost = m_cost; + context.lanes = parallelism; + context.threads = parallelism; + context.allocate_cbk = NULL; + context.free_cbk = NULL; + context.flags = ARGON2_DEFAULT_FLAGS; + context.version = version; + + result = argon2_ctx(&context, type); + + if (result != ARGON2_OK) { + clear_internal_memory(out, hashlen); + free(out); + return result; + } + + /* if raw hash requested, write it */ + if (hash) { + memcpy(hash, out, hashlen); + } + + /* if encoding requested, write it */ + if (encoded && encodedlen) { + if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) { + clear_internal_memory(out, hashlen); /* wipe buffers if error */ + clear_internal_memory(encoded, encodedlen); + free(out); + return ARGON2_ENCODING_FAIL; + } + } + clear_internal_memory(out, hashlen); + free(out); + + return ARGON2_OK; +} + +int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, const size_t hashlen, + char *encoded, const size_t encodedlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + NULL, hashlen, encoded, encodedlen, Argon2_i, + ARGON2_VERSION_NUMBER); +} + +int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, const size_t hashlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER); +} + +int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, const size_t hashlen, + char *encoded, const size_t encodedlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + NULL, hashlen, encoded, encodedlen, Argon2_d, + ARGON2_VERSION_NUMBER); +} + +int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, const size_t hashlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER); +} + +int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, const size_t hashlen, + char *encoded, const size_t encodedlen) { + + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + NULL, hashlen, encoded, encodedlen, Argon2_id, + ARGON2_VERSION_NUMBER); +} + +int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, const size_t hashlen) { + return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, + hash, hashlen, NULL, 0, Argon2_id, + ARGON2_VERSION_NUMBER); +} + +static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) { + size_t i; + uint8_t d = 0U; + + for (i = 0U; i < len; i++) { + d |= b1[i] ^ b2[i]; + } + return (int)((1 & ((d - 1) >> 8)) - 1); +} + +int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, + argon2_type type) { + + argon2_context ctx; + uint8_t *desired_result = NULL; + + int ret = ARGON2_OK; + + size_t encoded_len; + uint32_t max_field_len; + + if (pwdlen > ARGON2_MAX_PWD_LENGTH) { + return ARGON2_PWD_TOO_LONG; + } + + if (encoded == NULL) { + return ARGON2_DECODING_FAIL; + } + + encoded_len = strlen(encoded); + if (encoded_len > UINT32_MAX) { + return ARGON2_DECODING_FAIL; + } + + /* No field can be longer than the encoded length */ + /* coverity[strlen_assign] */ + max_field_len = (uint32_t)encoded_len; + + ctx.saltlen = max_field_len; + ctx.outlen = max_field_len; + + ctx.salt = malloc(ctx.saltlen); + ctx.out = malloc(ctx.outlen); + if (!ctx.salt || !ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + ctx.pwd = CONST_CAST(uint8_t *)pwd; + ctx.pwdlen = (uint32_t)pwdlen; + + ret = decode_string(&ctx, encoded, type); + if (ret != ARGON2_OK) { + goto fail; + } + + /* Set aside the desired result, and get a new buffer. */ + desired_result = ctx.out; + ctx.out = malloc(ctx.outlen); + if (!ctx.out) { + ret = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + ret = argon2_verify_ctx(&ctx, (char *)desired_result, type); + if (ret != ARGON2_OK) { + goto fail; + } + +fail: + free(ctx.salt); + free(ctx.out); + free(desired_result); + + return ret; +} + +int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) { + + return argon2_verify(encoded, pwd, pwdlen, Argon2_i); +} + +int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) { + + return argon2_verify(encoded, pwd, pwdlen, Argon2_d); +} + +int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) { + + return argon2_verify(encoded, pwd, pwdlen, Argon2_id); +} + +int argon2d_ctx(argon2_context *context) { + return argon2_ctx(context, Argon2_d); +} + +int argon2i_ctx(argon2_context *context) { + return argon2_ctx(context, Argon2_i); +} + +int argon2id_ctx(argon2_context *context) { + return argon2_ctx(context, Argon2_id); +} + +int argon2_verify_ctx(argon2_context *context, const char *hash, + argon2_type type) { + int ret = argon2_ctx(context, type); + if (ret != ARGON2_OK) { + return ret; + } + + if (argon2_compare(CONST_CAST(uint8_t *)hash, context->out, context->outlen)) { + return ARGON2_VERIFY_MISMATCH; + } + + return ARGON2_OK; +} + +int argon2d_verify_ctx(argon2_context *context, const char *hash) { + return argon2_verify_ctx(context, hash, Argon2_d); +} + +int argon2i_verify_ctx(argon2_context *context, const char *hash) { + return argon2_verify_ctx(context, hash, Argon2_i); +} + +int argon2id_verify_ctx(argon2_context *context, const char *hash) { + return argon2_verify_ctx(context, hash, Argon2_id); +} + +const char *argon2_error_message(int error_code) { + switch (error_code) { + case ARGON2_OK: + return "OK"; + case ARGON2_OUTPUT_PTR_NULL: + return "Output pointer is NULL"; + case ARGON2_OUTPUT_TOO_SHORT: + return "Output is too short"; + case ARGON2_OUTPUT_TOO_LONG: + return "Output is too long"; + case ARGON2_PWD_TOO_SHORT: + return "Password is too short"; + case ARGON2_PWD_TOO_LONG: + return "Password is too long"; + case ARGON2_SALT_TOO_SHORT: + return "Salt is too short"; + case ARGON2_SALT_TOO_LONG: + return "Salt is too long"; + case ARGON2_AD_TOO_SHORT: + return "Associated data is too short"; + case ARGON2_AD_TOO_LONG: + return "Associated data is too long"; + case ARGON2_SECRET_TOO_SHORT: + return "Secret is too short"; + case ARGON2_SECRET_TOO_LONG: + return "Secret is too long"; + case ARGON2_TIME_TOO_SMALL: + return "Time cost is too small"; + case ARGON2_TIME_TOO_LARGE: + return "Time cost is too large"; + case ARGON2_MEMORY_TOO_LITTLE: + return "Memory cost is too small"; + case ARGON2_MEMORY_TOO_MUCH: + return "Memory cost is too large"; + case ARGON2_LANES_TOO_FEW: + return "Too few lanes"; + case ARGON2_LANES_TOO_MANY: + return "Too many lanes"; + case ARGON2_PWD_PTR_MISMATCH: + return "Password pointer is NULL, but password length is not 0"; + case ARGON2_SALT_PTR_MISMATCH: + return "Salt pointer is NULL, but salt length is not 0"; + case ARGON2_SECRET_PTR_MISMATCH: + return "Secret pointer is NULL, but secret length is not 0"; + case ARGON2_AD_PTR_MISMATCH: + return "Associated data pointer is NULL, but ad length is not 0"; + case ARGON2_MEMORY_ALLOCATION_ERROR: + return "Memory allocation error"; + case ARGON2_FREE_MEMORY_CBK_NULL: + return "The free memory callback is NULL"; + case ARGON2_ALLOCATE_MEMORY_CBK_NULL: + return "The allocate memory callback is NULL"; + case ARGON2_INCORRECT_PARAMETER: + return "Argon2_Context context is NULL"; + case ARGON2_INCORRECT_TYPE: + return "There is no such version of Argon2"; + case ARGON2_OUT_PTR_MISMATCH: + return "Output pointer mismatch"; + case ARGON2_THREADS_TOO_FEW: + return "Not enough threads"; + case ARGON2_THREADS_TOO_MANY: + return "Too many threads"; + case ARGON2_MISSING_ARGS: + return "Missing arguments"; + case ARGON2_ENCODING_FAIL: + return "Encoding failed"; + case ARGON2_DECODING_FAIL: + return "Decoding failed"; + case ARGON2_THREAD_FAIL: + return "Threading failure"; + case ARGON2_DECODING_LENGTH_FAIL: + return "Some of encoded parameters are too long or too short"; + case ARGON2_VERIFY_MISMATCH: + return "The password does not match the supplied hash"; + default: + return "Unknown error code"; + } +} + +size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism, + uint32_t saltlen, uint32_t hashlen, argon2_type type) { + return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) + + numlen(t_cost) + numlen(m_cost) + numlen(parallelism) + + b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1; +} diff --git a/lib/crypto_backend/argon2/argon2.h b/lib/crypto_backend/argon2/argon2.h new file mode 100644 index 0000000..fc8682c --- /dev/null +++ b/lib/crypto_backend/argon2/argon2.h @@ -0,0 +1,437 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ARGON2_H +#define ARGON2_H + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Symbols visibility control */ +#ifdef A2_VISCTL +#define ARGON2_PUBLIC __attribute__((visibility("default"))) +#define ARGON2_LOCAL __attribute__ ((visibility ("hidden"))) +#elif _MSC_VER +#define ARGON2_PUBLIC __declspec(dllexport) +#define ARGON2_LOCAL +#else +#define ARGON2_PUBLIC +#define ARGON2_LOCAL +#endif + +/* + * Argon2 input parameter restrictions + */ + +/* Minimum and maximum number of lanes (degree of parallelism) */ +#define ARGON2_MIN_LANES UINT32_C(1) +#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF) + +/* Minimum and maximum number of threads */ +#define ARGON2_MIN_THREADS UINT32_C(1) +#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF) + +/* Number of synchronization points between lanes per pass */ +#define ARGON2_SYNC_POINTS UINT32_C(4) + +/* Minimum and maximum digest size in bytes */ +#define ARGON2_MIN_OUTLEN UINT32_C(4) +#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */ +#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ + +#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) +/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */ +#define ARGON2_MAX_MEMORY_BITS \ + ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1)) +#define ARGON2_MAX_MEMORY \ + ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS) + +/* Minimum and maximum number of passes */ +#define ARGON2_MIN_TIME UINT32_C(1) +#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum password length in bytes */ +#define ARGON2_MIN_PWD_LENGTH UINT32_C(0) +#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum associated data length in bytes */ +#define ARGON2_MIN_AD_LENGTH UINT32_C(0) +#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum salt length in bytes */ +#define ARGON2_MIN_SALT_LENGTH UINT32_C(8) +#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum key length in bytes */ +#define ARGON2_MIN_SECRET UINT32_C(0) +#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF) + +/* Flags to determine which fields are securely wiped (default = no wipe). */ +#define ARGON2_DEFAULT_FLAGS UINT32_C(0) +#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0) +#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1) + +/* Global flag to determine if we are wiping internal memory buffers. This flag + * is defined in core.c and defaults to 1 (wipe internal memory). */ +extern int FLAG_clear_internal_memory; + +/* Error codes */ +typedef enum Argon2_ErrorCodes { + ARGON2_OK = 0, + + ARGON2_OUTPUT_PTR_NULL = -1, + + ARGON2_OUTPUT_TOO_SHORT = -2, + ARGON2_OUTPUT_TOO_LONG = -3, + + ARGON2_PWD_TOO_SHORT = -4, + ARGON2_PWD_TOO_LONG = -5, + + ARGON2_SALT_TOO_SHORT = -6, + ARGON2_SALT_TOO_LONG = -7, + + ARGON2_AD_TOO_SHORT = -8, + ARGON2_AD_TOO_LONG = -9, + + ARGON2_SECRET_TOO_SHORT = -10, + ARGON2_SECRET_TOO_LONG = -11, + + ARGON2_TIME_TOO_SMALL = -12, + ARGON2_TIME_TOO_LARGE = -13, + + ARGON2_MEMORY_TOO_LITTLE = -14, + ARGON2_MEMORY_TOO_MUCH = -15, + + ARGON2_LANES_TOO_FEW = -16, + ARGON2_LANES_TOO_MANY = -17, + + ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */ + ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */ + ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */ + ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */ + + ARGON2_MEMORY_ALLOCATION_ERROR = -22, + + ARGON2_FREE_MEMORY_CBK_NULL = -23, + ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24, + + ARGON2_INCORRECT_PARAMETER = -25, + ARGON2_INCORRECT_TYPE = -26, + + ARGON2_OUT_PTR_MISMATCH = -27, + + ARGON2_THREADS_TOO_FEW = -28, + ARGON2_THREADS_TOO_MANY = -29, + + ARGON2_MISSING_ARGS = -30, + + ARGON2_ENCODING_FAIL = -31, + + ARGON2_DECODING_FAIL = -32, + + ARGON2_THREAD_FAIL = -33, + + ARGON2_DECODING_LENGTH_FAIL = -34, + + ARGON2_VERIFY_MISMATCH = -35 +} argon2_error_codes; + +/* Memory allocator types --- for external allocation */ +typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate); +typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate); + +/* Argon2 external data structures */ + +/* + ***** + * Context: structure to hold Argon2 inputs: + * output array and its length, + * password and its length, + * salt and its length, + * secret and its length, + * associated data and its length, + * number of passes, amount of used memory (in KBytes, can be rounded up a bit) + * number of parallel threads that will be run. + * All the parameters above affect the output hash value. + * Additionally, two function pointers can be provided to allocate and + * deallocate the memory (if NULL, memory will be allocated internally). + * Also, three flags indicate whether to erase password, secret as soon as they + * are pre-hashed (and thus not needed anymore), and the entire memory + ***** + * Simplest situation: you have output array out[8], password is stored in + * pwd[32], salt is stored in salt[16], you do not have keys nor associated + * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with + * 4 parallel lanes. + * You want to erase the password, but you're OK with last pass not being + * erased. You want to use the default memory allocator. + * Then you initialize: + Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false) + */ +typedef struct Argon2_Context { + uint8_t *out; /* output array */ + uint32_t outlen; /* digest length */ + + uint8_t *pwd; /* password array */ + uint32_t pwdlen; /* password length */ + + uint8_t *salt; /* salt array */ + uint32_t saltlen; /* salt length */ + + uint8_t *secret; /* key array */ + uint32_t secretlen; /* key length */ + + uint8_t *ad; /* associated data array */ + uint32_t adlen; /* associated data length */ + + uint32_t t_cost; /* number of passes */ + uint32_t m_cost; /* amount of memory requested (KB) */ + uint32_t lanes; /* number of lanes */ + uint32_t threads; /* maximum number of threads */ + + uint32_t version; /* version number */ + + allocate_fptr allocate_cbk; /* pointer to memory allocator */ + deallocate_fptr free_cbk; /* pointer to memory deallocator */ + + uint32_t flags; /* array of bool options */ +} argon2_context; + +/* Argon2 primitive type */ +typedef enum Argon2_type { + Argon2_d = 0, + Argon2_i = 1, + Argon2_id = 2 +} argon2_type; + +/* Version of the algorithm */ +typedef enum Argon2_version { + ARGON2_VERSION_10 = 0x10, + ARGON2_VERSION_13 = 0x13, + ARGON2_VERSION_NUMBER = ARGON2_VERSION_13 +} argon2_version; + +/* + * Function that gives the string representation of an argon2_type. + * @param type The argon2_type that we want the string for + * @param uppercase Whether the string should have the first letter uppercase + * @return NULL if invalid type, otherwise the string representation. + */ +ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase); + +/* + * Function that performs memory-hard hashing with certain degree of parallelism + * @param context Pointer to the Argon2 internal structure + * @return Error code if smth is wrong, ARGON2_OK otherwise + */ +ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type); + +/** + * Hashes a password with Argon2i, producing an encoded hash + * @param t_cost Number of iterations + * @param m_cost Sets memory usage to m_cost kibibytes + * @param parallelism Number of threads and compute lanes + * @param pwd Pointer to password + * @param pwdlen Password size in bytes + * @param salt Pointer to salt + * @param saltlen Salt size in bytes + * @param hashlen Desired length of the hash in bytes + * @param encoded Buffer where to write the encoded hash + * @param encodedlen Size of the buffer (thus max size of the encoded hash) + * @pre Different parallelism levels will give different results + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +/** + * Hashes a password with Argon2i, producing a raw hash at @hash + * @param t_cost Number of iterations + * @param m_cost Sets memory usage to m_cost kibibytes + * @param parallelism Number of threads and compute lanes + * @param pwd Pointer to password + * @param pwdlen Password size in bytes + * @param salt Pointer to salt + * @param saltlen Salt size in bytes + * @param hash Buffer where to write the raw hash - updated by the function + * @param hashlen Desired length of the hash in bytes + * @pre Different parallelism levels will give different results + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen, char *encoded, + const size_t encodedlen, argon2_type type, + const uint32_t version); + +/** + * Verifies a password against an encoded string + * Encoded string is restricted as in validate_inputs() + * @param encoded String encoding parameters, salt, hash + * @param pwd Pointer to password + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd, + const size_t pwdlen, argon2_type type); + +/** + * Argon2d: Version of Argon2 that picks memory blocks depending + * on the password and salt. Only for side-channel-free + * environment!! + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2d_ctx(argon2_context *context); + +/** + * Argon2i: Version of Argon2 that picks memory blocks + * independent on the password and salt. Good for side-channels, + * but worse w.r.t. tradeoff attacks if only one pass is used. + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2i_ctx(argon2_context *context); + +/** + * Argon2id: Version of Argon2 where the first half-pass over memory is + * password-independent, the rest are password-dependent (on the password and + * salt). OK against side channels (they reduce to 1/2-pass Argon2i), and + * better with w.r.t. tradeoff attacks (similar to Argon2d). + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2id_ctx(argon2_context *context); + +/** + * Verify if a given password is correct for Argon2d hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash); + +/** + * Verify if a given password is correct for Argon2i hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash); + +/** + * Verify if a given password is correct for Argon2id hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context, + const char *hash); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash, + argon2_type type); + +/** + * Get the associated error message for given error code + * @return The error message associated with the given error code + */ +ARGON2_PUBLIC const char *argon2_error_message(int error_code); + +/** + * Returns the encoded hash length for the given input parameters + * @param t_cost Number of iterations + * @param m_cost Memory usage in kibibytes + * @param parallelism Number of threads; used to compute lanes + * @param saltlen Salt size in bytes + * @param hashlen Hash size in bytes + * @param type The argon2_type that we want the encoded length for + * @return The encoded hash length in bytes + */ +ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, + uint32_t parallelism, uint32_t saltlen, + uint32_t hashlen, argon2_type type); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/lib/crypto_backend/argon2/blake2/blake2-impl.h b/lib/crypto_backend/argon2/blake2/blake2-impl.h new file mode 100644 index 0000000..e77ad92 --- /dev/null +++ b/lib/crypto_backend/argon2/blake2/blake2-impl.h @@ -0,0 +1,154 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef PORTABLE_BLAKE2_IMPL_H +#define PORTABLE_BLAKE2_IMPL_H + +#include +#include + +#if defined(_MSC_VER) +#define BLAKE2_INLINE __inline +#elif defined(__GNUC__) || defined(__clang__) +#define BLAKE2_INLINE __inline__ +#else +#define BLAKE2_INLINE +#endif + +/* Argon2 Team - Begin Code */ +/* + Not an exhaustive list, but should cover the majority of modern platforms + Additionally, the code will always be correct---this is only a performance + tweak. +*/ +#if (defined(__BYTE_ORDER__) && \ + (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \ + defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ + defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \ + defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(_M_ARM) +#define NATIVE_LITTLE_ENDIAN +#endif +/* Argon2 Team - End Code */ + +static BLAKE2_INLINE uint32_t load32(const void *src) { +#if defined(NATIVE_LITTLE_ENDIAN) + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = (const uint8_t *)src; + uint32_t w = *p++; + w |= (uint32_t)(*p++) << 8; + w |= (uint32_t)(*p++) << 16; + w |= (uint32_t)(*p++) << 24; + return w; +#endif +} + +static BLAKE2_INLINE uint64_t load64(const void *src) { +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = (const uint8_t *)src; + uint64_t w = *p++; + w |= (uint64_t)(*p++) << 8; + w |= (uint64_t)(*p++) << 16; + w |= (uint64_t)(*p++) << 24; + w |= (uint64_t)(*p++) << 32; + w |= (uint64_t)(*p++) << 40; + w |= (uint64_t)(*p++) << 48; + w |= (uint64_t)(*p++) << 56; + return w; +#endif +} + +static BLAKE2_INLINE void store32(void *dst, uint32_t w) { +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = (uint8_t *)dst; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; +#endif +} + +static BLAKE2_INLINE void store64(void *dst, uint64_t w) { +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = (uint8_t *)dst; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; +#endif +} + +static BLAKE2_INLINE uint64_t load48(const void *src) { + const uint8_t *p = (const uint8_t *)src; + uint64_t w = *p++; + w |= (uint64_t)(*p++) << 8; + w |= (uint64_t)(*p++) << 16; + w |= (uint64_t)(*p++) << 24; + w |= (uint64_t)(*p++) << 32; + w |= (uint64_t)(*p++) << 40; + return w; +} + +static BLAKE2_INLINE void store48(void *dst, uint64_t w) { + uint8_t *p = (uint8_t *)dst; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; +} + +static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) { + return (w >> c) | (w << (32 - c)); +} + +static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { + return (w >> c) | (w << (64 - c)); +} + +#endif diff --git a/lib/crypto_backend/argon2/blake2/blake2.h b/lib/crypto_backend/argon2/blake2/blake2.h new file mode 100644 index 0000000..9f97e1c --- /dev/null +++ b/lib/crypto_backend/argon2/blake2/blake2.h @@ -0,0 +1,89 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef PORTABLE_BLAKE2_H +#define PORTABLE_BLAKE2_H + +#include "../argon2.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +enum blake2b_constant { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 +}; + +#pragma pack(push, 1) +typedef struct __blake2b_param { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint64_t node_offset; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ +} blake2b_param; +#pragma pack(pop) + +typedef struct __blake2b_state { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + unsigned buflen; + unsigned outlen; + uint8_t last_node; +} blake2b_state; + +/* Ensure param structs have not been wrongly padded */ +/* Poor man's static_assert */ +enum { + blake2_size_check_0 = 1 / !!(CHAR_BIT == 8), + blake2_size_check_2 = + 1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT) +}; + +/* Streaming API */ +ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen); +ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, + size_t keylen); +ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P); +ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, size_t inlen); +ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, size_t outlen); + +/* Simple API */ +ARGON2_LOCAL int blake2b(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen); + +/* Argon2 Team - Begin Code */ +ARGON2_LOCAL int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen); +/* Argon2 Team - End Code */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/lib/crypto_backend/argon2/blake2/blake2b.c b/lib/crypto_backend/argon2/blake2/blake2b.c new file mode 100644 index 0000000..b8651f2 --- /dev/null +++ b/lib/crypto_backend/argon2/blake2/blake2b.c @@ -0,0 +1,392 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include + +#include "blake2.h" +#include "blake2-impl.h" + +void clear_internal_memory(void *v, size_t n); + +static const uint64_t blake2b_IV[8] = { + UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b), + UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1), + UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f), + UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)}; + +static const unsigned int blake2b_sigma[12][16] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, + {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, + {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, + {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, + {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, + {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, + {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, + {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, + {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, +}; + +static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) { + S->f[1] = (uint64_t)-1; +} + +static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) { + if (S->last_node) { + blake2b_set_lastnode(S); + } + S->f[0] = (uint64_t)-1; +} + +static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S, + uint64_t inc) { + S->t[0] += inc; + S->t[1] += (S->t[0] < inc); +} + +static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) { + clear_internal_memory(S, sizeof(*S)); /* wipe */ + blake2b_set_lastblock(S); /* invalidate for further use */ +} + +static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) { + memset(S, 0, sizeof(*S)); + memcpy(S->h, blake2b_IV, sizeof(S->h)); +} + +int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { + const unsigned char *p = (const unsigned char *)P; + unsigned int i; + + if (NULL == P || NULL == S) { + return -1; + } + + blake2b_init0(S); + /* IV XOR Parameter Block */ + for (i = 0; i < 8; ++i) { + S->h[i] ^= load64(&p[i * sizeof(S->h[i])]); + } + S->outlen = P->digest_length; + return 0; +} + +/* Sequential blake2b initialization */ +int blake2b_init(blake2b_state *S, size_t outlen) { + blake2b_param P; + + if (S == NULL) { + return -1; + } + + if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + /* Setup Parameter Block for unkeyed BLAKE2 */ + P.digest_length = (uint8_t)outlen; + P.key_length = 0; + P.fanout = 1; + P.depth = 1; + P.leaf_length = 0; + P.node_offset = 0; + P.node_depth = 0; + P.inner_length = 0; + memset(P.reserved, 0, sizeof(P.reserved)); + memset(P.salt, 0, sizeof(P.salt)); + memset(P.personal, 0, sizeof(P.personal)); + + return blake2b_init_param(S, &P); +} + +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, + size_t keylen) { + blake2b_param P; + + if (S == NULL) { + return -1; + } + + if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) { + blake2b_invalidate_state(S); + return -1; + } + + /* Setup Parameter Block for keyed BLAKE2 */ + P.digest_length = (uint8_t)outlen; + P.key_length = (uint8_t)keylen; + P.fanout = 1; + P.depth = 1; + P.leaf_length = 0; + P.node_offset = 0; + P.node_depth = 0; + P.inner_length = 0; + memset(P.reserved, 0, sizeof(P.reserved)); + memset(P.salt, 0, sizeof(P.salt)); + memset(P.personal, 0, sizeof(P.personal)); + + if (blake2b_init_param(S, &P) < 0) { + blake2b_invalidate_state(S); + return -1; + } + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset(block, 0, BLAKE2B_BLOCKBYTES); + memcpy(block, key, keylen); + blake2b_update(S, block, BLAKE2B_BLOCKBYTES); + /* Burn the key from stack */ + clear_internal_memory(block, BLAKE2B_BLOCKBYTES); + } + return 0; +} + +static void blake2b_compress(blake2b_state *S, const uint8_t *block) { + uint64_t m[16]; + uint64_t v[16]; + unsigned int i, r; + + for (i = 0; i < 16; ++i) { + m[i] = load64(block + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = S->h[i]; + } + + v[8] = blake2b_IV[0]; + v[9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while ((void)0, 0) + +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while ((void)0, 0) + + for (r = 0; r < 12; ++r) { + ROUND(r); + } + + for (i = 0; i < 8; ++i) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } + +#undef G +#undef ROUND +} + +int blake2b_update(blake2b_state *S, const void *in, size_t inlen) { + const uint8_t *pin = (const uint8_t *)in; + + if (inlen == 0) { + return 0; + } + + /* Sanity check */ + if (S == NULL || in == NULL) { + return -1; + } + + /* Is this a reused state? */ + if (S->f[0] != 0) { + return -1; + } + + if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) { + /* Complete current block */ + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + memcpy(&S->buf[left], pin, fill); + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, S->buf); + S->buflen = 0; + inlen -= fill; + pin += fill; + /* Avoid buffer copies when possible */ + while (inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress(S, pin); + inlen -= BLAKE2B_BLOCKBYTES; + pin += BLAKE2B_BLOCKBYTES; + } + } + memcpy(&S->buf[S->buflen], pin, inlen); + S->buflen += (unsigned int)inlen; + return 0; +} + +int blake2b_final(blake2b_state *S, void *out, size_t outlen) { + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + unsigned int i; + + /* Sanity checks */ + if (S == NULL || out == NULL || outlen < S->outlen) { + return -1; + } + + /* Is this a reused state? */ + if (S->f[0] != 0) { + return -1; + } + + blake2b_increment_counter(S, S->buflen); + blake2b_set_lastblock(S); + memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ + blake2b_compress(S, S->buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + store64(buffer + sizeof(S->h[i]) * i, S->h[i]); + } + + memcpy(out, buffer, S->outlen); + clear_internal_memory(buffer, sizeof(buffer)); + clear_internal_memory(S->buf, sizeof(S->buf)); + clear_internal_memory(S->h, sizeof(S->h)); + return 0; +} + +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen) { + blake2b_state S; + int ret = -1; + + /* Verify parameters */ + if (NULL == in && inlen > 0) { + goto fail; + } + + if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) { + goto fail; + } + + if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) { + goto fail; + } + + if (keylen > 0) { + if (blake2b_init_key(&S, outlen, key, keylen) < 0) { + goto fail; + } + } else { + if (blake2b_init(&S, outlen) < 0) { + goto fail; + } + } + + if (blake2b_update(&S, in, inlen) < 0) { + goto fail; + } + ret = blake2b_final(&S, out, outlen); + +fail: + clear_internal_memory(&S, sizeof(S)); + return ret; +} + +/* Argon2 Team - Begin Code */ +int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) { + uint8_t *out = (uint8_t *)pout; + blake2b_state blake_state; + uint8_t outlen_bytes[sizeof(uint32_t)] = {0}; + int ret = -1; + + if (outlen > UINT32_MAX) { + goto fail; + } + + /* Ensure little-endian byte order! */ + store32(outlen_bytes, (uint32_t)outlen); + +#define TRY(statement) \ + do { \ + ret = statement; \ + if (ret < 0) { \ + goto fail; \ + } \ + } while ((void)0, 0) + + if (outlen <= BLAKE2B_OUTBYTES) { + TRY(blake2b_init(&blake_state, outlen)); + TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); + TRY(blake2b_update(&blake_state, in, inlen)); + TRY(blake2b_final(&blake_state, out, outlen)); + } else { + uint32_t toproduce; + uint8_t out_buffer[BLAKE2B_OUTBYTES]; + uint8_t in_buffer[BLAKE2B_OUTBYTES]; + TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES)); + TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes))); + TRY(blake2b_update(&blake_state, in, inlen)); + TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES)); + memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); + out += BLAKE2B_OUTBYTES / 2; + toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2; + + while (toproduce > BLAKE2B_OUTBYTES) { + memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); + TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer, + BLAKE2B_OUTBYTES, NULL, 0)); + memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2); + out += BLAKE2B_OUTBYTES / 2; + toproduce -= BLAKE2B_OUTBYTES / 2; + } + + memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES); + TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL, + 0)); + memcpy(out, out_buffer, toproduce); + } +fail: + clear_internal_memory(&blake_state, sizeof(blake_state)); + return ret; +#undef TRY +} +/* Argon2 Team - End Code */ diff --git a/lib/crypto_backend/argon2/blake2/blamka-round-opt.h b/lib/crypto_backend/argon2/blake2/blamka-round-opt.h new file mode 100644 index 0000000..2c8942e --- /dev/null +++ b/lib/crypto_backend/argon2/blake2/blamka-round-opt.h @@ -0,0 +1,471 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef BLAKE_ROUND_MKA_OPT_H +#define BLAKE_ROUND_MKA_OPT_H + +#include "blake2-impl.h" + +#include +#if defined(__SSSE3__) +#include /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */ +#endif + +#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__)) +#include +#endif + +#if !defined(__AVX512F__) +#if !defined(__AVX2__) +#if !defined(__XOP__) +#if defined(__SSSE3__) +#define r16 \ + (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)) +#define r24 \ + (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)) +#define _mm_roti_epi64(x, c) \ + (-(c) == 32) \ + ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \ + : (-(c) == 24) \ + ? _mm_shuffle_epi8((x), r24) \ + : (-(c) == 16) \ + ? _mm_shuffle_epi8((x), r16) \ + : (-(c) == 63) \ + ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ + _mm_add_epi64((x), (x))) \ + : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \ + _mm_slli_epi64((x), 64 - (-(c)))) +#else /* defined(__SSE2__) */ +#define _mm_roti_epi64(r, c) \ + _mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c)))) +#endif +#else +#endif + +static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) { + const __m128i z = _mm_mul_epu32(x, y); + return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z)); +} + +#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = fBlaMka(A0, B0); \ + A1 = fBlaMka(A1, B1); \ + \ + D0 = _mm_xor_si128(D0, A0); \ + D1 = _mm_xor_si128(D1, A1); \ + \ + D0 = _mm_roti_epi64(D0, -32); \ + D1 = _mm_roti_epi64(D1, -32); \ + \ + C0 = fBlaMka(C0, D0); \ + C1 = fBlaMka(C1, D1); \ + \ + B0 = _mm_xor_si128(B0, C0); \ + B1 = _mm_xor_si128(B1, C1); \ + \ + B0 = _mm_roti_epi64(B0, -24); \ + B1 = _mm_roti_epi64(B1, -24); \ + } while ((void)0, 0) + +#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = fBlaMka(A0, B0); \ + A1 = fBlaMka(A1, B1); \ + \ + D0 = _mm_xor_si128(D0, A0); \ + D1 = _mm_xor_si128(D1, A1); \ + \ + D0 = _mm_roti_epi64(D0, -16); \ + D1 = _mm_roti_epi64(D1, -16); \ + \ + C0 = fBlaMka(C0, D0); \ + C1 = fBlaMka(C1, D1); \ + \ + B0 = _mm_xor_si128(B0, C0); \ + B1 = _mm_xor_si128(B1, C1); \ + \ + B0 = _mm_roti_epi64(B0, -63); \ + B1 = _mm_roti_epi64(B1, -63); \ + } while ((void)0, 0) + +#if defined(__SSSE3__) +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \ + __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \ + B0 = t0; \ + B1 = t1; \ + \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + \ + t0 = _mm_alignr_epi8(D1, D0, 8); \ + t1 = _mm_alignr_epi8(D0, D1, 8); \ + D0 = t1; \ + D1 = t0; \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \ + __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \ + B0 = t0; \ + B1 = t1; \ + \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + \ + t0 = _mm_alignr_epi8(D0, D1, 8); \ + t1 = _mm_alignr_epi8(D1, D0, 8); \ + D0 = t1; \ + D1 = t0; \ + } while ((void)0, 0) +#else /* SSE2 */ +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0 = D0; \ + __m128i t1 = B0; \ + D0 = C0; \ + C0 = C1; \ + C1 = D0; \ + D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \ + D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \ + B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \ + B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + __m128i t0, t1; \ + t0 = C0; \ + C0 = C1; \ + C1 = t0; \ + t0 = B0; \ + t1 = D0; \ + B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \ + B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \ + D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \ + D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \ + } while ((void)0, 0) +#endif + +#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ + \ + UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + } while ((void)0, 0) +#else /* __AVX2__ */ + +#include + +#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1)) +#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)) +#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)) +#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x))) + +#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i ml = _mm256_mul_epu32(A0, B0); \ + ml = _mm256_add_epi64(ml, ml); \ + A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \ + D0 = _mm256_xor_si256(D0, A0); \ + D0 = rotr32(D0); \ + \ + ml = _mm256_mul_epu32(C0, D0); \ + ml = _mm256_add_epi64(ml, ml); \ + C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \ + \ + B0 = _mm256_xor_si256(B0, C0); \ + B0 = rotr24(B0); \ + \ + ml = _mm256_mul_epu32(A1, B1); \ + ml = _mm256_add_epi64(ml, ml); \ + A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \ + D1 = _mm256_xor_si256(D1, A1); \ + D1 = rotr32(D1); \ + \ + ml = _mm256_mul_epu32(C1, D1); \ + ml = _mm256_add_epi64(ml, ml); \ + C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \ + \ + B1 = _mm256_xor_si256(B1, C1); \ + B1 = rotr24(B1); \ + } while((void)0, 0); + +#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i ml = _mm256_mul_epu32(A0, B0); \ + ml = _mm256_add_epi64(ml, ml); \ + A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \ + D0 = _mm256_xor_si256(D0, A0); \ + D0 = rotr16(D0); \ + \ + ml = _mm256_mul_epu32(C0, D0); \ + ml = _mm256_add_epi64(ml, ml); \ + C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \ + B0 = _mm256_xor_si256(B0, C0); \ + B0 = rotr63(B0); \ + \ + ml = _mm256_mul_epu32(A1, B1); \ + ml = _mm256_add_epi64(ml, ml); \ + A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \ + D1 = _mm256_xor_si256(D1, A1); \ + D1 = rotr16(D1); \ + \ + ml = _mm256_mul_epu32(C1, D1); \ + ml = _mm256_add_epi64(ml, ml); \ + C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \ + B1 = _mm256_xor_si256(B1, C1); \ + B1 = rotr63(B1); \ + } while((void)0, 0); + +#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \ + C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \ + \ + B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \ + C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ + D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \ + } while((void)0, 0); + +#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \ + __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \ + B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + \ + tmp1 = C0; \ + C0 = C1; \ + C1 = tmp1; \ + \ + tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \ + tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \ + D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + } while(0); + +#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \ + C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \ + \ + B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \ + C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ + D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \ + } while((void)0, 0); + +#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \ + __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \ + B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + \ + tmp1 = C0; \ + C0 = C1; \ + C1 = tmp1; \ + \ + tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \ + tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \ + D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \ + D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \ + } while((void)0, 0); + +#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \ + do{ \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \ + } while((void)0, 0); + +#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do{ \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \ + \ + UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + } while((void)0, 0); + +#endif /* __AVX2__ */ + +#else /* __AVX512F__ */ + +#include + +#define ror64(x, n) _mm512_ror_epi64((x), (n)) + +static __m512i muladd(__m512i x, __m512i y) +{ + __m512i z = _mm512_mul_epu32(x, y); + return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z)); +} + +#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = muladd(A0, B0); \ + A1 = muladd(A1, B1); \ +\ + D0 = _mm512_xor_si512(D0, A0); \ + D1 = _mm512_xor_si512(D1, A1); \ +\ + D0 = ror64(D0, 32); \ + D1 = ror64(D1, 32); \ +\ + C0 = muladd(C0, D0); \ + C1 = muladd(C1, D1); \ +\ + B0 = _mm512_xor_si512(B0, C0); \ + B1 = _mm512_xor_si512(B1, C1); \ +\ + B0 = ror64(B0, 24); \ + B1 = ror64(B1, 24); \ + } while ((void)0, 0) + +#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + A0 = muladd(A0, B0); \ + A1 = muladd(A1, B1); \ +\ + D0 = _mm512_xor_si512(D0, A0); \ + D1 = _mm512_xor_si512(D1, A1); \ +\ + D0 = ror64(D0, 16); \ + D1 = ror64(D1, 16); \ +\ + C0 = muladd(C0, D0); \ + C1 = muladd(C1, D1); \ +\ + B0 = _mm512_xor_si512(B0, C0); \ + B1 = _mm512_xor_si512(B1, C1); \ +\ + B0 = ror64(B0, 63); \ + B1 = ror64(B1, 63); \ + } while ((void)0, 0) + +#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \ + B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \ +\ + C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ +\ + D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \ + D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \ + } while ((void)0, 0) + +#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \ + B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \ +\ + C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \ + C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \ +\ + D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \ + D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \ + } while ((void)0, 0) + +#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \ + do { \ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + G1(A0, B0, C0, D0, A1, B1, C1, D1); \ + G2(A0, B0, C0, D0, A1, B1, C1, D1); \ +\ + UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \ + } while ((void)0, 0) + +#define SWAP_HALVES(A0, A1) \ + do { \ + __m512i t0, t1; \ + t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \ + t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \ + A0 = t0; \ + A1 = t1; \ + } while((void)0, 0) + +#define SWAP_QUARTERS(A0, A1) \ + do { \ + SWAP_HALVES(A0, A1); \ + A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \ + A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \ + } while((void)0, 0) + +#define UNSWAP_QUARTERS(A0, A1) \ + do { \ + A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \ + A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \ + SWAP_HALVES(A0, A1); \ + } while((void)0, 0) + +#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \ + do { \ + SWAP_HALVES(A0, B0); \ + SWAP_HALVES(C0, D0); \ + SWAP_HALVES(A1, B1); \ + SWAP_HALVES(C1, D1); \ + BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \ + SWAP_HALVES(A0, B0); \ + SWAP_HALVES(C0, D0); \ + SWAP_HALVES(A1, B1); \ + SWAP_HALVES(C1, D1); \ + } while ((void)0, 0) + +#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \ + do { \ + SWAP_QUARTERS(A0, A1); \ + SWAP_QUARTERS(B0, B1); \ + SWAP_QUARTERS(C0, C1); \ + SWAP_QUARTERS(D0, D1); \ + BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \ + UNSWAP_QUARTERS(A0, A1); \ + UNSWAP_QUARTERS(B0, B1); \ + UNSWAP_QUARTERS(C0, C1); \ + UNSWAP_QUARTERS(D0, D1); \ + } while ((void)0, 0) + +#endif /* __AVX512F__ */ +#endif /* BLAKE_ROUND_MKA_OPT_H */ diff --git a/lib/crypto_backend/argon2/blake2/blamka-round-ref.h b/lib/crypto_backend/argon2/blake2/blamka-round-ref.h new file mode 100644 index 0000000..b8f2cf4 --- /dev/null +++ b/lib/crypto_backend/argon2/blake2/blamka-round-ref.h @@ -0,0 +1,56 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef BLAKE_ROUND_MKA_H +#define BLAKE_ROUND_MKA_H + +#include "blake2.h" +#include "blake2-impl.h" + +/* designed by the Lyra PHC team */ +static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) { + const uint64_t m = UINT64_C(0xFFFFFFFF); + const uint64_t xy = (x & m) * (y & m); + return x + y + 2 * xy; +} + +#define G(a, b, c, d) \ + do { \ + a = fBlaMka(a, b); \ + d = rotr64(d ^ a, 32); \ + c = fBlaMka(c, d); \ + b = rotr64(b ^ c, 24); \ + a = fBlaMka(a, b); \ + d = rotr64(d ^ a, 16); \ + c = fBlaMka(c, d); \ + b = rotr64(b ^ c, 63); \ + } while ((void)0, 0) + +#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \ + v12, v13, v14, v15) \ + do { \ + G(v0, v4, v8, v12); \ + G(v1, v5, v9, v13); \ + G(v2, v6, v10, v14); \ + G(v3, v7, v11, v15); \ + G(v0, v5, v10, v15); \ + G(v1, v6, v11, v12); \ + G(v2, v7, v8, v13); \ + G(v3, v4, v9, v14); \ + } while ((void)0, 0) + +#endif diff --git a/lib/crypto_backend/argon2/core.c b/lib/crypto_backend/argon2/core.c new file mode 100644 index 0000000..f5b0067 --- /dev/null +++ b/lib/crypto_backend/argon2/core.c @@ -0,0 +1,641 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +/*For memory wiping*/ +#ifdef _MSC_VER +#include +#include /* For SecureZeroMemory */ +#endif +#if defined __STDC_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 +#endif +#define VC_GE_2005(version) (version >= 1400) + +#include +#include +#include + +#include "core.h" +#include "thread.h" +#include "blake2/blake2.h" +#include "blake2/blake2-impl.h" + +#ifdef GENKAT +#include "genkat.h" +#endif + +#if defined(__clang__) +#if __has_attribute(optnone) +#define NOT_OPTIMIZED __attribute__((optnone)) +#endif +#elif defined(__GNUC__) +#define GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if GCC_VERSION >= 40400 +#define NOT_OPTIMIZED __attribute__((optimize("O0"))) +#endif +#endif +#ifndef NOT_OPTIMIZED +#define NOT_OPTIMIZED +#endif + +/***************Instance and Position constructors**********/ +void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); } + +void copy_block(block *dst, const block *src) { + memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK); +} + +void xor_block(block *dst, const block *src) { + int i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + dst->v[i] ^= src->v[i]; + } +} + +static void load_block(block *dst, const void *input) { + unsigned i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i])); + } +} + +static void store_block(void *output, const block *src) { + unsigned i; + for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) { + store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]); + } +} + +/***************Memory functions*****************/ + +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size) { + size_t memory_size = num*size; + if (memory == NULL) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + /* 1. Check for multiplication overflow */ + if (size != 0 && memory_size / size != num) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + /* 2. Try to allocate with appropriate allocator */ + if (context->allocate_cbk) { + (context->allocate_cbk)(memory, memory_size); + } else { + *memory = malloc(memory_size); + } + + if (*memory == NULL) { + return ARGON2_MEMORY_ALLOCATION_ERROR; + } + + return ARGON2_OK; +} + +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size) { + size_t memory_size = num*size; + clear_internal_memory(memory, memory_size); + if (context->free_cbk) { + (context->free_cbk)(memory, memory_size); + } else { + free(memory); + } +} + +void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) { +#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER) + SecureZeroMemory(v, n); +#elif defined memset_s + memset_s(v, n, 0, n); +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(v, n); +#else + static void *(*const volatile memset_sec)(void *, int, size_t) = &memset; + memset_sec(v, 0, n); +#endif +} + +/* Memory clear flag defaults to true. */ +int FLAG_clear_internal_memory = 1; +void clear_internal_memory(void *v, size_t n) { + if (FLAG_clear_internal_memory && v) { + secure_wipe_memory(v, n); + } +} + +void finalize(const argon2_context *context, argon2_instance_t *instance) { + if (context != NULL && instance != NULL) { + block blockhash; + uint32_t l; + + copy_block(&blockhash, instance->memory + instance->lane_length - 1); + + /* XOR the last blocks */ + for (l = 1; l < instance->lanes; ++l) { + uint32_t last_block_in_lane = + l * instance->lane_length + (instance->lane_length - 1); + xor_block(&blockhash, instance->memory + last_block_in_lane); + } + + /* Hash the result */ + { + uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; + store_block(blockhash_bytes, &blockhash); + blake2b_long(context->out, context->outlen, blockhash_bytes, + ARGON2_BLOCK_SIZE); + /* clear blockhash and blockhash_bytes */ + clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE); + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); + } + +#ifdef GENKAT + print_tag(context->out, context->outlen); +#endif + + free_memory(context, (uint8_t *)instance->memory, + instance->memory_blocks, sizeof(block)); + } +} + +uint32_t index_alpha(const argon2_instance_t *instance, + const argon2_position_t *position, uint32_t pseudo_rand, + int same_lane) { + /* + * Pass 0: + * This lane : all already finished segments plus already constructed + * blocks in this segment + * Other lanes : all already finished segments + * Pass 1+: + * This lane : (SYNC_POINTS - 1) last segments plus already constructed + * blocks in this segment + * Other lanes : (SYNC_POINTS - 1) last segments + */ + uint32_t reference_area_size; + uint64_t relative_position; + uint32_t start_position, absolute_position; + + if (0 == position->pass) { + /* First pass */ + if (0 == position->slice) { + /* First slice */ + reference_area_size = + position->index - 1; /* all but the previous */ + } else { + if (same_lane) { + /* The same lane => add current segment */ + reference_area_size = + position->slice * instance->segment_length + + position->index - 1; + } else { + reference_area_size = + position->slice * instance->segment_length + + ((position->index == 0) ? (-1) : 0); + } + } + } else { + /* Second pass */ + if (same_lane) { + reference_area_size = instance->lane_length - + instance->segment_length + position->index - + 1; + } else { + reference_area_size = instance->lane_length - + instance->segment_length + + ((position->index == 0) ? (-1) : 0); + } + } + + /* 1.2.4. Mapping pseudo_rand to 0.. and produce + * relative position */ + relative_position = pseudo_rand; + relative_position = relative_position * relative_position >> 32; + relative_position = reference_area_size - 1 - + (reference_area_size * relative_position >> 32); + + /* 1.2.5 Computing starting position */ + start_position = 0; + + if (0 != position->pass) { + start_position = (position->slice == ARGON2_SYNC_POINTS - 1) + ? 0 + : (position->slice + 1) * instance->segment_length; + } + + /* 1.2.6. Computing absolute position */ + absolute_position = (start_position + relative_position) % + instance->lane_length; /* absolute position */ + return absolute_position; +} + +/* Single-threaded version for p=1 case */ +static int fill_memory_blocks_st(argon2_instance_t *instance) { + uint32_t r, s, l; + + for (r = 0; r < instance->passes; ++r) { + for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { + for (l = 0; l < instance->lanes; ++l) { + argon2_position_t position = {r, l, (uint8_t)s, 0}; + fill_segment(instance, position); + } + } +#ifdef GENKAT + internal_kat(instance, r); /* Print all memory blocks */ +#endif + } + return ARGON2_OK; +} + +#if !defined(ARGON2_NO_THREADS) + +#ifdef _WIN32 +static unsigned __stdcall fill_segment_thr(void *thread_data) +#else +static void *fill_segment_thr(void *thread_data) +#endif +{ + argon2_thread_data *my_data = thread_data; + fill_segment(my_data->instance_ptr, my_data->pos); + argon2_thread_exit(); + return 0; +} + +/* Multi-threaded version for p > 1 case */ +static int fill_memory_blocks_mt(argon2_instance_t *instance) { + uint32_t r, s; + argon2_thread_handle_t *thread = NULL; + argon2_thread_data *thr_data = NULL; + int rc = ARGON2_OK; + + /* 1. Allocating space for threads */ + thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t)); + if (thread == NULL) { + rc = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + thr_data = calloc(instance->lanes, sizeof(argon2_thread_data)); + if (thr_data == NULL) { + rc = ARGON2_MEMORY_ALLOCATION_ERROR; + goto fail; + } + + for (r = 0; r < instance->passes; ++r) { + for (s = 0; s < ARGON2_SYNC_POINTS; ++s) { + uint32_t l, ll; + + /* 2. Calling threads */ + for (l = 0; l < instance->lanes; ++l) { + argon2_position_t position; + + /* 2.1 Join a thread if limit is exceeded */ + if (l >= instance->threads) { + if (argon2_thread_join(thread[l - instance->threads])) { + rc = ARGON2_THREAD_FAIL; + goto fail; + } + } + + /* 2.2 Create thread */ + position.pass = r; + position.lane = l; + position.slice = (uint8_t)s; + position.index = 0; + thr_data[l].instance_ptr = + instance; /* preparing the thread input */ + memcpy(&(thr_data[l].pos), &position, + sizeof(argon2_position_t)); + if (argon2_thread_create(&thread[l], &fill_segment_thr, + (void *)&thr_data[l])) { + /* Wait for already running threads */ + for (ll = 0; ll < l; ++ll) + argon2_thread_join(thread[ll]); + rc = ARGON2_THREAD_FAIL; + goto fail; + } + + /* fill_segment(instance, position); */ + /*Non-thread equivalent of the lines above */ + } + + /* 3. Joining remaining threads */ + for (l = instance->lanes - instance->threads; l < instance->lanes; + ++l) { + if (argon2_thread_join(thread[l])) { + rc = ARGON2_THREAD_FAIL; + goto fail; + } + } + } + +#ifdef GENKAT + internal_kat(instance, r); /* Print all memory blocks */ +#endif + } + +fail: + if (thread != NULL) { + free(thread); + } + if (thr_data != NULL) { + free(thr_data); + } + return rc; +} + +#endif /* ARGON2_NO_THREADS */ + +int fill_memory_blocks(argon2_instance_t *instance) { + if (instance == NULL || instance->lanes == 0) { + return ARGON2_INCORRECT_PARAMETER; + } +#if defined(ARGON2_NO_THREADS) + return fill_memory_blocks_st(instance); +#else + return instance->threads == 1 ? + fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance); +#endif +} + +int validate_inputs(const argon2_context *context) { + if (NULL == context) { + return ARGON2_INCORRECT_PARAMETER; + } + + if (NULL == context->out) { + return ARGON2_OUTPUT_PTR_NULL; + } + + /* Validate output length */ + if (ARGON2_MIN_OUTLEN > context->outlen) { + return ARGON2_OUTPUT_TOO_SHORT; + } + + if (ARGON2_MAX_OUTLEN < context->outlen) { + return ARGON2_OUTPUT_TOO_LONG; + } + + /* Validate password (required param) */ + if (NULL == context->pwd) { + if (0 != context->pwdlen) { + return ARGON2_PWD_PTR_MISMATCH; + } + } +#if ARGON2_MIN_PWD_LENGTH > 0 /* cryptsetup: fix gcc warning */ + if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) { + return ARGON2_PWD_TOO_SHORT; + } +#endif + if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) { + return ARGON2_PWD_TOO_LONG; + } + + /* Validate salt (required param) */ + if (NULL == context->salt) { + if (0 != context->saltlen) { + return ARGON2_SALT_PTR_MISMATCH; + } + } + + if (ARGON2_MIN_SALT_LENGTH > context->saltlen) { + return ARGON2_SALT_TOO_SHORT; + } + + if (ARGON2_MAX_SALT_LENGTH < context->saltlen) { + return ARGON2_SALT_TOO_LONG; + } + + /* Validate secret (optional param) */ + if (NULL == context->secret) { + if (0 != context->secretlen) { + return ARGON2_SECRET_PTR_MISMATCH; + } + } else { +#if ARGON2_MIN_SECRET > 0 /* cryptsetup: fix gcc warning */ + if (ARGON2_MIN_SECRET > context->secretlen) { + return ARGON2_SECRET_TOO_SHORT; + } +#endif + if (ARGON2_MAX_SECRET < context->secretlen) { + return ARGON2_SECRET_TOO_LONG; + } + } + + /* Validate associated data (optional param) */ + if (NULL == context->ad) { + if (0 != context->adlen) { + return ARGON2_AD_PTR_MISMATCH; + } + } else { +#if ARGON2_MIN_AD_LENGTH > 0 /* cryptsetup: fix gcc warning */ + if (ARGON2_MIN_AD_LENGTH > context->adlen) { + return ARGON2_AD_TOO_SHORT; + } +#endif + if (ARGON2_MAX_AD_LENGTH < context->adlen) { + return ARGON2_AD_TOO_LONG; + } + } + + /* Validate memory cost */ + if (ARGON2_MIN_MEMORY > context->m_cost) { + return ARGON2_MEMORY_TOO_LITTLE; + } +#if 0 /* UINT32_MAX, cryptsetup: fix gcc warning */ + if (ARGON2_MAX_MEMORY < context->m_cost) { + return ARGON2_MEMORY_TOO_MUCH; + } +#endif + if (context->m_cost < 8 * context->lanes) { + return ARGON2_MEMORY_TOO_LITTLE; + } + + /* Validate time cost */ + if (ARGON2_MIN_TIME > context->t_cost) { + return ARGON2_TIME_TOO_SMALL; + } + + if (ARGON2_MAX_TIME < context->t_cost) { + return ARGON2_TIME_TOO_LARGE; + } + + /* Validate lanes */ + if (ARGON2_MIN_LANES > context->lanes) { + return ARGON2_LANES_TOO_FEW; + } + + if (ARGON2_MAX_LANES < context->lanes) { + return ARGON2_LANES_TOO_MANY; + } + + /* Validate threads */ + if (ARGON2_MIN_THREADS > context->threads) { + return ARGON2_THREADS_TOO_FEW; + } + + if (ARGON2_MAX_THREADS < context->threads) { + return ARGON2_THREADS_TOO_MANY; + } + + if (NULL != context->allocate_cbk && NULL == context->free_cbk) { + return ARGON2_FREE_MEMORY_CBK_NULL; + } + + if (NULL == context->allocate_cbk && NULL != context->free_cbk) { + return ARGON2_ALLOCATE_MEMORY_CBK_NULL; + } + + return ARGON2_OK; +} + +void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) { + uint32_t l; + /* Make the first and second block in each lane as G(H0||0||i) or + G(H0||1||i) */ + uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE]; + for (l = 0; l < instance->lanes; ++l) { + + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0); + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l); + blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, + ARGON2_PREHASH_SEED_LENGTH); + load_block(&instance->memory[l * instance->lane_length + 0], + blockhash_bytes); + + store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1); + blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash, + ARGON2_PREHASH_SEED_LENGTH); + load_block(&instance->memory[l * instance->lane_length + 1], + blockhash_bytes); + } + clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); +} + +void initial_hash(uint8_t *blockhash, argon2_context *context, + argon2_type type) { + blake2b_state BlakeHash; + uint8_t value[sizeof(uint32_t)]; + + if (NULL == context || NULL == blockhash) { + return; + } + + blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH); + + store32(&value, context->lanes); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->outlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->m_cost); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->t_cost); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->version); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, (uint32_t)type); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + store32(&value, context->pwdlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->pwd != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->pwd, + context->pwdlen); + + if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) { + secure_wipe_memory(context->pwd, context->pwdlen); + context->pwdlen = 0; + } + } + + store32(&value, context->saltlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->salt != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->salt, + context->saltlen); + } + + store32(&value, context->secretlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->secret != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->secret, + context->secretlen); + + if (context->flags & ARGON2_FLAG_CLEAR_SECRET) { + secure_wipe_memory(context->secret, context->secretlen); + context->secretlen = 0; + } + } + + store32(&value, context->adlen); + blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value)); + + if (context->ad != NULL) { + blake2b_update(&BlakeHash, (const uint8_t *)context->ad, + context->adlen); + } + + blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH); +} + +int initialize(argon2_instance_t *instance, argon2_context *context) { + uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; + int result = ARGON2_OK; + + if (instance == NULL || context == NULL) + return ARGON2_INCORRECT_PARAMETER; + instance->context_ptr = context; + + /* 1. Memory allocation */ + result = allocate_memory(context, (uint8_t **)&(instance->memory), + instance->memory_blocks, sizeof(block)); + if (result != ARGON2_OK) { + return result; + } + + /* 2. Initial hashing */ + /* H_0 + 8 extra bytes to produce the first blocks */ + /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */ + /* Hashing all inputs */ + initial_hash(blockhash, context, instance->type); + /* Zeroing 8 extra bytes */ + clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, + ARGON2_PREHASH_SEED_LENGTH - + ARGON2_PREHASH_DIGEST_LENGTH); + +#ifdef GENKAT + initial_kat(blockhash, context, instance->type); +#endif + + /* 3. Creating first blocks, we always have at least two blocks in a slice + */ + fill_first_blocks(blockhash, instance); + /* Clearing the hash */ + clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH); + + return ARGON2_OK; +} diff --git a/lib/crypto_backend/argon2/core.h b/lib/crypto_backend/argon2/core.h new file mode 100644 index 0000000..78000ba --- /dev/null +++ b/lib/crypto_backend/argon2/core.h @@ -0,0 +1,228 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ARGON2_CORE_H +#define ARGON2_CORE_H + +#include "argon2.h" + +#define CONST_CAST(x) (x)(uintptr_t) + +/**********************Argon2 internal constants*******************************/ + +enum argon2_core_constants { + /* Memory block size in bytes */ + ARGON2_BLOCK_SIZE = 1024, + ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8, + ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16, + ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32, + ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64, + + /* Number of pseudo-random values generated by one call to Blake in Argon2i + to + generate reference block positions */ + ARGON2_ADDRESSES_IN_BLOCK = 128, + + /* Pre-hashing digest length and its extension*/ + ARGON2_PREHASH_DIGEST_LENGTH = 64, + ARGON2_PREHASH_SEED_LENGTH = 72 +}; + +/*************************Argon2 internal data types***********************/ + +/* + * Structure for the (1KB) memory block implemented as 128 64-bit words. + * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no + * bounds checking). + */ +typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block; + +/*****************Functions that work with the block******************/ + +/* Initialize each byte of the block with @in */ +void init_block_value(block *b, uint8_t in); + +/* Copy block @src to block @dst */ +void copy_block(block *dst, const block *src); + +/* XOR @src onto @dst bytewise */ +void xor_block(block *dst, const block *src); + +/* + * Argon2 instance: memory pointer, number of passes, amount of memory, type, + * and derived values. + * Used to evaluate the number and location of blocks to construct in each + * thread + */ +typedef struct Argon2_instance_t { + block *memory; /* Memory pointer */ + uint32_t version; + uint32_t passes; /* Number of passes */ + uint32_t memory_blocks; /* Number of blocks in memory */ + uint32_t segment_length; + uint32_t lane_length; + uint32_t lanes; + uint32_t threads; + argon2_type type; + int print_internals; /* whether to print the memory blocks */ + argon2_context *context_ptr; /* points back to original context */ +} argon2_instance_t; + +/* + * Argon2 position: where we construct the block right now. Used to distribute + * work between threads. + */ +typedef struct Argon2_position_t { + uint32_t pass; + uint32_t lane; + uint8_t slice; + uint32_t index; +} argon2_position_t; + +/*Struct that holds the inputs for thread handling FillSegment*/ +typedef struct Argon2_thread_data { + argon2_instance_t *instance_ptr; + argon2_position_t pos; +} argon2_thread_data; + +/*************************Argon2 core functions********************************/ + +/* Allocates memory to the given pointer, uses the appropriate allocator as + * specified in the context. Total allocated memory is num*size. + * @param context argon2_context which specifies the allocator + * @param memory pointer to the pointer to the memory + * @param size the size in bytes for each element to be allocated + * @param num the number of elements to be allocated + * @return ARGON2_OK if @memory is a valid pointer and memory is allocated + */ +int allocate_memory(const argon2_context *context, uint8_t **memory, + size_t num, size_t size); + +/* + * Frees memory at the given pointer, uses the appropriate deallocator as + * specified in the context. Also cleans the memory using clear_internal_memory. + * @param context argon2_context which specifies the deallocator + * @param memory pointer to buffer to be freed + * @param size the size in bytes for each element to be deallocated + * @param num the number of elements to be deallocated + */ +void free_memory(const argon2_context *context, uint8_t *memory, + size_t num, size_t size); + +/* Function that securely cleans the memory. This ignores any flags set + * regarding clearing memory. Usually one just calls clear_internal_memory. + * @param mem Pointer to the memory + * @param s Memory size in bytes + */ +void secure_wipe_memory(void *v, size_t n); + +/* Function that securely clears the memory if FLAG_clear_internal_memory is + * set. If the flag isn't set, this function does nothing. + * @param mem Pointer to the memory + * @param s Memory size in bytes + */ +void clear_internal_memory(void *v, size_t n); + +/* + * Computes absolute position of reference block in the lane following a skewed + * distribution and using a pseudo-random value as input + * @param instance Pointer to the current instance + * @param position Pointer to the current position + * @param pseudo_rand 32-bit pseudo-random value used to determine the position + * @param same_lane Indicates if the block will be taken from the current lane. + * If so we can reference the current segment + * @pre All pointers must be valid + */ +uint32_t index_alpha(const argon2_instance_t *instance, + const argon2_position_t *position, uint32_t pseudo_rand, + int same_lane); + +/* + * Function that validates all inputs against predefined restrictions and return + * an error code + * @param context Pointer to current Argon2 context + * @return ARGON2_OK if everything is all right, otherwise one of error codes + * (all defined in + */ +int validate_inputs(const argon2_context *context); + +/* + * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears + * password and secret if needed + * @param context Pointer to the Argon2 internal structure containing memory + * pointer, and parameters for time and space requirements. + * @param blockhash Buffer for pre-hashing digest + * @param type Argon2 type + * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes + * allocated + */ +void initial_hash(uint8_t *blockhash, argon2_context *context, + argon2_type type); + +/* + * Function creates first 2 blocks per lane + * @param instance Pointer to the current instance + * @param blockhash Pointer to the pre-hashing digest + * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values + */ +void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance); + +/* + * Function allocates memory, hashes the inputs with Blake, and creates first + * two blocks. Returns the pointer to the main memory with 2 blocks per lane + * initialized + * @param context Pointer to the Argon2 internal structure containing memory + * pointer, and parameters for time and space requirements. + * @param instance Current Argon2 instance + * @return Zero if successful, -1 if memory failed to allocate. @context->state + * will be modified if successful. + */ +int initialize(argon2_instance_t *instance, argon2_context *context); + +/* + * XORing the last block of each lane, hashing it, making the tag. Deallocates + * the memory. + * @param context Pointer to current Argon2 context (use only the out parameters + * from it) + * @param instance Pointer to current instance of Argon2 + * @pre instance->state must point to necessary amount of memory + * @pre context->out must point to outlen bytes of memory + * @pre if context->free_cbk is not NULL, it should point to a function that + * deallocates memory + */ +void finalize(const argon2_context *context, argon2_instance_t *instance); + +/* + * Function that fills the segment using previous segments also from other + * threads + * @param context current context + * @param instance Pointer to the current instance + * @param position Current position + * @pre all block pointers must be valid + */ +void fill_segment(const argon2_instance_t *instance, + argon2_position_t position); + +/* + * Function that fills the entire memory t_cost times based on the first two + * blocks in each lane + * @param instance Pointer to the current instance + * @return ARGON2_OK if successful, @context->state + */ +int fill_memory_blocks(argon2_instance_t *instance); + +#endif diff --git a/lib/crypto_backend/argon2/encoding.c b/lib/crypto_backend/argon2/encoding.c new file mode 100644 index 0000000..9de606e --- /dev/null +++ b/lib/crypto_backend/argon2/encoding.c @@ -0,0 +1,462 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include +#include +#include "encoding.h" +#include "core.h" + +/* + * Example code for a decoder and encoder of "hash strings", with Argon2 + * parameters. + * + * This code comprises three sections: + * + * -- The first section contains generic Base64 encoding and decoding + * functions. It is conceptually applicable to any hash function + * implementation that uses Base64 to encode and decode parameters, + * salts and outputs. It could be made into a library, provided that + * the relevant functions are made public (non-static) and be given + * reasonable names to avoid collisions with other functions. + * + * -- The second section is specific to Argon2. It encodes and decodes + * the parameters, salts and outputs. It does not compute the hash + * itself. + * + * The code was originally written by Thomas Pornin , + * to whom comments and remarks may be sent. It is released under what + * should amount to Public Domain or its closest equivalent; the + * following mantra is supposed to incarnate that fact with all the + * proper legal rituals: + * + * --------------------------------------------------------------------- + * This file is provided under the terms of Creative Commons CC0 1.0 + * Public Domain Dedication. To the extent possible under law, the + * author (Thomas Pornin) has waived all copyright and related or + * neighboring rights to this file. This work is published from: Canada. + * --------------------------------------------------------------------- + * + * Copyright (c) 2015 Thomas Pornin + */ + +/* ==================================================================== */ +/* + * Common code; could be shared between different hash functions. + * + * Note: the Base64 functions below assume that uppercase letters (resp. + * lowercase letters) have consecutive numerical codes, that fit on 8 + * bits. All modern systems use ASCII-compatible charsets, where these + * properties are true. If you are stuck with a dinosaur of a system + * that still defaults to EBCDIC then you already have much bigger + * interoperability issues to deal with. + */ + +/* + * Some macros for constant-time comparisons. These work over values in + * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". + */ +#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) +#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) +#define GE(x, y) (GT(y, x) ^ 0xFF) +#define LT(x, y) GT(y, x) +#define LE(x, y) GE(y, x) + +/* + * Convert value x (0..63) to corresponding Base64 character. + */ +static int b64_byte_to_char(unsigned x) { + return (LT(x, 26) & (x + 'A')) | + (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) | + (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') | + (EQ(x, 63) & '/'); +} + +/* + * Convert character c to the corresponding 6-bit value. If character c + * is not a Base64 character, then 0xFF (255) is returned. + */ +static unsigned b64_char_to_byte(int c) { + unsigned x; + + x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) | + (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) | + (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) | + (EQ(c, '/') & 63); + return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF)); +} + +/* + * Convert some bytes to Base64. 'dst_len' is the length (in characters) + * of the output buffer 'dst'; if that buffer is not large enough to + * receive the result (including the terminating 0), then (size_t)-1 + * is returned. Otherwise, the zero-terminated Base64 string is written + * in the buffer, and the output length (counted WITHOUT the terminating + * zero) is returned. + */ +static size_t to_base64(char *dst, size_t dst_len, const void *src, + size_t src_len) { + size_t olen; + const unsigned char *buf; + unsigned acc, acc_len; + + olen = (src_len / 3) << 2; + switch (src_len % 3) { + case 2: + olen++; + /* fall through */ + case 1: + olen += 2; + break; + } + if (dst_len <= olen) { + return (size_t)-1; + } + acc = 0; + acc_len = 0; + buf = (const unsigned char *)src; + while (src_len-- > 0) { + acc = (acc << 8) + (*buf++); + acc_len += 8; + while (acc_len >= 6) { + acc_len -= 6; + *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F); + } + } + if (acc_len > 0) { + *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F); + } + *dst++ = 0; + return olen; +} + +/* + * Decode Base64 chars into bytes. The '*dst_len' value must initially + * contain the length of the output buffer '*dst'; when the decoding + * ends, the actual number of decoded bytes is written back in + * '*dst_len'. + * + * Decoding stops when a non-Base64 character is encountered, or when + * the output buffer capacity is exceeded. If an error occurred (output + * buffer is too small, invalid last characters leading to unprocessed + * buffered bits), then NULL is returned; otherwise, the returned value + * points to the first non-Base64 character in the source stream, which + * may be the terminating zero. + */ +static const char *from_base64(void *dst, size_t *dst_len, const char *src) { + size_t len; + unsigned char *buf; + unsigned acc, acc_len; + + buf = (unsigned char *)dst; + len = 0; + acc = 0; + acc_len = 0; + for (;;) { + unsigned d; + + d = b64_char_to_byte(*src); + if (d == 0xFF) { + break; + } + src++; + acc = (acc << 6) + d; + acc_len += 6; + if (acc_len >= 8) { + acc_len -= 8; + if ((len++) >= *dst_len) { + return NULL; + } + *buf++ = (acc >> acc_len) & 0xFF; + } + } + + /* + * If the input length is equal to 1 modulo 4 (which is + * invalid), then there will remain 6 unprocessed bits; + * otherwise, only 0, 2 or 4 bits are buffered. The buffered + * bits must also all be zero. + */ + if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) { + return NULL; + } + *dst_len = len; + return src; +} + +/* + * Decode decimal integer from 'str'; the value is written in '*v'. + * Returned value is a pointer to the next non-decimal character in the + * string. If there is no digit at all, or the value encoding is not + * minimal (extra leading zeros), or the value does not fit in an + * 'unsigned long', then NULL is returned. + */ +static const char *decode_decimal(const char *str, unsigned long *v) { + const char *orig; + unsigned long acc; + + acc = 0; + for (orig = str;; str++) { + int c; + + c = *str; + if (c < '0' || c > '9') { + break; + } + c -= '0'; + if (acc > (ULONG_MAX / 10)) { + return NULL; + } + acc *= 10; + if ((unsigned long)c > (ULONG_MAX - acc)) { + return NULL; + } + acc += (unsigned long)c; + } + if (str == orig || (*orig == '0' && str != (orig + 1))) { + return NULL; + } + *v = acc; + return str; +} + +/* ==================================================================== */ +/* + * Code specific to Argon2. + * + * The code below applies the following format: + * + * $argon2[$v=]$m=,t=,p=$$ + * + * where is either 'd', 'id', or 'i', is a decimal integer (positive, + * fits in an 'unsigned long'), and is Base64-encoded data (no '=' padding + * characters, no newline or whitespace). + * + * The last two binary chunks (encoded in Base64) are, in that order, + * the salt and the output. Both are required. The binary salt length and the + * output length must be in the allowed ranges defined in argon2.h. + * + * The ctx struct must contain buffers large enough to hold the salt and pwd + * when it is fed into decode_string. + */ + +int decode_string(argon2_context *ctx, const char *str, argon2_type type) { + +/* check for prefix */ +#define CC(prefix) \ + do { \ + size_t cc_len = strlen(prefix); \ + if (strncmp(str, prefix, cc_len) != 0) { \ + return ARGON2_DECODING_FAIL; \ + } \ + str += cc_len; \ + } while ((void)0, 0) + +/* optional prefix checking with supplied code */ +#define CC_opt(prefix, code) \ + do { \ + size_t cc_len = strlen(prefix); \ + if (strncmp(str, prefix, cc_len) == 0) { \ + str += cc_len; \ + { code; } \ + } \ + } while ((void)0, 0) + +/* Decoding prefix into decimal */ +#define DECIMAL(x) \ + do { \ + unsigned long dec_x; \ + str = decode_decimal(str, &dec_x); \ + if (str == NULL) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (x) = dec_x; \ + } while ((void)0, 0) + + +/* Decoding prefix into uint32_t decimal */ +#define DECIMAL_U32(x) \ + do { \ + unsigned long dec_x; \ + str = decode_decimal(str, &dec_x); \ + if (str == NULL || dec_x > UINT32_MAX) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (x) = (uint32_t)dec_x; \ + } while ((void)0, 0) + + +/* Decoding base64 into a binary buffer */ +#define BIN(buf, max_len, len) \ + do { \ + size_t bin_len = (max_len); \ + str = from_base64(buf, &bin_len, str); \ + if (str == NULL || bin_len > UINT32_MAX) { \ + return ARGON2_DECODING_FAIL; \ + } \ + (len) = (uint32_t)bin_len; \ + } while ((void)0, 0) + + size_t maxsaltlen = ctx->saltlen; + size_t maxoutlen = ctx->outlen; + int validation_result; + const char* type_string; + + /* We should start with the argon2_type we are using */ + type_string = argon2_type2string(type, 0); + if (!type_string) { + return ARGON2_INCORRECT_TYPE; + } + + CC("$"); + CC(type_string); + + /* Reading the version number if the default is suppressed */ + ctx->version = ARGON2_VERSION_10; + CC_opt("$v=", DECIMAL_U32(ctx->version)); + + CC("$m="); + DECIMAL_U32(ctx->m_cost); + CC(",t="); + DECIMAL_U32(ctx->t_cost); + CC(",p="); + DECIMAL_U32(ctx->lanes); + ctx->threads = ctx->lanes; + + CC("$"); + BIN(ctx->salt, maxsaltlen, ctx->saltlen); + CC("$"); + BIN(ctx->out, maxoutlen, ctx->outlen); + + /* The rest of the fields get the default values */ + ctx->secret = NULL; + ctx->secretlen = 0; + ctx->ad = NULL; + ctx->adlen = 0; + ctx->allocate_cbk = NULL; + ctx->free_cbk = NULL; + ctx->flags = ARGON2_DEFAULT_FLAGS; + + /* On return, must have valid context */ + validation_result = validate_inputs(ctx); + if (validation_result != ARGON2_OK) { + return validation_result; + } + + /* Can't have any additional characters */ + if (*str == 0) { + return ARGON2_OK; + } else { + return ARGON2_DECODING_FAIL; + } +#undef CC +#undef CC_opt +#undef DECIMAL +#undef BIN +} + +int encode_string(char *dst, size_t dst_len, argon2_context *ctx, + argon2_type type) { +#define SS(str) \ + do { \ + size_t pp_len = strlen(str); \ + if (pp_len >= dst_len) { \ + return ARGON2_ENCODING_FAIL; \ + } \ + memcpy(dst, str, pp_len + 1); \ + dst += pp_len; \ + dst_len -= pp_len; \ + } while ((void)0, 0) + +#define SX(x) \ + do { \ + char tmp[30]; \ + sprintf(tmp, "%lu", (unsigned long)(x)); \ + SS(tmp); \ + } while ((void)0, 0) + +#define SB(buf, len) \ + do { \ + size_t sb_len = to_base64(dst, dst_len, buf, len); \ + if (sb_len == (size_t)-1) { \ + return ARGON2_ENCODING_FAIL; \ + } \ + dst += sb_len; \ + dst_len -= sb_len; \ + } while ((void)0, 0) + + const char* type_string = argon2_type2string(type, 0); + int validation_result = validate_inputs(ctx); + + if (!type_string) { + return ARGON2_ENCODING_FAIL; + } + + if (validation_result != ARGON2_OK) { + return validation_result; + } + + + SS("$"); + SS(type_string); + + SS("$v="); + SX(ctx->version); + + SS("$m="); + SX(ctx->m_cost); + SS(",t="); + SX(ctx->t_cost); + SS(",p="); + SX(ctx->lanes); + + SS("$"); + SB(ctx->salt, ctx->saltlen); + + SS("$"); + SB(ctx->out, ctx->outlen); + return ARGON2_OK; + +#undef SS +#undef SX +#undef SB +} + +size_t b64len(uint32_t len) { + size_t olen = ((size_t)len / 3) << 2; + + switch (len % 3) { + case 2: + olen++; + /* fall through */ + case 1: + olen += 2; + break; + } + + return olen; +} + +size_t numlen(uint32_t num) { + size_t len = 1; + while (num >= 10) { + ++len; + num = num / 10; + } + return len; +} diff --git a/lib/crypto_backend/argon2/encoding.h b/lib/crypto_backend/argon2/encoding.h new file mode 100644 index 0000000..7e83ec9 --- /dev/null +++ b/lib/crypto_backend/argon2/encoding.h @@ -0,0 +1,57 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ENCODING_H +#define ENCODING_H +#include "argon2.h" + +#define ARGON2_MAX_DECODED_LANES UINT32_C(255) +#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8) +#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12) + +/* +* encode an Argon2 hash string into the provided buffer. 'dst_len' +* contains the size, in characters, of the 'dst' buffer; if 'dst_len' +* is less than the number of required characters (including the +* terminating 0), then this function returns ARGON2_ENCODING_ERROR. +* +* on success, ARGON2_OK is returned. +*/ +int encode_string(char *dst, size_t dst_len, argon2_context *ctx, + argon2_type type); + +/* +* Decodes an Argon2 hash string into the provided structure 'ctx'. +* The only fields that must be set prior to this call are ctx.saltlen and +* ctx.outlen (which must be the maximal salt and out length values that are +* allowed), ctx.salt and ctx.out (which must be buffers of the specified +* length), and ctx.pwd and ctx.pwdlen which must hold a valid password. +* +* Invalid input string causes an error. On success, the ctx is valid and all +* fields have been initialized. +* +* Returned value is ARGON2_OK on success, other ARGON2_ codes on error. +*/ +int decode_string(argon2_context *ctx, const char *str, argon2_type type); + +/* Returns the length of the encoded byte stream with length len */ +size_t b64len(uint32_t len); + +/* Returns the length of the encoded number num */ +size_t numlen(uint32_t num); + +#endif diff --git a/lib/crypto_backend/argon2/opt.c b/lib/crypto_backend/argon2/opt.c new file mode 100644 index 0000000..f6c2052 --- /dev/null +++ b/lib/crypto_backend/argon2/opt.c @@ -0,0 +1,283 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include + +#include "argon2.h" +#include "core.h" + +#include "blake2/blake2.h" +#include "blake2/blamka-round-opt.h" + +/* + * Function fills a new memory block and optionally XORs the old block over the new one. + * Memory must be initialized. + * @param state Pointer to the just produced block. Content will be updated(!) + * @param ref_block Pointer to the reference block + * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block + * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) + * @pre all block pointers must be valid + */ +#if defined(__AVX512F__) +static void fill_block(__m512i *state, const block *ref_block, + block *next_block, int with_xor) { + __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + state[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i)); + block_XY[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm512_xor_si512( + state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i)); + } + } + + for (i = 0; i < 2; ++i) { + BLAKE2_ROUND_1( + state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3], + state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]); + } + + for (i = 0; i < 2; ++i) { + BLAKE2_ROUND_2( + state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i], + state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]); + } + + for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) { + state[i] = _mm512_xor_si512(state[i], block_XY[i]); + _mm512_storeu_si512((__m512i *)next_block->v + i, state[i]); + } +} +#elif defined(__AVX2__) +static void fill_block(__m256i *state, const block *ref_block, + block *next_block, int with_xor) { + __m256i block_XY[ARGON2_HWORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + state[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i)); + block_XY[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm256_xor_si256( + state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i)); + } + } + + for (i = 0; i < 4; ++i) { + BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5], + state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]); + } + + for (i = 0; i < 4; ++i) { + BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i], + state[16 + i], state[20 + i], state[24 + i], state[28 + i]); + } + + for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) { + state[i] = _mm256_xor_si256(state[i], block_XY[i]); + _mm256_storeu_si256((__m256i *)next_block->v + i, state[i]); + } +} +#else +static void fill_block(__m128i *state, const block *ref_block, + block *next_block, int with_xor) { + __m128i block_XY[ARGON2_OWORDS_IN_BLOCK]; + unsigned int i; + + if (with_xor) { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + block_XY[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)next_block->v + i)); + } + } else { + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + block_XY[i] = state[i] = _mm_xor_si128( + state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i)); + } + } + + for (i = 0; i < 8; ++i) { + BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], + state[8 * i + 3], state[8 * i + 4], state[8 * i + 5], + state[8 * i + 6], state[8 * i + 7]); + } + + for (i = 0; i < 8; ++i) { + BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i], + state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i], + state[8 * 6 + i], state[8 * 7 + i]); + } + + for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) { + state[i] = _mm_xor_si128(state[i], block_XY[i]); + _mm_storeu_si128((__m128i *)next_block->v + i, state[i]); + } +} +#endif + +static void next_addresses(block *address_block, block *input_block) { + /*Temporary zero-initialized blocks*/ +#if defined(__AVX512F__) + __m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK]; + __m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK]; +#elif defined(__AVX2__) + __m256i zero_block[ARGON2_HWORDS_IN_BLOCK]; + __m256i zero2_block[ARGON2_HWORDS_IN_BLOCK]; +#else + __m128i zero_block[ARGON2_OWORDS_IN_BLOCK]; + __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK]; +#endif + + memset(zero_block, 0, sizeof(zero_block)); + memset(zero2_block, 0, sizeof(zero2_block)); + + /*Increasing index counter*/ + input_block->v[6]++; + + /*First iteration of G*/ + fill_block(zero_block, input_block, address_block, 0); + + /*Second iteration of G*/ + fill_block(zero2_block, address_block, address_block, 0); +} + +void fill_segment(const argon2_instance_t *instance, + argon2_position_t position) { + block *ref_block = NULL, *curr_block = NULL; + block address_block, input_block; + uint64_t pseudo_rand, ref_index, ref_lane; + uint32_t prev_offset, curr_offset; + uint32_t starting_index, i; +#if defined(__AVX512F__) + __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK]; +#elif defined(__AVX2__) + __m256i state[ARGON2_HWORDS_IN_BLOCK]; +#else + __m128i state[ARGON2_OWORDS_IN_BLOCK]; +#endif + int data_independent_addressing; + + if (instance == NULL) { + return; + } + + data_independent_addressing = + (instance->type == Argon2_i) || + (instance->type == Argon2_id && (position.pass == 0) && + (position.slice < ARGON2_SYNC_POINTS / 2)); + + if (data_independent_addressing) { + init_block_value(&input_block, 0); + + input_block.v[0] = position.pass; + input_block.v[1] = position.lane; + input_block.v[2] = position.slice; + input_block.v[3] = instance->memory_blocks; + input_block.v[4] = instance->passes; + input_block.v[5] = instance->type; + } + + starting_index = 0; + + if ((0 == position.pass) && (0 == position.slice)) { + starting_index = 2; /* we have already generated the first two blocks */ + + /* Don't forget to generate the first block of addresses: */ + if (data_independent_addressing) { + next_addresses(&address_block, &input_block); + } + } + + /* Offset of the current block */ + curr_offset = position.lane * instance->lane_length + + position.slice * instance->segment_length + starting_index; + + if (0 == curr_offset % instance->lane_length) { + /* Last block in this lane */ + prev_offset = curr_offset + instance->lane_length - 1; + } else { + /* Previous block */ + prev_offset = curr_offset - 1; + } + + memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE); + + for (i = starting_index; i < instance->segment_length; + ++i, ++curr_offset, ++prev_offset) { + /*1.1 Rotating prev_offset if needed */ + if (curr_offset % instance->lane_length == 1) { + prev_offset = curr_offset - 1; + } + + /* 1.2 Computing the index of the reference block */ + /* 1.2.1 Taking pseudo-random value from the previous block */ + if (data_independent_addressing) { + if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { + next_addresses(&address_block, &input_block); + } + pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; + } else { + pseudo_rand = instance->memory[prev_offset].v[0]; + } + + /* 1.2.2 Computing the lane of the reference block */ + ref_lane = ((pseudo_rand >> 32)) % instance->lanes; + + if ((position.pass == 0) && (position.slice == 0)) { + /* Can not reference other lanes yet */ + ref_lane = position.lane; + } + + /* 1.2.3 Computing the number of possible reference block within the + * lane. + */ + position.index = i; + ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, + ref_lane == position.lane); + + /* 2 Creating a new block */ + ref_block = + instance->memory + instance->lane_length * ref_lane + ref_index; + curr_block = instance->memory + curr_offset; + if (ARGON2_VERSION_10 == instance->version) { + /* version 1.2.1 and earlier: overwrite, not XOR */ + fill_block(state, ref_block, curr_block, 0); + } else { + if(0 == position.pass) { + fill_block(state, ref_block, curr_block, 0); + } else { + fill_block(state, ref_block, curr_block, 1); + } + } + } +} diff --git a/lib/crypto_backend/argon2/ref.c b/lib/crypto_backend/argon2/ref.c new file mode 100644 index 0000000..ad1cf46 --- /dev/null +++ b/lib/crypto_backend/argon2/ref.c @@ -0,0 +1,194 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#include +#include +#include + +#include "argon2.h" +#include "core.h" + +#include "blake2/blamka-round-ref.h" +#include "blake2/blake2-impl.h" +#include "blake2/blake2.h" + + +/* + * Function fills a new memory block and optionally XORs the old block over the new one. + * @next_block must be initialized. + * @param prev_block Pointer to the previous block + * @param ref_block Pointer to the reference block + * @param next_block Pointer to the block to be constructed + * @param with_xor Whether to XOR into the new block (1) or just overwrite (0) + * @pre all block pointers must be valid + */ +static void fill_block(const block *prev_block, const block *ref_block, + block *next_block, int with_xor) { + block blockR, block_tmp; + unsigned i; + + copy_block(&blockR, ref_block); + xor_block(&blockR, prev_block); + copy_block(&block_tmp, &blockR); + /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */ + if (with_xor) { + /* Saving the next block contents for XOR over: */ + xor_block(&block_tmp, next_block); + /* Now blockR = ref_block + prev_block and + block_tmp = ref_block + prev_block + next_block */ + } + + /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then + (16,17,..31)... finally (112,113,...127) */ + for (i = 0; i < 8; ++i) { + BLAKE2_ROUND_NOMSG( + blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2], + blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5], + blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8], + blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11], + blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14], + blockR.v[16 * i + 15]); + } + + /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then + (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */ + for (i = 0; i < 8; i++) { + BLAKE2_ROUND_NOMSG( + blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16], + blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33], + blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64], + blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81], + blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112], + blockR.v[2 * i + 113]); + } + + copy_block(next_block, &block_tmp); + xor_block(next_block, &blockR); +} + +static void next_addresses(block *address_block, block *input_block, + const block *zero_block) { + input_block->v[6]++; + fill_block(zero_block, input_block, address_block, 0); + fill_block(zero_block, address_block, address_block, 0); +} + +void fill_segment(const argon2_instance_t *instance, + argon2_position_t position) { + block *ref_block = NULL, *curr_block = NULL; + block address_block, input_block, zero_block; + uint64_t pseudo_rand, ref_index, ref_lane; + uint32_t prev_offset, curr_offset; + uint32_t starting_index; + uint32_t i; + int data_independent_addressing; + + if (instance == NULL) { + return; + } + + data_independent_addressing = + (instance->type == Argon2_i) || + (instance->type == Argon2_id && (position.pass == 0) && + (position.slice < ARGON2_SYNC_POINTS / 2)); + + if (data_independent_addressing) { + init_block_value(&zero_block, 0); + init_block_value(&input_block, 0); + + input_block.v[0] = position.pass; + input_block.v[1] = position.lane; + input_block.v[2] = position.slice; + input_block.v[3] = instance->memory_blocks; + input_block.v[4] = instance->passes; + input_block.v[5] = instance->type; + } + + starting_index = 0; + + if ((0 == position.pass) && (0 == position.slice)) { + starting_index = 2; /* we have already generated the first two blocks */ + + /* Don't forget to generate the first block of addresses: */ + if (data_independent_addressing) { + next_addresses(&address_block, &input_block, &zero_block); + } + } + + /* Offset of the current block */ + curr_offset = position.lane * instance->lane_length + + position.slice * instance->segment_length + starting_index; + + if (0 == curr_offset % instance->lane_length) { + /* Last block in this lane */ + prev_offset = curr_offset + instance->lane_length - 1; + } else { + /* Previous block */ + prev_offset = curr_offset - 1; + } + + for (i = starting_index; i < instance->segment_length; + ++i, ++curr_offset, ++prev_offset) { + /*1.1 Rotating prev_offset if needed */ + if (curr_offset % instance->lane_length == 1) { + prev_offset = curr_offset - 1; + } + + /* 1.2 Computing the index of the reference block */ + /* 1.2.1 Taking pseudo-random value from the previous block */ + if (data_independent_addressing) { + if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) { + next_addresses(&address_block, &input_block, &zero_block); + } + pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK]; + } else { + pseudo_rand = instance->memory[prev_offset].v[0]; + } + + /* 1.2.2 Computing the lane of the reference block */ + ref_lane = ((pseudo_rand >> 32)) % instance->lanes; + + if ((position.pass == 0) && (position.slice == 0)) { + /* Can not reference other lanes yet */ + ref_lane = position.lane; + } + + /* 1.2.3 Computing the number of possible reference block within the + * lane. + */ + position.index = i; + ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF, + ref_lane == position.lane); + + /* 2 Creating a new block */ + ref_block = + instance->memory + instance->lane_length * ref_lane + ref_index; + curr_block = instance->memory + curr_offset; + if (ARGON2_VERSION_10 == instance->version) { + /* version 1.2.1 and earlier: overwrite, not XOR */ + fill_block(instance->memory + prev_offset, ref_block, curr_block, 0); + } else { + if(0 == position.pass) { + fill_block(instance->memory + prev_offset, ref_block, + curr_block, 0); + } else { + fill_block(instance->memory + prev_offset, ref_block, + curr_block, 1); + } + } + } +} diff --git a/lib/crypto_backend/argon2/thread.c b/lib/crypto_backend/argon2/thread.c new file mode 100644 index 0000000..e099a00 --- /dev/null +++ b/lib/crypto_backend/argon2/thread.c @@ -0,0 +1,57 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#if !defined(ARGON2_NO_THREADS) + +#include "thread.h" +#if defined(_WIN32) +#include +#endif + +int argon2_thread_create(argon2_thread_handle_t *handle, + argon2_thread_func_t func, void *args) { + if (NULL == handle || func == NULL) { + return -1; + } +#if defined(_WIN32) + *handle = _beginthreadex(NULL, 0, func, args, 0, NULL); + return *handle != 0 ? 0 : -1; +#else + return pthread_create(handle, NULL, func, args); +#endif +} + +int argon2_thread_join(argon2_thread_handle_t handle) { +#if defined(_WIN32) + if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) { + return CloseHandle((HANDLE)handle) != 0 ? 0 : -1; + } + return -1; +#else + return pthread_join(handle, NULL); +#endif +} + +void argon2_thread_exit(void) { +#if defined(_WIN32) + _endthreadex(0); +#else + pthread_exit(NULL); +#endif +} + +#endif /* ARGON2_NO_THREADS */ diff --git a/lib/crypto_backend/argon2/thread.h b/lib/crypto_backend/argon2/thread.h new file mode 100644 index 0000000..49d8836 --- /dev/null +++ b/lib/crypto_backend/argon2/thread.h @@ -0,0 +1,67 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +#ifndef ARGON2_THREAD_H +#define ARGON2_THREAD_H + +#if !defined(ARGON2_NO_THREADS) + +/* + Here we implement an abstraction layer for the simpĺe requirements + of the Argon2 code. We only require 3 primitives---thread creation, + joining, and termination---so full emulation of the pthreads API + is unwarranted. Currently we wrap pthreads and Win32 threads. + + The API defines 2 types: the function pointer type, + argon2_thread_func_t, + and the type of the thread handle---argon2_thread_handle_t. +*/ +#if defined(_WIN32) +#include +typedef unsigned(__stdcall *argon2_thread_func_t)(void *); +typedef uintptr_t argon2_thread_handle_t; +#else +#include +typedef void *(*argon2_thread_func_t)(void *); +typedef pthread_t argon2_thread_handle_t; +#endif + +/* Creates a thread + * @param handle pointer to a thread handle, which is the output of this + * function. Must not be NULL. + * @param func A function pointer for the thread's entry point. Must not be + * NULL. + * @param args Pointer that is passed as an argument to @func. May be NULL. + * @return 0 if @handle and @func are valid pointers and a thread is successfully + * created. + */ +int argon2_thread_create(argon2_thread_handle_t *handle, + argon2_thread_func_t func, void *args); + +/* Waits for a thread to terminate + * @param handle Handle to a thread created with argon2_thread_create. + * @return 0 if @handle is a valid handle, and joining completed successfully. +*/ +int argon2_thread_join(argon2_thread_handle_t handle); + +/* Terminate the current thread. Must be run inside a thread created by + * argon2_thread_create. +*/ +void argon2_thread_exit(void); + +#endif /* ARGON2_NO_THREADS */ +#endif diff --git a/lib/crypto_backend/argon2_generic.c b/lib/crypto_backend/argon2_generic.c new file mode 100644 index 0000000..64cf10b --- /dev/null +++ b/lib/crypto_backend/argon2_generic.c @@ -0,0 +1,79 @@ +/* + * Argon2 PBKDF2 library wrapper + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "crypto_backend_internal.h" +#if HAVE_ARGON2_H +#include +#else +#include "argon2/argon2.h" +#endif + +#define CONST_CAST(x) (x)(uintptr_t) + +int argon2(const char *type, const char *password, size_t password_length, + const char *salt, size_t salt_length, + char *key, size_t key_length, + uint32_t iterations, uint32_t memory, uint32_t parallel) +{ +#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H + return -EINVAL; +#else + argon2_type atype; + argon2_context context = { + .flags = ARGON2_DEFAULT_FLAGS, + .version = ARGON2_VERSION_NUMBER, + .t_cost = (uint32_t)iterations, + .m_cost = (uint32_t)memory, + .lanes = (uint32_t)parallel, + .threads = (uint32_t)parallel, + .out = (uint8_t *)key, + .outlen = (uint32_t)key_length, + .pwd = CONST_CAST(uint8_t *)password, + .pwdlen = (uint32_t)password_length, + .salt = CONST_CAST(uint8_t *)salt, + .saltlen = (uint32_t)salt_length, + }; + int r; + + if (!strcmp(type, "argon2i")) + atype = Argon2_i; + else if(!strcmp(type, "argon2id")) + atype = Argon2_id; + else + return -EINVAL; + + switch (argon2_ctx(&context, atype)) { + case ARGON2_OK: + r = 0; + break; + case ARGON2_MEMORY_ALLOCATION_ERROR: + case ARGON2_FREE_MEMORY_CBK_NULL: + case ARGON2_ALLOCATE_MEMORY_CBK_NULL: + r = -ENOMEM; + break; + default: + r = -EINVAL; + } + + return r; +#endif +} diff --git a/lib/crypto_backend/cipher_check.c b/lib/crypto_backend/cipher_check.c new file mode 100644 index 0000000..2119d97 --- /dev/null +++ b/lib/crypto_backend/cipher_check.c @@ -0,0 +1,161 @@ +/* + * Cipher performance check + * + * Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include "crypto_backend_internal.h" + +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +#endif + +/* + * This is not simulating storage, so using disk block causes extreme overhead. + * Let's use some fixed block size where results are more reliable... + */ +#define CIPHER_BLOCK_BYTES 65536 + +/* + * If the measured value is lower, encrypted buffer is probably too small + * and calculated values are not reliable. + */ +#define CIPHER_TIME_MIN_MS 0.001 + +/* + * The whole test depends on Linux kernel usermode crypto API for now. + * (The same implementations are used in dm-crypt though.) + */ + +static int time_ms(struct timespec *start, struct timespec *end, double *ms) +{ + double start_ms, end_ms; + + start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000); + end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000); + + *ms = end_ms - start_ms; + return 0; +} + +static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size, + const char *key, size_t key_size, const char *iv, size_t iv_size, int enc) +{ + struct crypt_cipher_kernel cipher; + size_t done = 0, block = CIPHER_BLOCK_BYTES; + int r; + + if (buffer_size < block) + block = buffer_size; + + r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size); + if (r < 0) + return r; + + while (done < buffer_size) { + if ((done + block) > buffer_size) + block = buffer_size - done; + + if (enc) + r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done], + block, iv, iv_size); + else + r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done], + block, iv, iv_size); + if (r < 0) + break; + + done += block; + } + + crypt_cipher_destroy_kernel(&cipher); + + return r; +} +static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size, + const char *key, size_t key_size, const char *iv, size_t iv_size, + int encrypt, double *ms) +{ + struct timespec start, end; + int r; + + /* + * Using getrusage would be better here but the precision + * is not adequate, so better stick with CLOCK_MONOTONIC + */ + if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0) + return -EINVAL; + + r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt); + if (r < 0) + return r; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &end) < 0) + return -EINVAL; + + r = time_ms(&start, &end, ms); + if (r < 0) + return r; + + if (*ms < CIPHER_TIME_MIN_MS) + return -ERANGE; + + return 0; +} + +static double speed_mbs(unsigned long bytes, double ms) +{ + double speed = bytes, s = ms / 1000.; + + return speed / (1024 * 1024) / s; +} + +int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size, + const char *key, size_t key_size, const char *iv, size_t iv_size, + double *encryption_mbs, double *decryption_mbs) +{ + double ms_enc, ms_dec, ms; + int r, repeat_enc, repeat_dec; + + ms_enc = 0.0; + repeat_enc = 1; + while (ms_enc < 1000.0) { + r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms); + if (r < 0) + return r; + ms_enc += ms; + repeat_enc++; + } + + ms_dec = 0.0; + repeat_dec = 1; + while (ms_dec < 1000.0) { + r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms); + if (r < 0) + return r; + ms_dec += ms; + repeat_dec++; + } + + *encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc); + *decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec); + + return 0; +} diff --git a/lib/crypto_backend/cipher_generic.c b/lib/crypto_backend/cipher_generic.c new file mode 100644 index 0000000..0ddec59 --- /dev/null +++ b/lib/crypto_backend/cipher_generic.c @@ -0,0 +1,90 @@ +/* + * Linux kernel cipher generic utilities + * + * Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include "crypto_backend.h" + +struct cipher_alg { + const char *name; + const char *mode; + int blocksize; + bool wrapped_key; +}; + +/* FIXME: Getting block size should be dynamic from cipher backend. */ +static const struct cipher_alg cipher_algs[] = { + { "cipher_null", NULL, 16, false }, + { "aes", NULL, 16, false }, + { "serpent", NULL, 16, false }, + { "twofish", NULL, 16, false }, + { "anubis", NULL, 16, false }, + { "blowfish", NULL, 8, false }, + { "camellia", NULL, 16, false }, + { "cast5", NULL, 8, false }, + { "cast6", NULL, 16, false }, + { "des", NULL, 8, false }, + { "des3_ede", NULL, 8, false }, + { "khazad", NULL, 8, false }, + { "seed", NULL, 16, false }, + { "tea", NULL, 8, false }, + { "xtea", NULL, 8, false }, + { "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */ + { "xchacha12,aes", "adiantum", 32, false }, + { "xchacha20,aes", "adiantum", 32, false }, + { "sm4", NULL, 16, false }, + { NULL, NULL, 0, false } +}; + +static const struct cipher_alg *_get_alg(const char *name, const char *mode) +{ + int i = 0; + + while (name && cipher_algs[i].name) { + if (!strcasecmp(name, cipher_algs[i].name)) + if (!mode || !cipher_algs[i].mode || + !strncasecmp(mode, cipher_algs[i].mode, strlen(cipher_algs[i].mode))) + return &cipher_algs[i]; + i++; + } + return NULL; +} + +int crypt_cipher_ivsize(const char *name, const char *mode) +{ + const struct cipher_alg *ca = _get_alg(name, mode); + + if (!ca) + return -EINVAL; + + if (mode && !strcasecmp(mode, "ecb")) + return 0; + + return ca->blocksize; +} + +int crypt_cipher_wrapped_key(const char *name, const char *mode) +{ + const struct cipher_alg *ca = _get_alg(name, mode); + + return ca ? (int)ca->wrapped_key : 0; +} diff --git a/lib/crypto_backend/crc32.c b/lib/crypto_backend/crc32.c index 332f383..9d43623 100644 --- a/lib/crypto_backend/crc32.c +++ b/lib/crypto_backend/crc32.c @@ -19,7 +19,7 @@ * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way, * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit + * sends each low-bit to high-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly. * @@ -42,7 +42,6 @@ #include "crypto_backend.h" - static const uint32_t crc32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, @@ -113,4 +112,3 @@ uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len) return crc; } - diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h index 0aab38c..13fd47c 100644 --- a/lib/crypto_backend/crypto_backend.h +++ b/lib/crypto_backend/crypto_backend.h @@ -1,8 +1,8 @@ /* * crypto backend implementation * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2014, Milan Broz + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,15 +22,17 @@ #define _CRYPTO_BACKEND_H #include +#include +#include #include -struct crypt_device; struct crypt_hash; struct crypt_hmac; struct crypt_cipher; struct crypt_storage; -int crypt_backend_init(struct crypt_device *ctx); +int crypt_backend_init(void); +void crypt_backend_destroy(void); #define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */ @@ -42,71 +44,95 @@ int crypt_hash_size(const char *name); int crypt_hash_init(struct crypt_hash **ctx, const char *name); int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length); int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length); -int crypt_hash_destroy(struct crypt_hash *ctx); +void crypt_hash_destroy(struct crypt_hash *ctx); /* HMAC */ int crypt_hmac_size(const char *name); int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length); + const void *key, size_t key_length); int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length); int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length); -int crypt_hmac_destroy(struct crypt_hmac *ctx); +void crypt_hmac_destroy(struct crypt_hmac *ctx); -/* RNG (if fips paramater set, must provide FIPS compliance) */ +/* RNG (if fips parameter set, must provide FIPS compliance) */ enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 }; int crypt_backend_rng(char *buffer, size_t length, int quality, int fips); + /* PBKDF*/ -int crypt_pbkdf_check(const char *kdf, const char *hash, - const char *password, size_t password_size, - const char *salt, size_t salt_size, - uint64_t *iter_secs); +struct crypt_pbkdf_limits { + uint32_t min_iterations, max_iterations; + uint32_t min_memory, max_memory; + uint32_t min_parallel, max_parallel; +}; + +int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *l); int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, - unsigned int iterations); - -#if USE_INTERNAL_PBKDF2 -/* internal PBKDF2 implementation */ -int pkcs5_pbkdf2(const char *hash, - const char *P, size_t Plen, - const char *S, size_t Slen, - unsigned int c, - unsigned int dkLen, char *DK, - unsigned int hash_block_size); -#endif + uint32_t iterations, uint32_t memory, uint32_t parallel); +int crypt_pbkdf_perf(const char *kdf, const char *hash, + const char *password, size_t password_size, + const char *salt, size_t salt_size, + size_t volume_key_size, uint32_t time_ms, + uint32_t max_memory_kb, uint32_t parallel_threads, + uint32_t *iterations_out, uint32_t *memory_out, + int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr); /* CRC32 */ uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len); -/* ciphers */ -int crypt_cipher_blocksize(const char *name); +/* Block ciphers */ +int crypt_cipher_ivsize(const char *name, const char *mode); +int crypt_cipher_wrapped_key(const char *name, const char *mode); int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, - const char *mode, const void *buffer, size_t length); -int crypt_cipher_destroy(struct crypt_cipher *ctx); + const char *mode, const void *key, size_t key_length); +void crypt_cipher_destroy(struct crypt_cipher *ctx); int crypt_cipher_encrypt(struct crypt_cipher *ctx, const char *in, char *out, size_t length, const char *iv, size_t iv_length); int crypt_cipher_decrypt(struct crypt_cipher *ctx, const char *in, char *out, size_t length, const char *iv, size_t iv_length); +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx); + +/* Benchmark of kernel cipher performance */ +int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size, + const char *key, size_t key_size, const char *iv, size_t iv_size, + double *encryption_mbs, double *decryption_mbs); -/* storage encryption wrappers */ -int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start, +/* Check availability of a cipher (in kernel only) */ +int crypt_cipher_check_kernel(const char *name, const char *mode, + const char *integrity, size_t key_length); + +/* Storage encryption wrappers */ +int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size, const char *cipher, const char *cipher_mode, - char *key, size_t key_length); -int crypt_storage_destroy(struct crypt_storage *ctx); -int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector, - size_t count, char *buffer); -int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector, - size_t count, char *buffer); + const void *key, size_t key_length); +void crypt_storage_destroy(struct crypt_storage *ctx); +int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset, + uint64_t length, char *buffer); +int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset, + uint64_t length, char *buffer); + +bool crypt_storage_kernel_only(struct crypt_storage *ctx); + +/* Temporary Bitlk helper */ +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length); /* Memzero helper (memset on stack can be optimized out) */ static inline void crypt_backend_memzero(void *s, size_t n) { +#ifdef HAVE_EXPLICIT_BZERO + explicit_bzero(s, n); +#else volatile uint8_t *p = (volatile uint8_t *)s; while(n--) *p++ = 0; +#endif } #endif /* _CRYPTO_BACKEND_H */ diff --git a/lib/crypto_backend/crypto_backend_internal.h b/lib/crypto_backend/crypto_backend_internal.h new file mode 100644 index 0000000..6128cd4 --- /dev/null +++ b/lib/crypto_backend/crypto_backend_internal.h @@ -0,0 +1,63 @@ +/* + * crypto backend implementation + * + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef _CRYPTO_BACKEND_INTERNAL_H +#define _CRYPTO_BACKEND_INTERNAL_H + +#include "crypto_backend.h" + +#if USE_INTERNAL_PBKDF2 +/* internal PBKDF2 implementation */ +int pkcs5_pbkdf2(const char *hash, + const char *P, size_t Plen, + const char *S, size_t Slen, + unsigned int c, + unsigned int dkLen, char *DK, + unsigned int hash_block_size); +#endif + +/* Argon2 implementation wrapper */ +int argon2(const char *type, const char *password, size_t password_length, + const char *salt, size_t salt_length, + char *key, size_t key_length, + uint32_t iterations, uint32_t memory, uint32_t parallel); + +/* Block ciphers: fallback to kernel crypto API */ + +struct crypt_cipher_kernel { + int tfmfd; + int opfd; +}; + +int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name, + const char *mode, const void *key, size_t key_length); +int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length); +int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length); +void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx); +int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length); + +#endif /* _CRYPTO_BACKEND_INTERNAL_H */ diff --git a/lib/crypto_backend/crypto_cipher_kernel.c b/lib/crypto_backend/crypto_cipher_kernel.c index f7d2bcf..1a8aecf 100644 --- a/lib/crypto_backend/crypto_cipher_kernel.c +++ b/lib/crypto_backend/crypto_cipher_kernel.c @@ -1,8 +1,8 @@ /* * Linux kernel userspace API crypto backend implementation (skcipher) * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2014, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,11 +22,12 @@ #include #include #include +#include #include #include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" #ifdef ENABLE_AF_ALG @@ -39,125 +40,77 @@ #define SOL_ALG 279 #endif -struct crypt_cipher { - int tfmfd; - int opfd; -}; - -struct cipher_alg { - const char *name; - int blocksize; -}; - -/* FIXME: Getting block size should be dynamic from cipher backend. */ -static struct cipher_alg cipher_algs[] = { - { "cipher_null", 16 }, - { "aes", 16 }, - { "serpent", 16 }, - { "twofish", 16 }, - { "anubis", 16 }, - { "blowfish", 8 }, - { "camellia", 16 }, - { "cast5", 8 }, - { "cast6", 16 }, - { "des", 8 }, - { "des3_ede", 8 }, - { "khazad", 8 }, - { "seed", 16 }, - { "tea", 8 }, - { "xtea", 8 }, - { NULL, 0 } -}; - -static struct cipher_alg *_get_alg(const char *name) -{ - int i = 0; - - while (name && cipher_algs[i].name) { - if (!strcasecmp(name, cipher_algs[i].name)) - return &cipher_algs[i]; - i++; - } - return NULL; -} +#ifndef ALG_SET_AEAD_AUTHSIZE +#define ALG_SET_AEAD_AUTHSIZE 5 +#endif -int crypt_cipher_blocksize(const char *name) +/* + * ciphers + * + * ENOENT - algorithm not available + * ENOTSUP - AF_ALG family not available + * (but cannot check specifically for skcipher API) + */ +static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx, + const void *key, size_t key_length, + size_t tag_length, struct sockaddr_alg *sa) { - struct cipher_alg *ca = _get_alg(name); - - return ca ? ca->blocksize : -EINVAL; -} - -/* Shared with hash kernel backend */ -int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd); + if (!ctx) + return -EINVAL; -int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd) -{ - *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); - if (*tfmfd == -1) + ctx->opfd = -1; + ctx->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (ctx->tfmfd < 0) { + crypt_cipher_destroy_kernel(ctx); return -ENOTSUP; + } - if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) { - close(*tfmfd); - *tfmfd = -1; + if (bind(ctx->tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) { + crypt_cipher_destroy_kernel(ctx); return -ENOENT; } - *opfd = accept(*tfmfd, NULL, 0); - if (*opfd == -1) { - close(*tfmfd); - *tfmfd = -1; + if (setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) { + crypt_cipher_destroy_kernel(ctx); + return -EINVAL; + } + + if (tag_length && setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, tag_length) < 0) { + crypt_cipher_destroy_kernel(ctx); + return -EINVAL; + } + + ctx->opfd = accept(ctx->tfmfd, NULL, 0); + if (ctx->opfd < 0) { + crypt_cipher_destroy_kernel(ctx); return -EINVAL; } return 0; } -/* - *ciphers - * - * ENOENT - algorithm not available - * ENOTSUP - AF_ALG family not available - * (but cannot check specificaly for skcipher API) - */ -int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, - const char *mode, const void *buffer, size_t length) +int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name, + const char *mode, const void *key, size_t key_length) { - struct crypt_cipher *h; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "skcipher", }; - int r; - - h = malloc(sizeof(*h)); - if (!h) - return -ENOMEM; - - snprintf((char *)sa.salg_name, sizeof(sa.salg_name), - "%s(%s)", mode, name); - r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd); - if (r < 0) { - free(h); - return r; - } + if (!strcmp(name, "cipher_null")) + key_length = 0; - if (length && strcmp(name, "cipher_null") && - setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) { - crypt_cipher_destroy(h); - return -EINVAL; - } + snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name); - *ctx = h; - return 0; + return _crypt_cipher_init(ctx, key, key_length, 0, &sa); } /* The in/out should be aligned to page boundary */ -static int crypt_cipher_crypt(struct crypt_cipher *ctx, - const char *in, char *out, size_t length, - const char *iv, size_t iv_length, - uint32_t direction) +static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx, + const char *in, size_t in_length, + char *out, size_t out_length, + const char *iv, size_t iv_length, + uint32_t direction) { int r = 0; ssize_t len; @@ -166,7 +119,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx, uint32_t *type; struct iovec iov = { .iov_base = (void*)(uintptr_t)in, - .iov_len = length, + .iov_len = in_length, }; int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0; char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size]; @@ -177,7 +130,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx, .msg_iovlen = 1, }; - if (!in || !out || !length) + if (!in || !out || !in_length) return -EINVAL; if ((!iv && iv_length) || (iv && !iv_length)) @@ -208,74 +161,183 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx, } len = sendmsg(ctx->opfd, &msg, 0); - if (len != (ssize_t)length) { + if (len != (ssize_t)(in_length)) { r = -EIO; goto bad; } - len = read(ctx->opfd, out, length); - if (len != (ssize_t)length) + len = read(ctx->opfd, out, out_length); + if (len != (ssize_t)out_length) r = -EIO; bad: crypt_backend_memzero(buffer, sizeof(buffer)); return r; } -int crypt_cipher_encrypt(struct crypt_cipher *ctx, - const char *in, char *out, size_t length, - const char *iv, size_t iv_length) +int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) { - return crypt_cipher_crypt(ctx, in, out, length, - iv, iv_length, ALG_OP_ENCRYPT); + return _crypt_cipher_crypt(ctx, in, length, out, length, + iv, iv_length, ALG_OP_ENCRYPT); } -int crypt_cipher_decrypt(struct crypt_cipher *ctx, - const char *in, char *out, size_t length, - const char *iv, size_t iv_length) +int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) { - return crypt_cipher_crypt(ctx, in, out, length, - iv, iv_length, ALG_OP_DECRYPT); + return _crypt_cipher_crypt(ctx, in, length, out, length, + iv, iv_length, ALG_OP_DECRYPT); } -int crypt_cipher_destroy(struct crypt_cipher *ctx) +void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx) { - if (ctx->tfmfd != -1) + if (ctx->tfmfd >= 0) close(ctx->tfmfd); - if (ctx->opfd != -1) + if (ctx->opfd >= 0) close(ctx->opfd); - memset(ctx, 0, sizeof(*ctx)); - free(ctx); - return 0; + + ctx->tfmfd = -1; + ctx->opfd = -1; } -#else /* ENABLE_AF_ALG */ +int crypt_cipher_check_kernel(const char *name, const char *mode, + const char *integrity, size_t key_length) +{ + struct crypt_cipher_kernel c; + char mode_name[64], tmp_salg_name[180], *real_mode = NULL, *cipher_iv = NULL, *key; + const char *salg_type; + bool aead; + int r; + struct sockaddr_alg sa = { + .salg_family = AF_ALG, + }; + + aead = integrity && strcmp(integrity, "none"); + + /* Remove IV if present */ + if (mode) { + strncpy(mode_name, mode, sizeof(mode_name)); + mode_name[sizeof(mode_name) - 1] = 0; + cipher_iv = strchr(mode_name, '-'); + if (cipher_iv) { + *cipher_iv = '\0'; + real_mode = mode_name; + } + } + + salg_type = aead ? "aead" : "skcipher"; + snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type); + memset(tmp_salg_name, 0, sizeof(tmp_salg_name)); + + /* FIXME: this is duplicating a part of devmapper backend */ + if (aead && !strcmp(integrity, "poly1305")) + r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity); + else if (!real_mode) + r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name); + else if (aead && !strcmp(real_mode, "ccm")) + r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name); + else + r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name); + + if (r <= 0 || r > (int)(sizeof(sa.salg_name) - 1)) + return -EINVAL; + + memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name)); + + key = malloc(key_length); + if (!key) + return -ENOMEM; + + /* We cannot use RNG yet, any key works here, tweak the first part if it is split key (XTS). */ + memset(key, 0xab, key_length); + *key = 0xef; -int crypt_cipher_blocksize(const char *name) + r = _crypt_cipher_init(&c, key, key_length, 0, &sa); + crypt_cipher_destroy_kernel(&c); + free(key); + + return r; +} + +int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) { - return -EINVAL; + struct crypt_cipher_kernel c; + struct sockaddr_alg sa = { + .salg_family = AF_ALG, + .salg_type = "aead", + .salg_name = "ccm(aes)", + }; + int r; + char buffer[128], ccm_iv[16]; + + if (length + tag_length > sizeof(buffer)) + return -EINVAL; + + if (iv_length > sizeof(ccm_iv) - 2) + return -EINVAL; + + r = _crypt_cipher_init(&c, key, key_length, tag_length, &sa); + if (r < 0) + return r; + + memcpy(buffer, in, length); + memcpy(buffer + length, tag, tag_length); + + /* CCM IV - RFC3610 */ + memset(ccm_iv, 0, sizeof(ccm_iv)); + ccm_iv[0] = 15 - iv_length - 1; + memcpy(ccm_iv + 1, iv, iv_length); + memset(ccm_iv + 1 + iv_length, 0, ccm_iv[0] + 1); + iv_length = sizeof(ccm_iv); + + r = _crypt_cipher_crypt(&c, buffer, length + tag_length, out, length, + ccm_iv, iv_length, ALG_OP_DECRYPT); + + crypt_cipher_destroy_kernel(&c); + crypt_backend_memzero(buffer, sizeof(buffer)); + + return r; } -int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, - const char *mode, const void *buffer, size_t length) +#else /* ENABLE_AF_ALG */ +int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name, + const char *mode, const void *key, size_t key_length) { return -ENOTSUP; } -int crypt_cipher_destroy(struct crypt_cipher *ctx) +void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx) { - return 0; + return; } -int crypt_cipher_encrypt(struct crypt_cipher *ctx, - const char *in, char *out, size_t length, - const char *iv, size_t iv_length) +int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) { return -EINVAL; } -int crypt_cipher_decrypt(struct crypt_cipher *ctx, - const char *in, char *out, size_t length, - const char *iv, size_t iv_length) +int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) { return -EINVAL; } +int crypt_cipher_check_kernel(const char *name, const char *mode, + const char *integrity, size_t key_length) +{ + /* Cannot check, expect success. */ + return 0; +} +int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ + return -ENOTSUP; +} #endif diff --git a/lib/crypto_backend/crypto_gcrypt.c b/lib/crypto_backend/crypto_gcrypt.c index 9037ad6..f2cf3c6 100644 --- a/lib/crypto_backend/crypto_gcrypt.c +++ b/lib/crypto_backend/crypto_gcrypt.c @@ -1,8 +1,8 @@ /* * GCRYPT crypto backend implementation * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2014, Milan Broz + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" static int crypto_backend_initialised = 0; static int crypto_backend_secmem = 1; @@ -43,6 +43,14 @@ struct crypt_hmac { int hash_len; }; +struct crypt_cipher { + bool use_kernel; + union { + struct crypt_cipher_kernel kernel; + gcry_cipher_hd_t hd; + } u; +}; + /* * Test for wrong Whirlpool variant, * Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html @@ -81,7 +89,7 @@ static void crypt_hash_test_whirlpool_bug(void) crypto_backend_whirlpool_bug = 1; } -int crypt_backend_init(struct crypt_device *ctx) +int crypt_backend_init(void) { if (crypto_backend_initialised) return 0; @@ -121,6 +129,14 @@ int crypt_backend_init(struct crypt_device *ctx) return 0; } +void crypt_backend_destroy(void) +{ + if (crypto_backend_initialised) + gcry_control(GCRYCTL_TERM_SECMEM); + + crypto_backend_initialised = 0; +} + const char *crypt_backend_version(void) { return crypto_backend_initialised ? version : ""; @@ -217,12 +233,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) return 0; } -int crypt_hash_destroy(struct crypt_hash *ctx) +void crypt_hash_destroy(struct crypt_hash *ctx) { gcry_md_close(ctx->hd); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* HMAC */ @@ -232,7 +247,7 @@ int crypt_hmac_size(const char *name) } int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length) + const void *key, size_t key_length) { struct crypt_hmac *h; unsigned int flags = GCRY_MD_FLAG_HMAC; @@ -254,7 +269,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, return -EINVAL; } - if (gcry_md_setkey(h->hd, buffer, length)) { + if (gcry_md_setkey(h->hd, key, key_length)) { gcry_md_close(h->hd); free(h); return -EINVAL; @@ -293,12 +308,11 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) return 0; } -int crypt_hmac_destroy(struct crypt_hmac *ctx) +void crypt_hmac_destroy(struct crypt_hmac *ctx) { gcry_md_close(ctx->hd); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* RNG */ @@ -317,38 +331,191 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips) return 0; } -/* PBKDF */ -int crypt_pbkdf(const char *kdf, const char *hash, - const char *password, size_t password_length, - const char *salt, size_t salt_length, - char *key, size_t key_length, - unsigned int iterations) +static int pbkdf2(const char *hash, + const char *password, size_t password_length, + const char *salt, size_t salt_length, + char *key, size_t key_length, + uint32_t iterations) { const char *hash_name = crypt_hash_compat_name(hash, NULL); #if USE_INTERNAL_PBKDF2 - if (!kdf || strncmp(kdf, "pbkdf2", 6)) - return -EINVAL; - return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length, iterations, key_length, key, 0); - #else /* USE_INTERNAL_PBKDF2 */ int hash_id = gcry_md_map_name(hash_name); - int kdf_id; if (!hash_id) return -EINVAL; - if (kdf && !strncmp(kdf, "pbkdf2", 6)) - kdf_id = GCRY_KDF_PBKDF2; + if (gcry_kdf_derive(password, password_length, GCRY_KDF_PBKDF2, hash_id, + salt, salt_length, iterations, key_length, key)) + return -EINVAL; + + return 0; +#endif /* USE_INTERNAL_PBKDF2 */ +} + +/* PBKDF */ +int crypt_pbkdf(const char *kdf, const char *hash, + const char *password, size_t password_length, + const char *salt, size_t salt_length, + char *key, size_t key_length, + uint32_t iterations, uint32_t memory, uint32_t parallel) +{ + if (!kdf) + return -EINVAL; + + if (!strcmp(kdf, "pbkdf2")) + return pbkdf2(hash, password, password_length, salt, salt_length, + key, key_length, iterations); + else if (!strncmp(kdf, "argon2", 6)) + return argon2(kdf, password, password_length, salt, salt_length, + key, key_length, iterations, memory, parallel); + return -EINVAL; +} + +/* Block ciphers */ +static int _cipher_init(gcry_cipher_hd_t *hd, const char *name, + const char *mode, const void *buffer, size_t length) +{ + int cipher_id, mode_id; + + cipher_id = gcry_cipher_map_name(name); + if (cipher_id == GCRY_CIPHER_MODE_NONE) + return -ENOENT; + + if (!strcmp(mode, "ecb")) + mode_id = GCRY_CIPHER_MODE_ECB; + else if (!strcmp(mode, "cbc")) + mode_id = GCRY_CIPHER_MODE_CBC; +#if HAVE_DECL_GCRY_CIPHER_MODE_XTS + else if (!strcmp(mode, "xts")) + mode_id = GCRY_CIPHER_MODE_XTS; +#endif else + return -ENOENT; + + if (gcry_cipher_open(hd, cipher_id, mode_id, 0)) return -EINVAL; - if (gcry_kdf_derive(password, password_length, kdf_id, hash_id, - salt, salt_length, iterations, key_length, key)) + if (gcry_cipher_setkey(*hd, buffer, length)) { + gcry_cipher_close(*hd); return -EINVAL; + } return 0; -#endif /* USE_INTERNAL_PBKDF2 */ +} + +int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, + const char *mode, const void *key, size_t key_length) +{ + struct crypt_cipher *h; + int r; + + h = malloc(sizeof(*h)); + if (!h) + return -ENOMEM; + + if (!_cipher_init(&h->u.hd, name, mode, key, key_length)) { + h->use_kernel = false; + *ctx = h; + return 0; + } + + r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length); + if (r < 0) { + free(h); + return r; + } + + h->use_kernel = true; + *ctx = h; + return 0; +} + +void crypt_cipher_destroy(struct crypt_cipher *ctx) +{ + if (ctx->use_kernel) + crypt_cipher_destroy_kernel(&ctx->u.kernel); + else + gcry_cipher_close(ctx->u.hd); + free(ctx); +} + +int crypt_cipher_encrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + if (ctx->use_kernel) + return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length); + + if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length)) + return -EINVAL; + + if (gcry_cipher_encrypt(ctx->u.hd, out, length, in, length)) + return -EINVAL; + + return 0; +} + +int crypt_cipher_decrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + if (ctx->use_kernel) + return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length); + + if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length)) + return -EINVAL; + + if (gcry_cipher_decrypt(ctx->u.hd, out, length, in, length)) + return -EINVAL; + + return 0; +} + +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx) +{ + return ctx->use_kernel; +} + +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ +#ifdef GCRY_CCM_BLOCK_LEN + gcry_cipher_hd_t hd; + uint64_t l[3]; + int r = -EINVAL; + + if (gcry_cipher_open(&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CCM, 0)) + return -EINVAL; + + if (gcry_cipher_setkey(hd, key, key_length)) + goto out; + + if (gcry_cipher_setiv(hd, iv, iv_length)) + goto out; + + l[0] = length; + l[1] = 0; + l[2] = tag_length; + if (gcry_cipher_ctl(hd, GCRYCTL_SET_CCM_LENGTHS, l, sizeof(l))) + goto out; + + if (gcry_cipher_decrypt(hd, out, length, in, length)) + goto out; + + if (gcry_cipher_checktag(hd, tag, tag_length)) + goto out; + + r = 0; +out: + gcry_cipher_close(hd); + return r; +#else + return -ENOTSUP; +#endif } diff --git a/lib/crypto_backend/crypto_kernel.c b/lib/crypto_backend/crypto_kernel.c index 874d3a8..bb80d73 100644 --- a/lib/crypto_backend/crypto_kernel.c +++ b/lib/crypto_backend/crypto_kernel.c @@ -1,8 +1,8 @@ /* * Linux kernel userspace API crypto backend implementation * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2014, Milan Broz + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" /* FIXME: remove later */ #ifndef AF_ALG @@ -38,7 +38,7 @@ #endif static int crypto_backend_initialised = 0; -static char version[64]; +static char version[256]; struct hash_alg { const char *name; @@ -48,12 +48,21 @@ struct hash_alg { }; static struct hash_alg hash_algs[] = { - { "sha1", "sha1", 20, 64 }, - { "sha256", "sha256", 32, 64 }, - { "sha512", "sha512", 64, 128 }, - { "ripemd160", "rmd160", 20, 64 }, - { "whirlpool", "wp512", 64, 64 }, - { NULL, NULL, 0, 0 } + { "sha1", "sha1", 20, 64 }, + { "sha224", "sha224", 28, 64 }, + { "sha256", "sha256", 32, 64 }, + { "sha384", "sha384", 48, 128 }, + { "sha512", "sha512", 64, 128 }, + { "ripemd160", "rmd160", 20, 64 }, + { "whirlpool", "wp512", 64, 64 }, + { "sha3-224", "sha3-224", 28, 144 }, + { "sha3-256", "sha3-256", 32, 136 }, + { "sha3-384", "sha3-384", 48, 104 }, + { "sha3-512", "sha3-512", 64, 72 }, + { "stribog256","streebog256", 32, 64 }, + { "stribog512","streebog512", 64, 64 }, + { "sm3", "sm3", 32, 64 }, + { NULL, NULL, 0, 0 } }; struct crypt_hash { @@ -68,16 +77,46 @@ struct crypt_hmac { int hash_len; }; -/* Defined in crypt_kernel_ciphers.c */ -extern int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd); +struct crypt_cipher { + struct crypt_cipher_kernel ck; +}; + +static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd, + const void *key, size_t key_length) +{ + *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (*tfmfd < 0) + return -ENOTSUP; + + if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) { + close(*tfmfd); + *tfmfd = -1; + return -ENOENT; + } + + if (key && setsockopt(*tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) { + close(*tfmfd); + *tfmfd = -1; + return -EINVAL; + } -int crypt_backend_init(struct crypt_device *ctx) + *opfd = accept(*tfmfd, NULL, 0); + if (*opfd < 0) { + close(*tfmfd); + *tfmfd = -1; + return -EINVAL; + } + + return 0; +} + +int crypt_backend_init(void) { struct utsname uts; struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "hash", - .salg_name = "sha1", + .salg_name = "sha256", }; int tfmfd = -1, opfd = -1; @@ -87,7 +126,7 @@ int crypt_backend_init(struct crypt_device *ctx) if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux")) return -EINVAL; - if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd) < 0) + if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0) return -EINVAL; close(tfmfd); @@ -100,6 +139,11 @@ int crypt_backend_init(struct crypt_device *ctx) return 0; } +void crypt_backend_destroy(void) +{ + crypto_backend_initialised = 0; +} + uint32_t crypt_backend_flags(void) { return CRYPT_BACKEND_KERNEL; @@ -150,9 +194,9 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name) } h->hash_len = ha->length; - strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)); + strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)-1); - if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) { + if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) { free(h); return -EINVAL; } @@ -186,15 +230,14 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) return 0; } -int crypt_hash_destroy(struct crypt_hash *ctx) +void crypt_hash_destroy(struct crypt_hash *ctx) { - if (ctx->tfmfd != -1) + if (ctx->tfmfd >= 0) close(ctx->tfmfd); - if (ctx->opfd != -1) + if (ctx->opfd >= 0) close(ctx->opfd); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* HMAC */ @@ -204,7 +247,7 @@ int crypt_hmac_size(const char *name) } int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length) + const void *key, size_t key_length) { struct crypt_hmac *h; struct hash_alg *ha; @@ -227,16 +270,11 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "hmac(%s)", ha->kernel_name); - if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) { + if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) { free(h); return -EINVAL; } - if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) { - crypt_hmac_destroy(h); - return -EINVAL; - } - *ctx = h; return 0; } @@ -266,15 +304,14 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) return 0; } -int crypt_hmac_destroy(struct crypt_hmac *ctx) +void crypt_hmac_destroy(struct crypt_hmac *ctx) { - if (ctx->tfmfd != -1) + if (ctx->tfmfd >= 0) close(ctx->tfmfd); - if (ctx->opfd != -1) + if (ctx->opfd >= 0) close(ctx->opfd); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* RNG - N/A */ @@ -288,13 +325,79 @@ int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, - unsigned int iterations) + uint32_t iterations, uint32_t memory, uint32_t parallel) { - struct hash_alg *ha = _get_alg(hash); + struct hash_alg *ha; - if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6)) + if (!kdf) return -EINVAL; - return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length, - iterations, key_length, key, ha->block_length); + if (!strcmp(kdf, "pbkdf2")) { + ha = _get_alg(hash); + if (!ha) + return -EINVAL; + + return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length, + iterations, key_length, key, ha->block_length); + } else if (!strncmp(kdf, "argon2", 6)) { + return argon2(kdf, password, password_length, salt, salt_length, + key, key_length, iterations, memory, parallel); + } + + return -EINVAL; +} + +/* Block ciphers */ +int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, + const char *mode, const void *key, size_t key_length) +{ + struct crypt_cipher *h; + int r; + + h = malloc(sizeof(*h)); + if (!h) + return -ENOMEM; + + r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length); + if (r < 0) { + free(h); + return r; + } + + *ctx = h; + return 0; +} + +void crypt_cipher_destroy(struct crypt_cipher *ctx) +{ + crypt_cipher_destroy_kernel(&ctx->ck); + free(ctx); +} + +int crypt_cipher_encrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +int crypt_cipher_decrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx) +{ + return true; +} + +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ + return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length, + iv, iv_length, tag, tag_length); } diff --git a/lib/crypto_backend/crypto_nettle.c b/lib/crypto_backend/crypto_nettle.c index cc6617a..c2ec305 100644 --- a/lib/crypto_backend/crypto_nettle.c +++ b/lib/crypto_backend/crypto_nettle.c @@ -1,8 +1,8 @@ /* * Nettle crypto backend implementation * - * Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. - * Copyright (C) 2011-2014, Milan Broz + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,16 +23,24 @@ #include #include #include +#include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" -static char *version = "Nettle"; +#if HAVE_NETTLE_VERSION_H +#include +#define VSTR(s) STR(s) +#define STR(s) #s +static const char *version = "Nettle "VSTR(NETTLE_VERSION_MAJOR)"."VSTR(NETTLE_VERSION_MINOR); +#else +static const char *version = "Nettle"; +#endif typedef void (*init_func) (void *); -typedef void (*update_func) (void *, unsigned, const uint8_t *); -typedef void (*digest_func) (void *, unsigned, uint8_t *); -typedef void (*set_key_func) (void *, unsigned, const uint8_t *); +typedef void (*update_func) (void *, size_t, const uint8_t *); +typedef void (*digest_func) (void *, size_t, uint8_t *); +typedef void (*set_key_func) (void *, size_t, const uint8_t *); struct hash_alg { const char *name; @@ -45,6 +53,24 @@ struct hash_alg { set_key_func hmac_set_key; }; +/* Missing HMAC wrappers in Nettle */ +#define HMAC_FCE(xxx) \ +struct xhmac_##xxx##_ctx HMAC_CTX(struct xxx##_ctx); \ +static void xhmac_##xxx##_set_key(struct xhmac_##xxx##_ctx *ctx, \ +size_t key_length, const uint8_t *key) \ +{HMAC_SET_KEY(ctx, &nettle_##xxx, key_length, key);} \ +static void xhmac_##xxx##_update(struct xhmac_##xxx##_ctx *ctx, \ +size_t length, const uint8_t *data) \ +{xxx##_update(&ctx->state, length, data);} \ +static void xhmac_##xxx##_digest(struct xhmac_##xxx##_ctx *ctx, \ +size_t length, uint8_t *digest) \ +{HMAC_DIGEST(ctx, &nettle_##xxx, length, digest);} + +HMAC_FCE(sha3_224); +HMAC_FCE(sha3_256); +HMAC_FCE(sha3_384); +HMAC_FCE(sha3_512); + static struct hash_alg hash_algs[] = { { "sha1", SHA1_DIGEST_SIZE, (init_func) sha1_init, @@ -94,6 +120,41 @@ static struct hash_alg hash_algs[] = { (digest_func) hmac_ripemd160_digest, (set_key_func) hmac_ripemd160_set_key, }, +/* Nettle prior to version 3.2 has incompatible SHA3 implementation */ +#if NETTLE_SHA3_FIPS202 + { "sha3-224", SHA3_224_DIGEST_SIZE, + (init_func) sha3_224_init, + (update_func) sha3_224_update, + (digest_func) sha3_224_digest, + (update_func) xhmac_sha3_224_update, + (digest_func) xhmac_sha3_224_digest, + (set_key_func) xhmac_sha3_224_set_key, + }, + { "sha3-256", SHA3_256_DIGEST_SIZE, + (init_func) sha3_256_init, + (update_func) sha3_256_update, + (digest_func) sha3_256_digest, + (update_func) xhmac_sha3_256_update, + (digest_func) xhmac_sha3_256_digest, + (set_key_func) xhmac_sha3_256_set_key, + }, + { "sha3-384", SHA3_384_DIGEST_SIZE, + (init_func) sha3_384_init, + (update_func) sha3_384_update, + (digest_func) sha3_384_digest, + (update_func) xhmac_sha3_384_update, + (digest_func) xhmac_sha3_384_digest, + (set_key_func) xhmac_sha3_384_set_key, + }, + { "sha3-512", SHA3_512_DIGEST_SIZE, + (init_func) sha3_512_init, + (update_func) sha3_512_update, + (digest_func) sha3_512_digest, + (update_func) xhmac_sha3_512_update, + (digest_func) xhmac_sha3_512_digest, + (set_key_func) xhmac_sha3_512_set_key, + }, +#endif { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, } }; @@ -105,6 +166,11 @@ struct crypt_hash { struct sha256_ctx sha256; struct sha384_ctx sha384; struct sha512_ctx sha512; + struct ripemd160_ctx ripemd160; + struct sha3_224_ctx sha3_224; + struct sha3_256_ctx sha3_256; + struct sha3_384_ctx sha3_384; + struct sha3_512_ctx sha3_512; } nettle_ctx; }; @@ -116,11 +182,20 @@ struct crypt_hmac { struct hmac_sha256_ctx sha256; struct hmac_sha384_ctx sha384; struct hmac_sha512_ctx sha512; + struct hmac_ripemd160_ctx ripemd160; + struct xhmac_sha3_224_ctx sha3_224; + struct xhmac_sha3_256_ctx sha3_256; + struct xhmac_sha3_384_ctx sha3_384; + struct xhmac_sha3_512_ctx sha3_512; } nettle_ctx; size_t key_length; uint8_t *key; }; +struct crypt_cipher { + struct crypt_cipher_kernel ck; +}; + uint32_t crypt_backend_flags(void) { return 0; @@ -138,11 +213,16 @@ static struct hash_alg *_get_alg(const char *name) return NULL; } -int crypt_backend_init(struct crypt_device *ctx) +int crypt_backend_init(void) { return 0; } +void crypt_backend_destroy(void) +{ + return; +} + const char *crypt_backend_version(void) { return version; @@ -197,11 +277,10 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) return 0; } -int crypt_hash_destroy(struct crypt_hash *ctx) +void crypt_hash_destroy(struct crypt_hash *ctx) { memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* HMAC */ @@ -211,7 +290,7 @@ int crypt_hmac_size(const char *name) } int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length) + const void *key, size_t key_length) { struct crypt_hmac *h; @@ -225,12 +304,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, if (!h->hash) goto bad; - h->key = malloc(length); + h->key = malloc(key_length); if (!h->key) goto bad; - memcpy(h->key, buffer, length); - h->key_length = length; + memcpy(h->key, key, key_length); + h->key_length = key_length; h->hash->init(&h->nettle_ctx); h->hash->hmac_set_key(&h->nettle_ctx, h->key_length, h->key); @@ -263,13 +342,12 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) return 0; } -int crypt_hmac_destroy(struct crypt_hmac *ctx) +void crypt_hmac_destroy(struct crypt_hmac *ctx) { memset(ctx->key, 0, ctx->key_length); free(ctx->key); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* RNG - N/A */ @@ -283,23 +361,84 @@ int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, - unsigned int iterations) + uint32_t iterations, uint32_t memory, uint32_t parallel) { struct crypt_hmac *h; int r; - if (!kdf || strncmp(kdf, "pbkdf2", 6)) + if (!kdf) return -EINVAL; - r = crypt_hmac_init(&h, hash, password, password_length); - if (r < 0) - return r; + if (!strcmp(kdf, "pbkdf2")) { + r = crypt_hmac_init(&h, hash, password, password_length); + if (r < 0) + return r; + + nettle_pbkdf2(&h->nettle_ctx, h->hash->hmac_update, + h->hash->hmac_digest, h->hash->length, iterations, + salt_length, (const uint8_t *)salt, key_length, + (uint8_t *)key); + crypt_hmac_destroy(h); + return 0; + } else if (!strncmp(kdf, "argon2", 6)) { + return argon2(kdf, password, password_length, salt, salt_length, + key, key_length, iterations, memory, parallel); + } + + return -EINVAL; +} + +/* Block ciphers */ +int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, + const char *mode, const void *key, size_t key_length) +{ + struct crypt_cipher *h; + int r; + + h = malloc(sizeof(*h)); + if (!h) + return -ENOMEM; - nettle_pbkdf2(&h->nettle_ctx, h->hash->nettle_hmac_update, - h->hash->nettle_hmac_digest, h->hash->length, iterations, - salt_length, (const uint8_t *)salt, key_length, - (uint8_t *)key); - crypt_hmac_destroy(h); + r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length); + if (r < 0) { + free(h); + return r; + } + *ctx = h; return 0; } + +void crypt_cipher_destroy(struct crypt_cipher *ctx) +{ + crypt_cipher_destroy_kernel(&ctx->ck); + free(ctx); +} + +int crypt_cipher_encrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +int crypt_cipher_decrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx) +{ + return true; +} + +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ + return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length, + iv, iv_length, tag, tag_length); +} diff --git a/lib/crypto_backend/crypto_nss.c b/lib/crypto_backend/crypto_nss.c index 4b9f943..f141432 100644 --- a/lib/crypto_backend/crypto_nss.c +++ b/lib/crypto_backend/crypto_nss.c @@ -1,8 +1,8 @@ /* * NSS crypto backend implementation * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2014, Milan Broz + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,7 @@ #include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" #define CONST_CAST(x) (x)(uintptr_t) @@ -59,6 +59,10 @@ struct crypt_hmac { const struct hash_alg *hash; }; +struct crypt_cipher { + struct crypt_cipher_kernel ck; +}; + static struct hash_alg *_get_alg(const char *name) { int i = 0; @@ -71,7 +75,7 @@ static struct hash_alg *_get_alg(const char *name) return NULL; } -int crypt_backend_init(struct crypt_device *ctx) +int crypt_backend_init(void) { if (crypto_backend_initialised) return 0; @@ -88,6 +92,11 @@ int crypt_backend_init(struct crypt_device *ctx) return 0; } +void crypt_backend_destroy(void) +{ + crypto_backend_initialised = 0; +} + uint32_t crypt_backend_flags(void) { return 0; @@ -175,12 +184,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) return 0; } -int crypt_hash_destroy(struct crypt_hash *ctx) +void crypt_hash_destroy(struct crypt_hash *ctx) { PK11_DestroyContext(ctx->md, PR_TRUE); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* HMAC */ @@ -190,15 +198,15 @@ int crypt_hmac_size(const char *name) } int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length) + const void *key, size_t key_length) { struct crypt_hmac *h; SECItem keyItem; SECItem noParams; keyItem.type = siBuffer; - keyItem.data = CONST_CAST(unsigned char *)buffer; - keyItem.len = (int)length; + keyItem.data = CONST_CAST(unsigned char *)key; + keyItem.len = (int)key_length; noParams.type = siBuffer; noParams.data = 0; @@ -277,7 +285,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) return 0; } -int crypt_hmac_destroy(struct crypt_hmac *ctx) +void crypt_hmac_destroy(struct crypt_hmac *ctx) { if (ctx->key) PK11_FreeSymKey(ctx->key); @@ -287,7 +295,6 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx) PK11_DestroyContext(ctx->md, PR_TRUE); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* RNG */ @@ -307,13 +314,79 @@ int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, - unsigned int iterations) + uint32_t iterations, uint32_t memory, uint32_t parallel) { - struct hash_alg *ha = _get_alg(hash); + struct hash_alg *ha; - if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6)) + if (!kdf) return -EINVAL; - return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length, - iterations, key_length, key, ha->block_length); + if (!strcmp(kdf, "pbkdf2")) { + ha = _get_alg(hash); + if (!ha) + return -EINVAL; + + return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length, + iterations, key_length, key, ha->block_length); + } else if (!strncmp(kdf, "argon2", 6)) { + return argon2(kdf, password, password_length, salt, salt_length, + key, key_length, iterations, memory, parallel); + } + + return -EINVAL; +} + +/* Block ciphers */ +int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, + const char *mode, const void *key, size_t key_length) +{ + struct crypt_cipher *h; + int r; + + h = malloc(sizeof(*h)); + if (!h) + return -ENOMEM; + + r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length); + if (r < 0) { + free(h); + return r; + } + + *ctx = h; + return 0; +} + +void crypt_cipher_destroy(struct crypt_cipher *ctx) +{ + crypt_cipher_destroy_kernel(&ctx->ck); + free(ctx); +} + +int crypt_cipher_encrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +int crypt_cipher_decrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length); +} + +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx) +{ + return true; +} + +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ + return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length, + iv, iv_length, tag, tag_length); } diff --git a/lib/crypto_backend/crypto_openssl.c b/lib/crypto_backend/crypto_openssl.c index 5e4345b..2edec7b 100644 --- a/lib/crypto_backend/crypto_openssl.c +++ b/lib/crypto_backend/crypto_openssl.c @@ -1,8 +1,8 @@ /* * OPENSSL crypto backend implementation * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2010-2014, Milan Broz + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,33 +33,110 @@ #include #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" + +#define CONST_CAST(x) (x)(uintptr_t) static int crypto_backend_initialised = 0; struct crypt_hash { - EVP_MD_CTX md; + EVP_MD_CTX *md; const EVP_MD *hash_id; int hash_len; }; struct crypt_hmac { - HMAC_CTX md; + HMAC_CTX *md; const EVP_MD *hash_id; int hash_len; }; -int crypt_backend_init(struct crypt_device *ctx) +struct crypt_cipher { + bool use_kernel; + union { + struct crypt_cipher_kernel kernel; + struct { + EVP_CIPHER_CTX *hd_enc; + EVP_CIPHER_CTX *hd_dec; + size_t iv_length; + } lib; + } u; +}; + +/* + * Compatible wrappers for OpenSSL < 1.1.0 and LibreSSL < 2.7.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) + +static void openssl_backend_init(void) +{ + OpenSSL_add_all_algorithms(); +} + +static const char *openssl_backend_version(void) +{ + return SSLeay_version(SSLEAY_VERSION); +} + +static EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *md = malloc(sizeof(*md)); + + if (md) + EVP_MD_CTX_init(md); + + return md; +} + +static void EVP_MD_CTX_free(EVP_MD_CTX *md) +{ + EVP_MD_CTX_cleanup(md); + free(md); +} + +static HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *md = malloc(sizeof(*md)); + + if (md) + HMAC_CTX_init(md); + + return md; +} + +static void HMAC_CTX_free(HMAC_CTX *md) +{ + HMAC_CTX_cleanup(md); + free(md); +} +#else +static void openssl_backend_init(void) +{ +} + +static const char *openssl_backend_version(void) +{ + return OpenSSL_version(OPENSSL_VERSION); +} +#endif + +int crypt_backend_init(void) { if (crypto_backend_initialised) return 0; - OpenSSL_add_all_algorithms(); + openssl_backend_init(); crypto_backend_initialised = 1; return 0; } +void crypt_backend_destroy(void) +{ + crypto_backend_initialised = 0; +} + uint32_t crypt_backend_flags(void) { return 0; @@ -67,7 +144,7 @@ uint32_t crypt_backend_flags(void) const char *crypt_backend_version(void) { - return SSLeay_version(SSLEAY_VERSION); + return openssl_backend_version(); } /* HASH */ @@ -89,13 +166,21 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name) if (!h) return -ENOMEM; + h->md = EVP_MD_CTX_new(); + if (!h->md) { + free(h); + return -ENOMEM; + } + h->hash_id = EVP_get_digestbyname(name); if (!h->hash_id) { + EVP_MD_CTX_free(h->md); free(h); return -EINVAL; } - if (EVP_DigestInit(&h->md, h->hash_id) != 1) { + if (EVP_DigestInit_ex(h->md, h->hash_id, NULL) != 1) { + EVP_MD_CTX_free(h->md); free(h); return -EINVAL; } @@ -107,7 +192,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name) static int crypt_hash_restart(struct crypt_hash *ctx) { - if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1) + if (EVP_DigestInit_ex(ctx->md, ctx->hash_id, NULL) != 1) return -EINVAL; return 0; @@ -115,7 +200,7 @@ static int crypt_hash_restart(struct crypt_hash *ctx) int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length) { - if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1) + if (EVP_DigestUpdate(ctx->md, buffer, length) != 1) return -EINVAL; return 0; @@ -129,7 +214,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) if (length > (size_t)ctx->hash_len) return -EINVAL; - if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1) + if (EVP_DigestFinal_ex(ctx->md, tmp, &tmp_len) != 1) return -EINVAL; memcpy(buffer, tmp, length); @@ -144,12 +229,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length) return 0; } -int crypt_hash_destroy(struct crypt_hash *ctx) +void crypt_hash_destroy(struct crypt_hash *ctx) { - EVP_MD_CTX_cleanup(&ctx->md); + EVP_MD_CTX_free(ctx->md); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* HMAC */ @@ -159,7 +243,7 @@ int crypt_hmac_size(const char *name) } int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, - const void *buffer, size_t length) + const void *key, size_t key_length) { struct crypt_hmac *h; @@ -167,14 +251,20 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, if (!h) return -ENOMEM; + h->md = HMAC_CTX_new(); + if (!h->md) { + free(h); + return -ENOMEM; + } + h->hash_id = EVP_get_digestbyname(name); if (!h->hash_id) { + HMAC_CTX_free(h->md); free(h); return -EINVAL; } - HMAC_CTX_init(&h->md); - HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL); + HMAC_Init_ex(h->md, key, key_length, h->hash_id, NULL); h->hash_len = EVP_MD_size(h->hash_id); *ctx = h; @@ -183,12 +273,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, static void crypt_hmac_restart(struct crypt_hmac *ctx) { - HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL); + HMAC_Init_ex(ctx->md, NULL, 0, ctx->hash_id, NULL); } int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length) { - HMAC_Update(&ctx->md, (const unsigned char *)buffer, length); + HMAC_Update(ctx->md, (const unsigned char *)buffer, length); return 0; } @@ -200,7 +290,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) if (length > (size_t)ctx->hash_len) return -EINVAL; - HMAC_Final(&ctx->md, tmp, &tmp_len); + HMAC_Final(ctx->md, tmp, &tmp_len); memcpy(buffer, tmp, length); crypt_backend_memzero(tmp, sizeof(tmp)); @@ -213,20 +303,16 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length) return 0; } -int crypt_hmac_destroy(struct crypt_hmac *ctx) +void crypt_hmac_destroy(struct crypt_hmac *ctx) { - HMAC_CTX_cleanup(&ctx->md); + HMAC_CTX_free(ctx->md); memset(ctx, 0, sizeof(*ctx)); free(ctx); - return 0; } /* RNG */ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips) { - if (fips) - return -EINVAL; - if (RAND_bytes((unsigned char *)buffer, length) != 1) return -EINVAL; @@ -238,21 +324,223 @@ int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, - unsigned int iterations) + uint32_t iterations, uint32_t memory, uint32_t parallel) + { const EVP_MD *hash_id; - if (!kdf || strncmp(kdf, "pbkdf2", 6)) + if (!kdf) return -EINVAL; - hash_id = EVP_get_digestbyname(hash); - if (!hash_id) + if (!strcmp(kdf, "pbkdf2")) { + hash_id = EVP_get_digestbyname(hash); + if (!hash_id) + return -EINVAL; + + if (!PKCS5_PBKDF2_HMAC(password, (int)password_length, + (const unsigned char *)salt, (int)salt_length, + (int)iterations, hash_id, (int)key_length, (unsigned char *)key)) + return -EINVAL; + return 0; + } else if (!strncmp(kdf, "argon2", 6)) { + return argon2(kdf, password, password_length, salt, salt_length, + key, key_length, iterations, memory, parallel); + } + + return -EINVAL; +} + +/* Block ciphers */ +static void _cipher_destroy(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec) +{ + EVP_CIPHER_CTX_free(*hd_enc); + *hd_enc = NULL; + + EVP_CIPHER_CTX_free(*hd_dec); + *hd_dec = NULL; +} + +static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const char *name, + const char *mode, const void *key, size_t key_length, size_t *iv_length) +{ + char cipher_name[256]; + const EVP_CIPHER *type; + int r, key_bits; + + key_bits = key_length * 8; + if (!strcmp(mode, "xts")) + key_bits /= 2; + + r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode); + if (r < 0 || r >= (int)sizeof(cipher_name)) + return -EINVAL; + + type = EVP_get_cipherbyname(cipher_name); + if (!type) + return -ENOENT; + + if (EVP_CIPHER_key_length(type) != (int)key_length) + return -EINVAL; + + *hd_enc = EVP_CIPHER_CTX_new(); + *hd_dec = EVP_CIPHER_CTX_new(); + *iv_length = EVP_CIPHER_iv_length(type); + + if (!*hd_enc || !*hd_dec) + return -EINVAL; + + if (EVP_EncryptInit_ex(*hd_enc, type, NULL, key, NULL) != 1 || + EVP_DecryptInit_ex(*hd_dec, type, NULL, key, NULL) != 1) { + _cipher_destroy(hd_enc, hd_dec); + return -EINVAL; + } + + if (EVP_CIPHER_CTX_set_padding(*hd_enc, 0) != 1 || + EVP_CIPHER_CTX_set_padding(*hd_dec, 0) != 1) { + _cipher_destroy(hd_enc, hd_dec); + return -EINVAL; + } + + return 0; +} + +int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, + const char *mode, const void *key, size_t key_length) +{ + struct crypt_cipher *h; + int r; + + h = malloc(sizeof(*h)); + if (!h) + return -ENOMEM; + + if (!_cipher_init(&h->u.lib.hd_enc, &h->u.lib.hd_dec, name, mode, key, + key_length, &h->u.lib.iv_length)) { + h->use_kernel = false; + *ctx = h; + return 0; + } + + r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length); + if (r < 0) { + free(h); + return r; + } + + h->use_kernel = true; + *ctx = h; + return 0; +} + +void crypt_cipher_destroy(struct crypt_cipher *ctx) +{ + if (ctx->use_kernel) + crypt_cipher_destroy_kernel(&ctx->u.kernel); + else + _cipher_destroy(&ctx->u.lib.hd_enc, &ctx->u.lib.hd_dec); + free(ctx); +} + +static int _cipher_encrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out, + int length, const unsigned char *iv, size_t iv_length) +{ + int len; + + if (ctx->u.lib.iv_length != iv_length) + return -EINVAL; + + if (EVP_EncryptInit_ex(ctx->u.lib.hd_enc, NULL, NULL, NULL, iv) != 1) return -EINVAL; - if (!PKCS5_PBKDF2_HMAC(password, (int)password_length, - (unsigned char *)salt, (int)salt_length, - (int)iterations, hash_id, (int)key_length, (unsigned char *)key)) + if (EVP_EncryptUpdate(ctx->u.lib.hd_enc, out, &len, in, length) != 1) + return -EINVAL; + + if (EVP_EncryptFinal(ctx->u.lib.hd_enc, out + len, &len) != 1) + return -EINVAL; + + return 0; +} + +static int _cipher_decrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out, + int length, const unsigned char *iv, size_t iv_length) +{ + int len; + + if (ctx->u.lib.iv_length != iv_length) + return -EINVAL; + + if (EVP_DecryptInit_ex(ctx->u.lib.hd_dec, NULL, NULL, NULL, iv) != 1) + return -EINVAL; + + if (EVP_DecryptUpdate(ctx->u.lib.hd_dec, out, &len, in, length) != 1) + return -EINVAL; + + if (EVP_DecryptFinal(ctx->u.lib.hd_dec, out + len, &len) != 1) return -EINVAL; return 0; } + +int crypt_cipher_encrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + if (ctx->use_kernel) + return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length); + + return _cipher_encrypt(ctx, (const unsigned char*)in, + (unsigned char *)out, length, (const unsigned char*)iv, iv_length); +} + +int crypt_cipher_decrypt(struct crypt_cipher *ctx, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length) +{ + if (ctx->use_kernel) + return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length); + + return _cipher_decrypt(ctx, (const unsigned char*)in, + (unsigned char *)out, length, (const unsigned char*)iv, iv_length); +} + +bool crypt_cipher_kernel_only(struct crypt_cipher *ctx) +{ + return ctx->use_kernel; +} + +int crypt_bitlk_decrypt_key(const void *key, size_t key_length, + const char *in, char *out, size_t length, + const char *iv, size_t iv_length, + const char *tag, size_t tag_length) +{ +#ifdef EVP_CTRL_CCM_SET_IVLEN + EVP_CIPHER_CTX *ctx; + int len = 0, r = -EINVAL; + + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return -EINVAL; + + if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1) + goto out; + + //EVP_CIPHER_CTX_key_length(ctx) + //EVP_CIPHER_CTX_iv_length(ctx) + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_length, NULL) != 1) + goto out; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_length, CONST_CAST(void*)tag) != 1) + goto out; + + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, (const unsigned char*)iv) != 1) + goto out; + + if (EVP_DecryptUpdate(ctx, (unsigned char*)out, &len, (const unsigned char*)in, length) == 1) + r = 0; +out: + EVP_CIPHER_CTX_free(ctx); + return r; +#else + return -ENOTSUP; +#endif +} diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c index b0452a3..846f17c 100644 --- a/lib/crypto_backend/crypto_storage.c +++ b/lib/crypto_backend/crypto_storage.c @@ -2,7 +2,7 @@ * Generic wrapper for storage encryption modes and Initial Vectors * (reimplementation of some functions from Linux dm-crypt kernel) * - * Copyright (C) 2014, Milan Broz + * Copyright (C) 2014-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,23 +25,23 @@ #include "crypto_backend.h" #define SECTOR_SHIFT 9 -#define SECTOR_SIZE (1 << SECTOR_SHIFT) /* * Internal IV helper * IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */ struct crypt_sector_iv { - enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI } type; + enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type; int iv_size; char *iv; - struct crypt_cipher *essiv_cipher; - int benbi_shift; + struct crypt_cipher *cipher; + int shift; }; /* Block encryption storage context */ struct crypt_storage { - uint64_t sector_start; + unsigned sector_shift; + unsigned iv_shift; struct crypt_cipher *cipher; struct crypt_sector_iv cipher_iv; }; @@ -56,24 +56,31 @@ static int int_log2(unsigned int x) static int crypt_sector_iv_init(struct crypt_sector_iv *ctx, const char *cipher_name, const char *mode_name, - const char *iv_name, char *key, size_t key_length) + const char *iv_name, const void *key, size_t key_length, size_t sector_size) { + int r; + memset(ctx, 0, sizeof(*ctx)); - ctx->iv_size = crypt_cipher_blocksize(cipher_name); - if (ctx->iv_size < 0) + ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name); + if (ctx->iv_size < 8) return -ENOENT; - if (!iv_name || - !strcmp(cipher_name, "cipher_null") || + if (!strcmp(cipher_name, "cipher_null") || !strcmp(mode_name, "ecb")) { + if (iv_name) + return -EINVAL; ctx->type = IV_NONE; ctx->iv_size = 0; return 0; + } else if (!iv_name) { + return -EINVAL; } else if (!strcasecmp(iv_name, "null")) { ctx->type = IV_NULL; } else if (!strcasecmp(iv_name, "plain64")) { ctx->type = IV_PLAIN64; + } else if (!strcasecmp(iv_name, "plain64be")) { + ctx->type = IV_PLAIN64BE; } else if (!strcasecmp(iv_name, "plain")) { ctx->type = IV_PLAIN; } else if (!strncasecmp(iv_name, "essiv:", 6)) { @@ -81,7 +88,6 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx, char *hash_name = strchr(iv_name, ':'); int hash_size; char tmp[256]; - int r; if (!hash_name) return -EINVAL; @@ -109,7 +115,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx, return r; } - r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb", + r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb", tmp, hash_size); crypt_backend_memzero(tmp, sizeof(tmp)); if (r) @@ -122,7 +128,15 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx, return -EINVAL; ctx->type = IV_BENBI; - ctx->benbi_shift = SECTOR_SHIFT - log; + ctx->shift = SECTOR_SHIFT - log; + } else if (!strncasecmp(iv_name, "eboiv", 5)) { + r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb", + key, key_length); + if (r) + return r; + + ctx->type = IV_EBOIV; + ctx->shift = int_log2(sector_size); } else return -ENOENT; @@ -151,17 +165,27 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector memset(ctx->iv, 0, ctx->iv_size); *(uint64_t *)ctx->iv = cpu_to_le64(sector); break; + case IV_PLAIN64BE: + memset(ctx->iv, 0, ctx->iv_size); + *(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector); + break; case IV_ESSIV: memset(ctx->iv, 0, ctx->iv_size); *(uint64_t *)ctx->iv = cpu_to_le64(sector); - return crypt_cipher_encrypt(ctx->essiv_cipher, + return crypt_cipher_encrypt(ctx->cipher, ctx->iv, ctx->iv, ctx->iv_size, NULL, 0); break; case IV_BENBI: memset(ctx->iv, 0, ctx->iv_size); - val = cpu_to_be64((sector << ctx->benbi_shift) + 1); + val = cpu_to_be64((sector << ctx->shift) + 1); memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val)); break; + case IV_EBOIV: + memset(ctx->iv, 0, ctx->iv_size); + *(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift); + return crypt_cipher_encrypt(ctx->cipher, + ctx->iv, ctx->iv, ctx->iv_size, NULL, 0); + break; default: return -EINVAL; } @@ -169,10 +193,10 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector return 0; } -static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx) +static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx) { - if (ctx->type == IV_ESSIV) - crypt_cipher_destroy(ctx->essiv_cipher); + if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV) + crypt_cipher_destroy(ctx->cipher); if (ctx->iv) { memset(ctx->iv, 0, ctx->iv_size); @@ -180,22 +204,26 @@ static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx) } memset(ctx, 0, sizeof(*ctx)); - return 0; } /* Block encryption storage wrappers */ int crypt_storage_init(struct crypt_storage **ctx, - uint64_t sector_start, + size_t sector_size, const char *cipher, const char *cipher_mode, - char *key, size_t key_length) + const void *key, size_t key_length) { struct crypt_storage *s; char mode_name[64]; char *cipher_iv = NULL; int r = -EIO; + if (sector_size < (1 << SECTOR_SHIFT) || + sector_size > (1 << (SECTOR_SHIFT + 3)) || + sector_size & (sector_size - 1)) + return -EINVAL; + s = malloc(sizeof(*s)); if (!s) return -ENOMEM; @@ -216,33 +244,39 @@ int crypt_storage_init(struct crypt_storage **ctx, return r; } - r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length); + r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size); if (r) { crypt_storage_destroy(s); return r; } - s->sector_start = sector_start; + s->sector_shift = int_log2(sector_size); + s->iv_shift = s->sector_shift - SECTOR_SHIFT; *ctx = s; return 0; } int crypt_storage_decrypt(struct crypt_storage *ctx, - uint64_t sector, size_t count, - char *buffer) + uint64_t iv_offset, + uint64_t length, char *buffer) { - unsigned int i; + uint64_t i; int r = 0; - for (i = 0; i < count; i++) { - r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i); + if (length & ((1 << ctx->sector_shift) - 1)) + return -EINVAL; + + length >>= ctx->sector_shift; + + for (i = 0; i < length; i++) { + r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (uint64_t)(i << ctx->iv_shift)); if (r) break; r = crypt_cipher_decrypt(ctx->cipher, - &buffer[i * SECTOR_SIZE], - &buffer[i * SECTOR_SIZE], - SECTOR_SIZE, + &buffer[i << ctx->sector_shift], + &buffer[i << ctx->sector_shift], + 1 << ctx->sector_shift, ctx->cipher_iv.iv, ctx->cipher_iv.iv_size); if (r) @@ -253,20 +287,25 @@ int crypt_storage_decrypt(struct crypt_storage *ctx, } int crypt_storage_encrypt(struct crypt_storage *ctx, - uint64_t sector, size_t count, - char *buffer) + uint64_t iv_offset, + uint64_t length, char *buffer) { - unsigned int i; + uint64_t i; int r = 0; - for (i = 0; i < count; i++) { - r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i); + if (length & ((1 << ctx->sector_shift) - 1)) + return -EINVAL; + + length >>= ctx->sector_shift; + + for (i = 0; i < length; i++) { + r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (i << ctx->iv_shift)); if (r) break; r = crypt_cipher_encrypt(ctx->cipher, - &buffer[i * SECTOR_SIZE], - &buffer[i * SECTOR_SIZE], - SECTOR_SIZE, + &buffer[i << ctx->sector_shift], + &buffer[i << ctx->sector_shift], + 1 << ctx->sector_shift, ctx->cipher_iv.iv, ctx->cipher_iv.iv_size); if (r) @@ -276,10 +315,10 @@ int crypt_storage_encrypt(struct crypt_storage *ctx, return r; } -int crypt_storage_destroy(struct crypt_storage *ctx) +void crypt_storage_destroy(struct crypt_storage *ctx) { if (!ctx) - return 0; + return; crypt_sector_iv_destroy(&ctx->cipher_iv); @@ -288,6 +327,9 @@ int crypt_storage_destroy(struct crypt_storage *ctx) memset(ctx, 0, sizeof(*ctx)); free(ctx); +} - return 0; +bool crypt_storage_kernel_only(struct crypt_storage *ctx) +{ + return crypt_cipher_kernel_only(ctx->cipher); } diff --git a/lib/crypto_backend/pbkdf2_generic.c b/lib/crypto_backend/pbkdf2_generic.c index 2e9a3d2..3f6163c 100644 --- a/lib/crypto_backend/pbkdf2_generic.c +++ b/lib/crypto_backend/pbkdf2_generic.c @@ -4,8 +4,8 @@ * Copyright (C) 2004 Free Software Foundation * * cryptsetup related changes - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2014, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ #include #include -#include "crypto_backend.h" +#include "crypto_backend_internal.h" static int hash_buf(const char *src, size_t src_len, char *dst, size_t dst_len, @@ -230,197 +230,3 @@ out: return rc; } - -#if 0 -#include - -struct test_vector { - const char *hash; - unsigned int hash_block_length; - unsigned int iterations; - const char *password; - unsigned int password_length; - const char *salt; - unsigned int salt_length; - const char *output; - unsigned int output_length; -}; - -struct test_vector test_vectors[] = { - /* RFC 3962 */ - { - "sha1", 64, 1, - "password", 8, - "ATHENA.MIT.EDUraeburn", 21, - "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01" - "\x56\x5a\x11\x22\xb2\x56\x35\x15" - "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3" - "\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32 - }, { - "sha1", 64, 2, - "password", 8, - "ATHENA.MIT.EDUraeburn", 21, - "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e" - "\x98\x8b\x62\xc7\x3c\xda\x93\x5d" - "\xa0\x53\x78\xb9\x32\x44\xec\x8f" - "\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32 - }, { - "sha1", 64, 1200, - "password", 8, - "ATHENA.MIT.EDUraeburn", 21, - "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e" - "\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b" - "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f" - "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32 - }, { - "sha1", 64, 5, - "password", 8, - "\0224VxxV4\022", 8, // "\x1234567878563412 - "\xd1\xda\xa7\x86\x15\xf2\x87\xe6" - "\xa1\xc8\xb1\x20\xd7\x06\x2a\x49" - "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6" - "\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32 - }, { - "sha1", 64, 1200, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 64, - "pass phrase equals block size", 29, - "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b" - "\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9" - "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc" - "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32 - }, { - "sha1", 64, 1200, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65, - "pass phrase exceeds block size", 30, - "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5" - "\x1b\x10\xe6\xa6\x87\x21\xbe\x61" - "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b" - "\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32 - }, { - "sha1", 64, 50, - "\360\235\204\236", 4, // g-clef ("\xf09d849e) - "EXAMPLE.COMpianist", 18, - "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43" - "\xa5\xb8\xbb\x27\x6a\x40\x3b\x39" - "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2" - "\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32 - }, { - /* RFC-6070 */ - "sha1", 64, 1, - "password", 8, - "salt", 4, - "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" - "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20 - }, { - "sha1", 64, 2, - "password", 8, - "salt", 4, - "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e" - "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20 - }, { - "sha1", 64, 4096, - "password", 8, - "salt", 4, - "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad" - "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20 - }, { - "sha1", 64, 16777216, - "password", 8, - "salt", 4, - "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94" - "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20 - }, { - "sha1", 64, 4096, - "passwordPASSWORDpassword", 24, - "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, - "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8" - "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96" - "\x4c\xf2\xf0\x70\x38", 25 - }, { - "sha1", 64, 4096, - "pass\0word", 9, - "sa\0lt", 5, - "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37" - "\xd7\xf0\x34\x25\xe0\xc3", 16 - }, { - /* empty password test */ - "sha1", 64, 2, - "", 0, - "salt", 4, - "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2" - "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20 - }, { - /* Password exceeds block size test */ - "sha256", 64, 1200, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65, - "pass phrase exceeds block size", 30, - "\x22\x34\x4b\xc4\xb6\xe3\x26\x75" - "\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d" - "\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa" - "\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32 - }, { - "sha512", 128, 1200, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 129, - "pass phrase exceeds block size", 30, - "\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d" - "\x7d\x8e\xdd\x58\x01\xb4\x59\x72" - "\x99\x92\x16\x30\x5e\xa4\x36\x8d" - "\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32 - }, { - "whirlpool", 64, 1200, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65, - "pass phrase exceeds block size", 30, - "\x9c\x1c\x74\xf5\x88\x26\xe7\x6a" - "\x53\x58\xf4\x0c\x39\xe7\x80\x89" - "\x07\xc0\x31\x19\x9a\x50\xa2\x48" - "\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32 - } -}; - -static void printhex(const char *s, const char *buf, size_t len) -{ - size_t i; - - printf("%s: ", s); - for (i = 0; i < len; i++) - printf("\\x%02x", (unsigned char)buf[i]); - printf("\n"); - fflush(stdout); -} - -static int pkcs5_pbkdf2_test_vectors(void) -{ - char result[64]; - unsigned int i, j; - struct test_vector *vec; - - for (i = 0; i < (sizeof(test_vectors) / sizeof(*test_vectors)); i++) { - vec = &test_vectors[i]; - for (j = 1; j <= vec->output_length; j++) { - if (pkcs5_pbkdf2(vec->hash, - vec->password, vec->password_length, - vec->salt, vec->salt_length, - vec->iterations, - j, result, vec->hash_block_length)) { - printf("pbkdf2 failed, vector %d\n", i); - return -EINVAL; - } - if (memcmp(result, vec->output, j) != 0) { - printf("vector %u\n", i); - printhex(" got", result, j); - printhex("want", vec->output, j); - return -EINVAL; - } - memset(result, 0, sizeof(result)); - } - } - return 0; -} -#endif diff --git a/lib/crypto_backend/pbkdf_check.c b/lib/crypto_backend/pbkdf_check.c index c6236cc..7444e0a 100644 --- a/lib/crypto_backend/pbkdf_check.c +++ b/lib/crypto_backend/pbkdf_check.c @@ -1,7 +1,8 @@ /* * PBKDF performance check - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2014, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz + * Copyright (C) 2016-2020 Ondrej Mosnacek * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,11 +19,52 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include +#include +#include #include #include #include "crypto_backend.h" +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +#endif + +#define BENCH_MIN_MS 250 +#define BENCH_MIN_MS_FAST 10 +#define BENCH_PERCENT_ATLEAST 95 +#define BENCH_PERCENT_ATMOST 110 +#define BENCH_SAMPLES_FAST 3 +#define BENCH_SAMPLES_SLOW 1 + +/* These PBKDF2 limits must be never violated */ +int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits) +{ + if (!kdf || !limits) + return -EINVAL; + + if (!strcmp(kdf, "pbkdf2")) { + limits->min_iterations = 1000; /* recommendation in NIST SP 800-132 */ + limits->max_iterations = UINT32_MAX; + limits->min_memory = 0; /* N/A */ + limits->max_memory = 0; /* N/A */ + limits->min_parallel = 0; /* N/A */ + limits->max_parallel = 0; /* N/A */ + return 0; + } else if (!strcmp(kdf, "argon2i") || !strcmp(kdf, "argon2id")) { + limits->min_iterations = 4; + limits->max_iterations = UINT32_MAX; + limits->min_memory = 32; + limits->max_memory = 4*1024*1024; /* 4GiB */ + limits->min_parallel = 1; + limits->max_parallel = 4; + return 0; + } + + return -EINVAL; +} + static long time_ms(struct rusage *start, struct rusage *end) { int count_kernel_time = 0; @@ -50,35 +92,285 @@ static long time_ms(struct rusage *start, struct rusage *end) return ms; } +static long timespec_ms(struct timespec *start, struct timespec *end) +{ + return (end->tv_sec - start->tv_sec) * 1000 + + (end->tv_nsec - start->tv_nsec) / (1000 * 1000); +} + +static int measure_argon2(const char *kdf, const char *password, size_t password_length, + const char *salt, size_t salt_length, + char *key, size_t key_length, + uint32_t t_cost, uint32_t m_cost, uint32_t parallel, + size_t samples, long ms_atleast, long *out_ms) +{ + long ms, ms_min = LONG_MAX; + int r; + size_t i; + + for (i = 0; i < samples; i++) { + struct timespec tstart, tend; + + /* + * NOTE: We must use clock_gettime here, because Argon2 can run over + * multiple threads, and thus we care about real time, not CPU time! + */ + if (clock_gettime(CLOCK_MONOTONIC_RAW, &tstart) < 0) + return -EINVAL; + + r = crypt_pbkdf(kdf, NULL, password, password_length, salt, + salt_length, key, key_length, t_cost, m_cost, parallel); + if (r < 0) + return r; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &tend) < 0) + return -EINVAL; + + ms = timespec_ms(&tstart, &tend); + if (ms < 0) + return -EINVAL; + + if (ms < ms_atleast) { + /* early exit */ + ms_min = ms; + break; + } + if (ms < ms_min) { + ms_min = ms; + } + } + *out_ms = ms_min; + return 0; +} + +#define CONTINUE 0 +#define FINAL 1 +static int next_argon2_params(uint32_t *t_cost, uint32_t *m_cost, + uint32_t min_t_cost, uint32_t min_m_cost, + uint32_t max_m_cost, long ms, uint32_t target_ms) +{ + uint32_t old_t_cost, old_m_cost, new_t_cost, new_m_cost; + uint64_t num, denom; + + old_t_cost = *t_cost; + old_m_cost = *m_cost; + + if ((uint32_t)ms > target_ms) { + /* decreasing, first try to lower t_cost, then m_cost */ + num = (uint64_t)*t_cost * (uint64_t)target_ms; + denom = (uint64_t)ms; + new_t_cost = (uint32_t)(num / denom); + if (new_t_cost < min_t_cost) { + num = (uint64_t)*t_cost * (uint64_t)*m_cost * + (uint64_t)target_ms; + denom = (uint64_t)min_t_cost * (uint64_t)ms; + *t_cost = min_t_cost; + *m_cost = (uint32_t)(num / denom); + if (*m_cost < min_m_cost) { + *m_cost = min_m_cost; + return FINAL; + } + } else { + *t_cost = new_t_cost; + } + } else { + /* increasing, first try to increase m_cost, then t_cost */ + num = (uint64_t)*m_cost * (uint64_t)target_ms; + denom = (uint64_t)ms; + new_m_cost = (uint32_t)(num / denom); + if (new_m_cost > max_m_cost) { + num = (uint64_t)*t_cost * (uint64_t)*m_cost * + (uint64_t)target_ms; + denom = (uint64_t)max_m_cost * (uint64_t)ms; + *t_cost = (uint32_t)(num / denom); + *m_cost = max_m_cost; + if (*t_cost <= min_t_cost) { + *t_cost = min_t_cost; + return FINAL; + } + } else if (new_m_cost < min_m_cost) { + *m_cost = min_m_cost; + return FINAL; + } else { + *m_cost = new_m_cost; + } + } + + /* do not continue if it is the same as in the previous run */ + if (old_t_cost == *t_cost && old_m_cost == *m_cost) + return FINAL; + + return CONTINUE; +} + +static int crypt_argon2_check(const char *kdf, const char *password, + size_t password_length, const char *salt, + size_t salt_length, size_t key_length, + uint32_t min_t_cost, uint32_t min_m_cost, uint32_t max_m_cost, + uint32_t parallel, uint32_t target_ms, + uint32_t *out_t_cost, uint32_t *out_m_cost, + int (*progress)(uint32_t time_ms, void *usrptr), + void *usrptr) +{ + int r = 0; + char *key = NULL; + uint32_t t_cost, m_cost; + long ms; + long ms_atleast = (long)target_ms * BENCH_PERCENT_ATLEAST / 100; + long ms_atmost = (long)target_ms * BENCH_PERCENT_ATMOST / 100; + + if (key_length <= 0 || target_ms <= 0) + return -EINVAL; + + if (min_m_cost < (parallel * 8)) + min_m_cost = parallel * 8; + + if (max_m_cost < min_m_cost) + return -EINVAL; + + key = malloc(key_length); + if (!key) + return -ENOMEM; + + t_cost = min_t_cost; + m_cost = min_m_cost; + + /* 1. Find some small parameters, s. t. ms >= BENCH_MIN_MS: */ + while (1) { + r = measure_argon2(kdf, password, password_length, salt, salt_length, + key, key_length, t_cost, m_cost, parallel, + BENCH_SAMPLES_FAST, BENCH_MIN_MS, &ms); + if (!r) { + /* Update parameters to actual measurement */ + *out_t_cost = t_cost; + *out_m_cost = m_cost; + if (progress && progress((uint32_t)ms, usrptr)) + r = -EINTR; + } + + if (r < 0) + goto out; + + if (ms >= BENCH_MIN_MS) + break; + + if (m_cost == max_m_cost) { + if (ms < BENCH_MIN_MS_FAST) + t_cost *= 16; + else { + uint32_t new = (t_cost * BENCH_MIN_MS) / (uint32_t)ms; + if (new == t_cost) + break; + + t_cost = new; + } + } else { + if (ms < BENCH_MIN_MS_FAST) + m_cost *= 16; + else { + uint32_t new = (m_cost * BENCH_MIN_MS) / (uint32_t)ms; + if (new == m_cost) + break; + + m_cost = new; + } + if (m_cost > max_m_cost) { + m_cost = max_m_cost; + } + } + } + /* + * 2. Use the params obtained in (1.) to estimate the target params. + * 3. Then repeatedly measure the candidate params and if they fall out of + * the acceptance range (+-5 %), try to improve the estimate: + */ + do { + if (next_argon2_params(&t_cost, &m_cost, min_t_cost, min_m_cost, + max_m_cost, ms, target_ms)) { + /* Update parameters to final computation */ + *out_t_cost = t_cost; + *out_m_cost = m_cost; + break; + } + + r = measure_argon2(kdf, password, password_length, salt, salt_length, + key, key_length, t_cost, m_cost, parallel, + BENCH_SAMPLES_SLOW, ms_atleast, &ms); + + if (!r) { + /* Update parameters to actual measurement */ + *out_t_cost = t_cost; + *out_m_cost = m_cost; + if (progress && progress((uint32_t)ms, usrptr)) + r = -EINTR; + } + + if (r < 0) + break; + + } while (ms < ms_atleast || ms > ms_atmost); +out: + if (key) { + crypt_backend_memzero(key, key_length); + free(key); + } + return r; +} + /* This code benchmarks PBKDF and returns iterations/second using specified hash */ -int crypt_pbkdf_check(const char *kdf, const char *hash, - const char *password, size_t password_size, - const char *salt, size_t salt_size, - uint64_t *iter_secs) +static int crypt_pbkdf_check(const char *kdf, const char *hash, + const char *password, size_t password_length, + const char *salt, size_t salt_length, + size_t key_length, uint32_t *iter_secs, uint32_t target_ms, + int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr) + { struct rusage rstart, rend; int r = 0, step = 0; long ms = 0; - char buf; - unsigned int iterations; + char *key = NULL; + uint32_t iterations; + double PBKDF2_temp; - if (!kdf || !hash) + if (!kdf || !hash || key_length <= 0) return -EINVAL; + key = malloc(key_length); + if (!key) + return -ENOMEM; + + *iter_secs = 0; iterations = 1 << 15; - while (ms < 500) { - if (getrusage(RUSAGE_SELF, &rstart) < 0) - return -EINVAL; + while (1) { + if (getrusage(RUSAGE_SELF, &rstart) < 0) { + r = -EINVAL; + goto out; + } + + r = crypt_pbkdf(kdf, hash, password, password_length, salt, + salt_length, key, key_length, iterations, 0, 0); - r = crypt_pbkdf(kdf, hash, password, password_size, salt, - salt_size, &buf, 1, iterations); if (r < 0) - return r; + goto out; - if (getrusage(RUSAGE_SELF, &rend) < 0) - return -EINVAL; + if (getrusage(RUSAGE_SELF, &rend) < 0) { + r = -EINVAL; + goto out; + } ms = time_ms(&rstart, &rend); + if (ms) { + PBKDF2_temp = (double)iterations * target_ms / ms; + if (PBKDF2_temp > UINT32_MAX) + return -EINVAL; + *iter_secs = (uint32_t)PBKDF2_temp; + } + + if (progress && progress((uint32_t)ms, usrptr)) { + r = -EINTR; + goto out; + } + if (ms > 500) break; @@ -91,11 +383,53 @@ int crypt_pbkdf_check(const char *kdf, const char *hash, else iterations <<= 1; - if (++step > 10 || !iterations) - return -EINVAL; + if (++step > 10 || !iterations) { + r = -EINVAL; + goto out; + } } +out: + if (key) { + crypt_backend_memzero(key, key_length); + free(key); + } + return r; +} + +int crypt_pbkdf_perf(const char *kdf, const char *hash, + const char *password, size_t password_size, + const char *salt, size_t salt_size, + size_t volume_key_size, uint32_t time_ms, + uint32_t max_memory_kb, uint32_t parallel_threads, + uint32_t *iterations_out, uint32_t *memory_out, + int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr) +{ + struct crypt_pbkdf_limits pbkdf_limits; + int r = -EINVAL; + + if (!kdf || !iterations_out || !memory_out) + return -EINVAL; + + /* FIXME: whole limits propagation should be more clear here */ + r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits); + if (r < 0) + return r; + + *memory_out = 0; + *iterations_out = 0; + + if (!strcmp(kdf, "pbkdf2")) + r = crypt_pbkdf_check(kdf, hash, password, password_size, + salt, salt_size, volume_key_size, + iterations_out, time_ms, progress, usrptr); - if (iter_secs) - *iter_secs = (iterations * 1000) / ms; + else if (!strncmp(kdf, "argon2", 6)) + r = crypt_argon2_check(kdf, password, password_size, + salt, salt_size, volume_key_size, + pbkdf_limits.min_iterations, + pbkdf_limits.min_memory, + max_memory_kb, + parallel_threads, time_ms, iterations_out, + memory_out, progress, usrptr); return r; } diff --git a/lib/integrity/integrity.c b/lib/integrity/integrity.c new file mode 100644 index 0000000..86305ce --- /dev/null +++ b/lib/integrity/integrity.c @@ -0,0 +1,366 @@ +/* + * Integrity volume handling + * + * Copyright (C) 2016-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include "integrity.h" +#include "internal.h" + +static int INTEGRITY_read_superblock(struct crypt_device *cd, + struct device *device, + uint64_t offset, struct superblock *sb) +{ + int devfd, r; + + devfd = device_open(cd, device, O_RDONLY); + if(devfd < 0) + return -EINVAL; + + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) || + memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) || + sb->version < SB_VERSION_1 || sb->version > SB_VERSION_4) { + log_std(cd, "No integrity superblock detected on %s.\n", + device_path(device)); + r = -EINVAL; + } else { + sb->integrity_tag_size = le16toh(sb->integrity_tag_size); + sb->journal_sections = le32toh(sb->journal_sections); + sb->provided_data_sectors = le64toh(sb->provided_data_sectors); + sb->recalc_sector = le64toh(sb->recalc_sector); + sb->flags = le32toh(sb->flags); + r = 0; + } + + return r; +} + +int INTEGRITY_read_sb(struct crypt_device *cd, + struct crypt_params_integrity *params, + uint32_t *flags) +{ + struct superblock sb; + int r; + + r = INTEGRITY_read_superblock(cd, crypt_metadata_device(cd), 0, &sb); + if (r) + return r; + + params->sector_size = SECTOR_SIZE << sb.log2_sectors_per_block; + params->tag_size = sb.integrity_tag_size; + + if (flags) + *flags = sb.flags; + + return 0; +} + +int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset) +{ + struct superblock sb; + int r; + + r = INTEGRITY_read_superblock(cd, device, offset, &sb); + if (r) + return r; + + log_std(cd, "Info for integrity device %s.\n", device_path(device)); + log_std(cd, "superblock_version %d\n", (unsigned)sb.version); + log_std(cd, "log2_interleave_sectors %d\n", sb.log2_interleave_sectors); + log_std(cd, "integrity_tag_size %u\n", sb.integrity_tag_size); + log_std(cd, "journal_sections %u\n", sb.journal_sections); + log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors); + log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block); + if (sb.version == SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING)) + log_std(cd, "recalc_sector %" PRIu64 "\n", sb.recalc_sector); + log_std(cd, "log2_blocks_per_bitmap %u\n", sb.log2_blocks_per_bitmap_bit); + log_std(cd, "flags %s%s%s%s\n", + sb.flags & SB_FLAG_HAVE_JOURNAL_MAC ? "have_journal_mac " : "", + sb.flags & SB_FLAG_RECALCULATING ? "recalculating " : "", + sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "", + sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : ""); + + return 0; +} + +int INTEGRITY_data_sectors(struct crypt_device *cd, + struct device *device, uint64_t offset, + uint64_t *data_sectors) +{ + struct superblock sb; + int r; + + r = INTEGRITY_read_superblock(cd, device, offset, &sb); + if (r) + return r; + + *data_sectors = sb.provided_data_sectors; + return 0; +} + +int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity) +{ + if (!integrity) + return 0; + + //FIXME: use crypto backend hash size + if (!strcmp(integrity, "aead")) + return 0; + else if (!strcmp(integrity, "hmac(sha1)")) + return 20; + else if (!strcmp(integrity, "hmac(sha256)")) + return 32; + else if (!strcmp(integrity, "hmac(sha512)")) + return 64; + else if (!strcmp(integrity, "poly1305")) + return 0; + else if (!strcmp(integrity, "none")) + return 0; + + return -EINVAL; +} + +/* Return hash or hmac(hash) size, if known */ +int INTEGRITY_hash_tag_size(const char *integrity) +{ + char hash[MAX_CIPHER_LEN]; + int r; + + if (!integrity) + return 0; + + if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c")) + return 4; + + r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash); + if (r == 1) + r = crypt_hash_size(hash); + else + r = crypt_hash_size(integrity); + + return r < 0 ? 0 : r; +} + +int INTEGRITY_tag_size(struct crypt_device *cd, + const char *integrity, + const char *cipher, + const char *cipher_mode) +{ + int iv_tag_size = 0, auth_tag_size = 0; + + if (!cipher_mode) + iv_tag_size = 0; + else if (!strcmp(cipher_mode, "xts-random")) + iv_tag_size = 16; + else if (!strcmp(cipher_mode, "gcm-random")) + iv_tag_size = 12; + else if (!strcmp(cipher_mode, "ccm-random")) + iv_tag_size = 8; + else if (!strcmp(cipher_mode, "ctr-random")) + iv_tag_size = 16; + else if (!strcmp(cipher, "aegis256") && !strcmp(cipher_mode, "random")) + iv_tag_size = 32; + else if (!strcmp(cipher_mode, "random")) + iv_tag_size = 16; + + //FIXME: use crypto backend hash size + if (!integrity || !strcmp(integrity, "none")) + auth_tag_size = 0; + else if (!strcmp(integrity, "aead")) + auth_tag_size = 16; //FIXME gcm- mode only + else if (!strcmp(integrity, "cmac(aes)")) + auth_tag_size = 16; + else if (!strcmp(integrity, "hmac(sha1)")) + auth_tag_size = 20; + else if (!strcmp(integrity, "hmac(sha256)")) + auth_tag_size = 32; + else if (!strcmp(integrity, "hmac(sha512)")) + auth_tag_size = 64; + else if (!strcmp(integrity, "poly1305")) { + if (iv_tag_size) + iv_tag_size = 12; + auth_tag_size = 16; + } + + return iv_tag_size + auth_tag_size; +} + +int INTEGRITY_create_dmd_device(struct crypt_device *cd, + const struct crypt_params_integrity *params, + struct volume_key *vk, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key, + struct crypt_dm_active_device *dmd, + uint32_t flags, uint32_t sb_flags) +{ + int r; + + if (!dmd) + return -EINVAL; + + *dmd = (struct crypt_dm_active_device) { + .flags = flags, + }; + + /* Workaround for kernel dm-integrity table bug */ + if (sb_flags & SB_FLAG_RECALCULATING) + dmd->flags |= CRYPT_ACTIVATE_RECALCULATE; + + r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd), + crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size); + if (r < 0) + return r; + + return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size, + crypt_metadata_device(cd), crypt_data_device(cd), + crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd), + crypt_get_sector_size(cd), vk, journal_crypt_key, + journal_mac_key, params); +} + +int INTEGRITY_activate_dmd_device(struct crypt_device *cd, + const char *name, + const char *type, + struct crypt_dm_active_device *dmd, + uint32_t sb_flags) +{ + int r; + uint32_t dmi_flags; + struct dm_target *tgt = &dmd->segment; + + if (!single_segment(dmd) || tgt->type != DM_INTEGRITY) + return -EINVAL; + + log_dbg(cd, "Trying to activate INTEGRITY device on top of %s, using name %s, tag size %d, provided sectors %" PRIu64".", + device_path(tgt->data_device), name, tgt->u.integrity.tag_size, dmd->size); + + r = device_block_adjust(cd, tgt->data_device, DEV_EXCL, + tgt->u.integrity.offset, NULL, &dmd->flags); + if (r) + return r; + + if (tgt->u.integrity.meta_device) { + r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL); + if (r) + return r; + } + + r = dm_create_device(cd, name, type, dmd); + if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) { + log_err(cd, _("Kernel does not support dm-integrity mapping.")); + return -ENOTSUP; + } + + if (r < 0 && (sb_flags & SB_FLAG_FIXED_PADDING) && !dm_flags(cd, DM_INTEGRITY, &dmi_flags) && + !(dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED)) { + log_err(cd, _("Kernel does not support dm-integrity fixed metadata alignment.")); + return -ENOTSUP; + } + + return r; +} + +int INTEGRITY_activate(struct crypt_device *cd, + const char *name, + const struct crypt_params_integrity *params, + struct volume_key *vk, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key, + uint32_t flags, uint32_t sb_flags) +{ + struct crypt_dm_active_device dmd = {}; + int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key, + journal_mac_key, &dmd, flags, sb_flags); + + if (r < 0) + return r; + + r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags); + dm_targets_free(cd, &dmd); + return r; +} + +int INTEGRITY_format(struct crypt_device *cd, + const struct crypt_params_integrity *params, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key) +{ + uint32_t dmi_flags; + char tmp_name[64], tmp_uuid[40]; + struct crypt_dm_active_device dmdi = { + .size = 8, + .flags = CRYPT_ACTIVATE_PRIVATE, /* We always create journal but it can be unused later */ + }; + struct dm_target *tgt = &dmdi.segment; + int r; + uuid_t tmp_uuid_bin; + struct volume_key *vk = NULL; + + uuid_generate(tmp_uuid_bin); + uuid_unparse(tmp_uuid_bin, tmp_uuid); + + snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid); + + /* There is no data area, we can actually use fake zeroed key */ + if (params && params->integrity_key_size) + vk = crypt_alloc_volume_key(params->integrity_key_size, NULL); + + r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, crypt_metadata_device(cd), + crypt_data_device(cd), crypt_get_integrity_tag_size(cd), + crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk, + journal_crypt_key, journal_mac_key, params); + if (r < 0) { + crypt_free_volume_key(vk); + return r; + } + + log_dbg(cd, "Trying to format INTEGRITY device on top of %s, tmp name %s, tag size %d.", + device_path(tgt->data_device), tmp_name, tgt->u.integrity.tag_size); + + r = device_block_adjust(cd, tgt->data_device, DEV_EXCL, tgt->u.integrity.offset, NULL, NULL); + if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) { + log_err(cd, _("Kernel does not support dm-integrity mapping.")); + r = -ENOTSUP; + } + if (r) { + dm_targets_free(cd, &dmdi); + return r; + } + + if (tgt->u.integrity.meta_device) { + r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL); + if (r) { + dm_targets_free(cd, &dmdi); + return r; + } + } + + r = dm_create_device(cd, tmp_name, CRYPT_INTEGRITY, &dmdi); + crypt_free_volume_key(vk); + dm_targets_free(cd, &dmdi); + if (r) + return r; + + return dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE); +} diff --git a/lib/integrity/integrity.h b/lib/integrity/integrity.h new file mode 100644 index 0000000..38c4c5e --- /dev/null +++ b/lib/integrity/integrity.h @@ -0,0 +1,101 @@ +/* + * Integrity header definition + * + * Copyright (C) 2016-2020 Milan Broz + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_INTEGRITY_H +#define _CRYPTSETUP_INTEGRITY_H + +#include + +struct crypt_device; +struct device; +struct crypt_params_integrity; +struct volume_key; +struct crypt_dm_active_device; + +/* dm-integrity helper */ +#define SB_MAGIC "integrt" +#define SB_VERSION_1 1 +#define SB_VERSION_2 2 +#define SB_VERSION_3 3 +#define SB_VERSION_4 4 + +#define SB_FLAG_HAVE_JOURNAL_MAC (1 << 0) +#define SB_FLAG_RECALCULATING (1 << 1) /* V2 only */ +#define SB_FLAG_DIRTY_BITMAP (1 << 2) /* V3 only */ +#define SB_FLAG_FIXED_PADDING (1 << 3) /* V4 only */ + +struct superblock { + uint8_t magic[8]; + uint8_t version; + int8_t log2_interleave_sectors; + uint16_t integrity_tag_size; + uint32_t journal_sections; + uint64_t provided_data_sectors; + uint32_t flags; + uint8_t log2_sectors_per_block; + uint8_t log2_blocks_per_bitmap_bit; /* V3 only */ + uint8_t pad[2]; + uint64_t recalc_sector; /* V2 only */ +} __attribute__ ((packed)); + +int INTEGRITY_read_sb(struct crypt_device *cd, + struct crypt_params_integrity *params, + uint32_t *flags); + +int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset); + +int INTEGRITY_data_sectors(struct crypt_device *cd, + struct device *device, uint64_t offset, + uint64_t *data_sectors); +int INTEGRITY_key_size(struct crypt_device *cd, + const char *integrity); +int INTEGRITY_tag_size(struct crypt_device *cd, + const char *integrity, + const char *cipher, + const char *cipher_mode); +int INTEGRITY_hash_tag_size(const char *integrity); + +int INTEGRITY_format(struct crypt_device *cd, + const struct crypt_params_integrity *params, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key); + +int INTEGRITY_activate(struct crypt_device *cd, + const char *name, + const struct crypt_params_integrity *params, + struct volume_key *vk, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key, + uint32_t flags, uint32_t sb_flags); + +int INTEGRITY_create_dmd_device(struct crypt_device *cd, + const struct crypt_params_integrity *params, + struct volume_key *vk, + struct volume_key *journal_crypt_key, + struct volume_key *journal_mac_key, + struct crypt_dm_active_device *dmd, + uint32_t flags, uint32_t sb_flags); + +int INTEGRITY_activate_dmd_device(struct crypt_device *cd, + const char *name, + const char *type, + struct crypt_dm_active_device *dmd, + uint32_t sb_flags); +#endif diff --git a/lib/internal.h b/lib/internal.h index fb265ee..a418a46 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -1,10 +1,10 @@ /* * libcryptsetup - cryptsetup library internal * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,64 +26,150 @@ #include #include +#include +#include #include #include +#include #include "nls.h" #include "bitops.h" +#include "utils_blkid.h" #include "utils_crypt.h" #include "utils_loop.h" #include "utils_dm.h" #include "utils_fips.h" +#include "utils_keyring.h" +#include "utils_io.h" #include "crypto_backend.h" +#include "utils_storage_wrappers.h" #include "libcryptsetup.h" /* to silent gcc -Wcast-qual for const cast */ #define CONST_CAST(x) (x)(uintptr_t) +#define SHIFT_4K 12 #define SECTOR_SHIFT 9 #define SECTOR_SIZE (1 << SECTOR_SHIFT) +#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */ #define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */ #define DEFAULT_MEM_ALIGNMENT 4096 -#define MAX_ERROR_LENGTH 512 +#define LOG_MAX_LEN 4096 +#define MAX_DM_DEPS 32 + +#define CRYPT_SUBDEV "SUBDEV" /* prefix for sublayered devices underneath public crypt types */ #define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); }) +#define MISALIGNED(a, b) ((a) & ((b) - 1)) +#define MISALIGNED_4K(a) MISALIGNED((a), 1 << SHIFT_4K) +#define MISALIGNED_512(a) MISALIGNED((a), 1 << SECTOR_SHIFT) +#define NOTPOW2(a) MISALIGNED((a), (a)) + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +#define MOVE_REF(x, y) \ + do { \ + typeof (x) *_px = &(x), *_py = &(y); \ + *_px = *_py; \ + *_py = NULL; \ + } while (0) + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + struct crypt_device; +struct luks2_reenc_context; struct volume_key { + int id; size_t keylength; + const char *key_description; + struct volume_key *next; char key[]; }; -struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key); -struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, unsigned keylength); +struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key); +struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength); void crypt_free_volume_key(struct volume_key *vk); +int crypt_volume_key_set_description(struct volume_key *key, const char *key_description); +void crypt_volume_key_set_id(struct volume_key *vk, int id); +int crypt_volume_key_get_id(const struct volume_key *vk); +void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk); +struct volume_key *crypt_volume_key_next(struct volume_key *vk); +struct volume_key *crypt_volume_key_by_id(struct volume_key *vk, int id); + +struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd); +int init_pbkdf_type(struct crypt_device *cd, + const struct crypt_pbkdf_type *pbkdf, + const char *dev_type); +int verify_pbkdf_params(struct crypt_device *cd, + const struct crypt_pbkdf_type *pbkdf); +int crypt_benchmark_pbkdf_internal(struct crypt_device *cd, + struct crypt_pbkdf_type *pbkdf, + size_t volume_key_size); +const char *crypt_get_cipher_spec(struct crypt_device *cd); /* Device backend */ struct device; -int device_alloc(struct device **device, const char *path); -void device_free(struct device *device); +int device_alloc(struct crypt_device *cd, struct device **device, const char *path); +int device_alloc_no_check(struct device **device, const char *path); +void device_close(struct crypt_device *cd, struct device *device); +void device_free(struct crypt_device *cd, struct device *device); const char *device_path(const struct device *device); +const char *device_dm_name(const struct device *device); const char *device_block_path(const struct device *device); -void device_topology_alignment(struct device *device, - unsigned long *required_alignment, /* bytes */ - unsigned long *alignment_offset, /* bytes */ - unsigned long default_alignment); -int device_block_size(struct device *device); +void device_topology_alignment(struct crypt_device *cd, + struct device *device, + unsigned long *required_alignment, /* bytes */ + unsigned long *alignment_offset, /* bytes */ + unsigned long default_alignment); +size_t device_block_size(struct crypt_device *cd, struct device *device); int device_read_ahead(struct device *device, uint32_t *read_ahead); int device_size(struct device *device, uint64_t *size); -int device_open(struct device *device, int flags); +int device_open(struct crypt_device *cd, struct device *device, int flags); +int device_open_excl(struct crypt_device *cd, struct device *device, int flags); +void device_release_excl(struct crypt_device *cd, struct device *device); +void device_disable_direct_io(struct device *device); +int device_is_identical(struct device *device1, struct device *device2); +int device_is_rotational(struct device *device); +size_t device_alignment(struct device *device); +int device_direct_io(const struct device *device); +int device_fallocate(struct device *device, uint64_t size); +void device_sync(struct crypt_device *cd, struct device *device); +int device_check_size(struct crypt_device *cd, + struct device *device, + uint64_t req_offset, int falloc); + +int device_open_locked(struct crypt_device *cd, struct device *device, int flags); +int device_read_lock(struct crypt_device *cd, struct device *device); +int device_write_lock(struct crypt_device *cd, struct device *device); +void device_read_unlock(struct crypt_device *cd, struct device *device); +void device_write_unlock(struct crypt_device *cd, struct device *device); +bool device_is_locked(struct device *device); -enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 }; +enum devcheck { DEV_OK = 0, DEV_EXCL = 1 }; +int device_check_access(struct crypt_device *cd, + struct device *device, + enum devcheck device_check); int device_block_adjust(struct crypt_device *cd, struct device *device, enum devcheck device_check, uint64_t device_offset, uint64_t *size, uint32_t *flags); -size_t size_round_up(size_t size, unsigned int block); +size_t size_round_up(size_t size, size_t block); + +int create_or_reload_device(struct crypt_device *cd, const char *name, + const char *type, struct crypt_dm_active_device *dmd); + +int create_or_reload_device_with_integrity(struct crypt_device *cd, const char *name, + const char *type, struct crypt_dm_active_device *dmd, + struct crypt_dm_active_device *dmdi); /* Receive backend devices from context helpers */ struct device *crypt_metadata_device(struct crypt_device *cd); @@ -97,16 +183,18 @@ int crypt_dev_is_partition(const char *dev_path); char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size); char *crypt_get_base_device(const char *dev_path); uint64_t crypt_dev_partition_offset(const char *dev_path); +int lookup_by_disk_id(const char *dm_uuid); +int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len); +int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid); -ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count); -ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count); -ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset); +size_t crypt_getpagesize(void); +unsigned crypt_cpusonline(void); +uint64_t crypt_getphysmemory_kb(void); -unsigned crypt_getpagesize(void); int init_crypto(struct crypt_device *ctx); -void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 5, 6))); -#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x) +void logger(struct crypt_device *cd, int level, const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 5, 6))); +#define log_dbg(c, x...) logger(c, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x) #define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x) #define log_verbose(c, x...) logger(c, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x) #define log_err(c, x...) logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x) @@ -116,12 +204,14 @@ int crypt_get_debug_level(void); int crypt_memlock_inc(struct crypt_device *ctx); int crypt_memlock_dec(struct crypt_device *ctx); +int crypt_metadata_locking_enabled(void); + int crypt_random_init(struct crypt_device *ctx); int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int quality); void crypt_random_exit(void); int crypt_random_default_key_rng(void); -int crypt_plain_hash(struct crypt_device *ctx, +int crypt_plain_hash(struct crypt_device *cd, const char *hash_name, char *key, size_t key_size, const char *passphrase, size_t passphrase_size); @@ -131,23 +221,49 @@ int PLAIN_activate(struct crypt_device *cd, uint64_t size, uint32_t flags); -/** - * Different methods used to erase sensitive data concerning - * either encrypted payload area or master key inside keyslot - * area - */ -typedef enum { - CRYPT_WIPE_ZERO, /**< overwrite area using zero blocks */ - CRYPT_WIPE_DISK, /**< erase disk (using Gutmann method if it is rotational disk)*/ - CRYPT_WIPE_SSD, /**< erase solid state disk (random write) */ - CRYPT_WIPE_RANDOM /**< overwrite area using some up to now unspecified - * random algorithm */ -} crypt_wipe_type; - -int crypt_wipe(struct device *device, - uint64_t offset, - uint64_t sectors, - crypt_wipe_type type, - int flags); +void *crypt_get_hdr(struct crypt_device *cd, const char *type); +void crypt_set_reenc_context(struct crypt_device *cd, struct luks2_reenc_context *rh); +struct luks2_reenc_context *crypt_get_reenc_context(struct crypt_device *cd); + +int onlyLUKS2(struct crypt_device *cd); +int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask); + +int crypt_wipe_device(struct crypt_device *cd, + struct device *device, + crypt_wipe_pattern pattern, + uint64_t offset, + uint64_t length, + size_t wipe_block_size, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr), + void *usrptr); + +/* Internal integrity helpers */ +const char *crypt_get_integrity(struct crypt_device *cd); +int crypt_get_integrity_key_size(struct crypt_device *cd); +int crypt_get_integrity_tag_size(struct crypt_device *cd); + +int crypt_key_in_keyring(struct crypt_device *cd); +void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring); +int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk); +int crypt_use_keyring_for_vk(struct crypt_device *cd); +void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype); +void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks); + +static inline uint64_t version(uint16_t major, uint16_t minor, uint16_t patch, uint16_t release) +{ + return (uint64_t)release | ((uint64_t)patch << 16) | ((uint64_t)minor << 32) | ((uint64_t)major << 48); +} + +int kernel_version(uint64_t *kversion); + +int crypt_serialize_lock(struct crypt_device *cd); +void crypt_serialize_unlock(struct crypt_device *cd); + +bool crypt_string_in(const char *str, char **list, size_t list_size); +int crypt_strcmp(const char *a, const char *b); +int crypt_compare_dm_devices(struct crypt_device *cd, + const struct crypt_dm_active_device *src, + const struct crypt_dm_active_device *tgt); +static inline void *crypt_zalloc(size_t size) { return calloc(1, size); } #endif /* INTERNAL_H */ diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index 21b91dd..bfb0ca1 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -1,10 +1,10 @@ /* * libcryptsetup - cryptsetup library * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2015, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,10 +38,17 @@ extern "C" { #include #include +/** + * @defgroup crypt-init Cryptsetup device context initialization + * Set of functions for creating and destroying @e crypt_device context + * @addtogroup crypt-init + * @{ + */ + struct crypt_device; /* crypt device handle */ /** - * Initialize crypt device handle and check if provided device exists. + * Initialize crypt device handle and check if the provided device exists. * * @param cd Returns pointer to crypt device handle * @param device Path to the backing device. @@ -52,12 +59,29 @@ struct crypt_device; /* crypt device handle */ * * @return @e 0 on success or negative errno value otherwise. * - * @note Note that logging is not initialized here, possible messages uses + * @note Note that logging is not initialized here, possible messages use * default log function. */ int crypt_init(struct crypt_device **cd, const char *device); /** + * Initialize crypt device handle with optional data device and check + * if devices exist. + * + * @param cd Returns pointer to crypt device handle + * @param device Path to the backing device or detached header. + * @param data_device Path to the data device or @e NULL. + * + * @return @e 0 on success or negative errno value otherwise. + * + * @note Note that logging is not initialized here, possible messages use + * default log function. + */ +int crypt_init_data_device(struct crypt_device **cd, + const char *device, + const char *data_device); + +/** * Initialize crypt device handle from provided active device name, * and, optionally, from separate metadata (header) device * and check if provided device exists. @@ -77,8 +101,8 @@ int crypt_init(struct crypt_device **cd, const char *device); * crypt_init_by_name_and_header(cd, name, NULL); */ int crypt_init_by_name_and_header(struct crypt_device **cd, - const char *name, - const char *header_device); + const char *name, + const char *header_device); /** * This is equivalent to call @@ -89,15 +113,71 @@ int crypt_init_by_name_and_header(struct crypt_device **cd, int crypt_init_by_name(struct crypt_device **cd, const char *name); /** - * @defgroup loglevel Cryptsetup logging + * Release crypt device context and used memory. * - * Set of functions and defines used in cryptsetup for - * logging purposes + * @param cd crypt device handle + */ +void crypt_free(struct crypt_device *cd); + +/** + * Set confirmation callback (yes/no). + * + * If code need confirmation (like resetting uuid or restoring LUKS header from file) + * this function is called. If not defined, everything is confirmed. + * + * Callback function @e confirm should return @e 0 if operation is declined, + * other values mean accepted. + * + * @param cd crypt device handle + * @param confirm user defined confirm callback reference + * @param usrptr provided identification in callback + * @param msg Message for user to confirm * + * @note Current version of cryptsetup API requires confirmation for UUID change and + * LUKS header restore only. */ +void crypt_set_confirm_callback(struct crypt_device *cd, + int (*confirm)(const char *msg, void *usrptr), + void *usrptr); + +/** + * Set data device + * For LUKS it is encrypted data device when LUKS header is separated. + * For VERITY it is data device when hash device is separated. + * + * @param cd crypt device handle + * @param device path to device + * + * @returns 0 on success or negative errno value otherwise. + */ +int crypt_set_data_device(struct crypt_device *cd, const char *device); + +/** + * Set data device offset in 512-byte sectors. + * Used for LUKS. + * This function is replacement for data alignment fields in LUKS param struct. + * If set to 0 (default), old behaviour is preserved. + * This value is reset on @link crypt_load @endlink. + * + * @param cd crypt device handle + * @param data_offset data offset in bytes + * + * @returns 0 on success or negative errno value otherwise. + * + * @note Data offset must be aligned to multiple of 8 (alignment to 4096-byte sectors) + * and must be big enough to accommodate the whole LUKS header with all keyslots. + * @note Data offset is enforced by this function, device topology + * information is no longer used after calling this function. + */ +int crypt_set_data_offset(struct crypt_device *cd, uint64_t data_offset); + +/** @} */ /** - * @addtogroup loglevel + * @defgroup crypt-log Cryptsetup logging + * Set of functions and defines used in cryptsetup for + * logging purposes + * @addtogroup crypt-log * @{ */ @@ -109,6 +189,8 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name); #define CRYPT_LOG_VERBOSE 2 /** debug log level - always on stdout */ #define CRYPT_LOG_DEBUG -1 +/** debug log level - additional JSON output (for LUKS2) */ +#define CRYPT_LOG_DEBUG_JSON -2 /** * Set log function. @@ -136,145 +218,121 @@ void crypt_log(struct crypt_device *cd, int level, const char *msg); /** @} */ /** - * Set confirmation callback (yes/no) - * - * If code need confirmation (like resetting uuid or restoring LUKS header from file) - * this function is called. If not defined, everything is confirmed. - * - * Callback function @e confirm should return @e 0 if operation is declined, - * other values mean accepted. - * - * @param cd crypt device handle - * @param confirm user defined confirm callback reference - * @param usrptr provided identification in callback - * @param msg Message for user to confirm - * - * @note Current version of cryptsetup API requires confirmation only when UUID is being changed + * @defgroup crypt-set Cryptsetup settings (RNG, PBKDF, locking) + * @addtogroup crypt-set + * @{ */ -void crypt_set_confirm_callback(struct crypt_device *cd, - int (*confirm)(const char *msg, void *usrptr), - void *usrptr); -/** - * Set password query callback. - * - * If code need @e _interactive_ query for password, this callback is called. - * If not defined, compiled-in default is called (uses terminal input). - * - * Callback should return length of password in buffer - * or negative errno value in case of error. - * - * @param cd crypt device handle - * @param password user defined password callback reference - * @param usrptr provided identification in callback - * @param msg Message for user - * @param buf buffer for password - * @param length size of buffer - * - * @note Note that if this function is defined, verify option is ignored - * (caller which provided callback is responsible for password verification) - * @note Only zero terminated passwords can be entered this way, for complex - * use API functions directly. - * @note Maximal length of password is limited to @e length @e - @e 1 (minimal 511 chars) - * @note Internal compiled-in terminal input is DEPRECATED and will be removed - * in future versions. - * - * @see Callback function is used in these call provided, that certain conditions are met: - * @li crypt_keyslot_add_by_passphrase - * @li crypt_activate_by_passphrase - * @li crypt_resume_by_passphrase - * @li crypt_resume_by_keyfile - * @li crypt_keyslot_add_by_keyfile - * @li crypt_keyslot_add_by_volume_key - * - */ -void crypt_set_password_callback(struct crypt_device *cd, - int (*password)(const char *msg, char *buf, size_t length, void *usrptr), - void *usrptr); +/** CRYPT_RNG_URANDOM - use /dev/urandom */ +#define CRYPT_RNG_URANDOM 0 +/** CRYPT_RNG_RANDOM - use /dev/random (waits if no entropy in system) */ +#define CRYPT_RNG_RANDOM 1 /** - * Set timeout for interactive password entry using default - * password callback + * Set which RNG (random number generator) is used for generating long term key * * @param cd crypt device handle - * @param timeout_sec timeout in seconds + * @param rng_type kernel random number generator to use + * */ -void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec); +void crypt_set_rng_type(struct crypt_device *cd, int rng_type); /** - * Set number of retries in case password input has been incorrect + * Get which RNG (random number generator) is used for generating long term key. * * @param cd crypt device handle - * @param tries the number + * @return RNG type on success or negative errno value otherwise. + * */ -void crypt_set_password_retry(struct crypt_device *cd, int tries); +int crypt_get_rng_type(struct crypt_device *cd); /** - * Set how long should cryptsetup iterate in PBKDF2 function. - * Default value heads towards the iterations which takes around 1 second - * - * @param cd crypt device handle - * @param iteration_time_ms the time in ms + * PBKDF parameters. */ -void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms); -/* Don't ask :-) */ -void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms); +struct crypt_pbkdf_type { + const char *type; /**< PBKDF algorithm */ + const char *hash; /**< Hash algorithm */ + uint32_t time_ms; /**< Requested time cost [milliseconds] */ + uint32_t iterations; /**< Iterations, 0 or benchmarked value. */ + uint32_t max_memory_kb; /**< Requested or benchmarked memory cost [kilobytes] */ + uint32_t parallel_threads;/**< Requested parallel cost [threads] */ + uint32_t flags; /**< CRYPT_PBKDF* flags */ +}; + +/** Iteration time set by crypt_set_iteration_time(), for compatibility only. */ +#define CRYPT_PBKDF_ITER_TIME_SET (1 << 0) +/** Never run benchmarks, use pre-set value or defaults. */ +#define CRYPT_PBKDF_NO_BENCHMARK (1 << 1) + +/** PBKDF2 according to RFC2898, LUKS1 legacy */ +#define CRYPT_KDF_PBKDF2 "pbkdf2" +/** Argon2i according to RFC */ +#define CRYPT_KDF_ARGON2I "argon2i" +/** Argon2id according to RFC */ +#define CRYPT_KDF_ARGON2ID "argon2id" /** - * Set whether passphrase will be verified on input - * (user has to input same passphrase twice) + * Set default PBKDF (Password-Based Key Derivation Algorithm) for next keyslot + * about to get created with any crypt_keyslot_add_*() call. * * @param cd crypt device handle - * @param password_verify @e 0 = false, @e !0 true + * @param pbkdf PBKDF parameters + * + * @return 0 on success or negative errno value otherwise. + * + * @note For LUKS1, only PBKDF2 is supported, other settings will be rejected. + * @note For non-LUKS context types the call succeeds, but PBKDF is not used. */ -void crypt_set_password_verify(struct crypt_device *cd, int password_verify); +int crypt_set_pbkdf_type(struct crypt_device *cd, + const struct crypt_pbkdf_type *pbkdf); /** - * Set data device - * For LUKS it is encrypted data device when LUKS header is separated. - * For VERITY it is data device when hash device is separated. + * Get PBKDF (Password-Based Key Derivation Algorithm) parameters. * - * @param cd crypt device handle - * @param device path to device + * @param pbkdf_type type of PBKDF + * + * @return struct on success or NULL value otherwise. * */ -int crypt_set_data_device(struct crypt_device *cd, const char *device); +const struct crypt_pbkdf_type *crypt_get_pbkdf_type_params(const char *pbkdf_type); /** - * @defgroup rng Cryptsetup RNG + * Get default PBKDF (Password-Based Key Derivation Algorithm) settings for keyslots. + * Works only with LUKS device handles (both versions). * - * @addtogroup rng - * @{ + * @param type type of device (see @link crypt-type @endlink) + * + * @return struct on success or NULL value otherwise. * */ - -/** CRYPT_RNG_URANDOM - use /dev/urandom */ -#define CRYPT_RNG_URANDOM 0 -/** CRYPT_RNG_RANDOM - use /dev/random (waits if no entropy in system) */ -#define CRYPT_RNG_RANDOM 1 +const struct crypt_pbkdf_type *crypt_get_pbkdf_default(const char *type); /** - * Set which RNG (random number generator) is used for generating long term key + * Get current PBKDF (Password-Based Key Derivation Algorithm) settings for keyslots. + * Works only with LUKS device handles (both versions). * * @param cd crypt device handle - * @param rng_type kernel random number generator to use + * + * @return struct on success or NULL value otherwise. * */ -void crypt_set_rng_type(struct crypt_device *cd, int rng_type); +const struct crypt_pbkdf_type *crypt_get_pbkdf_type(struct crypt_device *cd); /** - * Get which RNG (random number generator) is used for generating long term key + * Set how long should cryptsetup iterate in PBKDF2 function. + * Default value heads towards the iterations which takes around 1 second. + * \b Deprecated, only for backward compatibility. + * Use @link crypt_set_pbkdf_type @endlink. * * @param cd crypt device handle - * @return RNG type on success or negative errno value otherwise. + * @param iteration_time_ms the time in ms * + * @note If the time value is not acceptable for active PBKDF, value is quietly ignored. */ -int crypt_get_rng_type(struct crypt_device *cd); - -/** @} */ +void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms); /** - * Helper to lock/unlock memory to avoid swap sensitive data to disk + * Helper to lock/unlock memory to avoid swap sensitive data to disk. * * @param cd crypt device handle, can be @e NULL * @param lock 0 to unlock otherwise lock memory @@ -287,14 +345,58 @@ int crypt_get_rng_type(struct crypt_device *cd); int crypt_memory_lock(struct crypt_device *cd, int lock); /** - * @defgroup crypt_type Cryptsetup on-disk format types + * Set global lock protection for on-disk metadata (file-based locking). * - * Set of functions, \#defines and structs related - * to on-disk format types + * @param cd crypt device handle, can be @e NULL + * @param enable 0 to disable locking otherwise enable it (default) + * + * @returns @e 0 on success or negative errno value otherwise. + * + * @note Locking applied only for some metadata formats (LUKS2). + * @note The switch is global on the library level. + * In current version locking can be only switched off and cannot be switched on later. + */ +int crypt_metadata_locking(struct crypt_device *cd, int enable); + +/** + * Set metadata header area sizes. This applies only to LUKS2. + * These values limit amount of metadata anf number of supportable keyslots. + * + * @param cd crypt device handle, can be @e NULL + * @param metadata_size size in bytes of JSON area + 4k binary header + * @param keyslots_size size in bytes of binary keyslots area + * + * @returns @e 0 on success or negative errno value otherwise. + * + * @note The metadata area is stored twice and both copies contain 4k binary header. + * Only 16,32,64,128,256,512,1024,2048 and 4096 kB value is allowed (see LUKS2 specification). + * @note Keyslots area size must be multiple of 4k with maximum 128MB. + */ +int crypt_set_metadata_size(struct crypt_device *cd, + uint64_t metadata_size, + uint64_t keyslots_size); + +/** + * Get metadata header area sizes. This applies only to LUKS2. + * These values limit amount of metadata anf number of supportable keyslots. + * + * @param cd crypt device handle + * @param metadata_size size in bytes of JSON area + 4k binary header + * @param keyslots_size size in bytes of binary keyslots area + * + * @returns @e 0 on success or negative errno value otherwise. */ +int crypt_get_metadata_size(struct crypt_device *cd, + uint64_t *metadata_size, + uint64_t *keyslots_size); + +/** @} */ /** - * @addtogroup crypt_type + * @defgroup crypt-type Cryptsetup on-disk format types + * Set of functions, \#defines and structs related + * to on-disk format types + * @addtogroup crypt-type * @{ */ @@ -302,12 +404,21 @@ int crypt_memory_lock(struct crypt_device *cd, int lock); #define CRYPT_PLAIN "PLAIN" /** LUKS version 1 header on-disk */ #define CRYPT_LUKS1 "LUKS1" +/** LUKS version 2 header on-disk */ +#define CRYPT_LUKS2 "LUKS2" /** loop-AES compatibility mode */ #define CRYPT_LOOPAES "LOOPAES" /** dm-verity mode */ #define CRYPT_VERITY "VERITY" /** TCRYPT (TrueCrypt-compatible and VeraCrypt-compatible) mode */ #define CRYPT_TCRYPT "TCRYPT" +/** INTEGRITY dm-integrity device */ +#define CRYPT_INTEGRITY "INTEGRITY" +/** BITLK (BitLocker-compatible mode) */ +#define CRYPT_BITLK "BITLK" + +/** LUKS any version */ +#define CRYPT_LUKS NULL /** * Get device type @@ -318,20 +429,28 @@ int crypt_memory_lock(struct crypt_device *cd, int lock); const char *crypt_get_type(struct crypt_device *cd); /** + * Get device default LUKS type + * + * @return string according to device type (CRYPT_LUKS1 or CRYPT_LUKS2). + */ +const char *crypt_get_default_type(void); + +/** * - * Structure used as parameter for PLAIN device type + * Structure used as parameter for PLAIN device type. * * @see crypt_format */ struct crypt_params_plain { - const char *hash; /**< password hash function */ - uint64_t offset; /**< offset in sectors */ - uint64_t skip; /**< IV offset / initialization sector */ - uint64_t size; /**< size of mapped device or @e 0 for autodetection */ + const char *hash; /**< password hash function */ + uint64_t offset; /**< offset in sectors */ + uint64_t skip; /**< IV offset / initialization sector */ + uint64_t size; /**< size of mapped device or @e 0 for autodetection */ + uint32_t sector_size; /**< sector size in bytes (@e 0 means 512 for compatibility) */ }; /** - * Structure used as parameter for LUKS device type + * Structure used as parameter for LUKS device type. * * @see crypt_format, crypt_load * @@ -340,14 +459,14 @@ struct crypt_params_plain { * */ struct crypt_params_luks1 { - const char *hash; /**< hash used in LUKS header */ - size_t data_alignment; /**< data alignment in sectors, data offset is multiple of this */ + const char *hash; /**< hash used in LUKS header */ + size_t data_alignment; /**< data area alignment in 512B sectors, data offset is multiple of this */ const char *data_device; /**< detached encrypted data device or @e NULL */ }; /** * - * Structure used as parameter for loop-AES device type + * Structure used as parameter for loop-AES device type. * * @see crypt_format * @@ -360,7 +479,7 @@ struct crypt_params_loopaes { /** * - * Structure used as parameter for dm-verity device type + * Structure used as parameter for dm-verity device type. * * @see crypt_format, crypt_load * @@ -369,6 +488,7 @@ struct crypt_params_verity { const char *hash_name; /**< hash function */ const char *data_device; /**< data_device (CRYPT_VERITY_CREATE_HASH) */ const char *hash_device; /**< hash_device (output only) */ + const char *fec_device; /**< fec_device (output only) */ const char *salt; /**< salt */ uint32_t salt_size; /**< salt size (in bytes) */ uint32_t hash_type; /**< in-kernel hashing type */ @@ -376,6 +496,8 @@ struct crypt_params_verity { uint32_t hash_block_size; /**< hash block size (in bytes) */ uint64_t data_size; /**< data area size (in data blocks) */ uint64_t hash_area_offset; /**< hash/header offset (in bytes) */ + uint64_t fec_area_offset; /**< FEC/header offset (in bytes) */ + uint32_t fec_roots; /**< Reed-Solomon FEC roots */ uint32_t flags; /**< CRYPT_VERITY* flags */ }; @@ -385,10 +507,12 @@ struct crypt_params_verity { #define CRYPT_VERITY_CHECK_HASH (1 << 1) /** Create hash - format hash device */ #define CRYPT_VERITY_CREATE_HASH (1 << 2) +/** Root hash signature required for activation */ +#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (1 << 3) /** * - * Structure used as parameter for TCRYPT device type + * Structure used as parameter for TCRYPT device type. * * @see crypt_load * @@ -403,9 +527,10 @@ struct crypt_params_tcrypt { const char *mode; /**< cipher block mode */ size_t key_size; /**< key size in bytes (the whole chain) */ uint32_t flags; /**< CRYPT_TCRYPT* flags */ + uint32_t veracrypt_pim; /**< VeraCrypt Personal Iteration Multiplier */ }; -/** Include legacy modes when scanning for header*/ +/** Include legacy modes when scanning for header */ #define CRYPT_TCRYPT_LEGACY_MODES (1 << 0) /** Try to load hidden header (describing hidden device) */ #define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1) @@ -419,10 +544,67 @@ struct crypt_params_tcrypt { */ #define CRYPT_TCRYPT_VERA_MODES (1 << 4) +/** + * + * Structure used as parameter for dm-integrity device type. + * + * @see crypt_format, crypt_load + * + * @note In bitmap tracking mode, the journal is implicitly disabled. + * As an ugly workaround for compatibility, journal_watermark is overloaded + * to mean 512-bytes sectors-per-bit and journal_commit_time means bitmap flush time. + * All other journal parameters are not applied in the bitmap mode. + */ +struct crypt_params_integrity { + uint64_t journal_size; /**< size of journal in bytes */ + unsigned int journal_watermark; /**< journal flush watermark in percents; in bitmap mode sectors-per-bit */ + unsigned int journal_commit_time; /**< journal commit time (or bitmap flush time) in ms */ + uint32_t interleave_sectors; /**< number of interleave sectors (power of two) */ + uint32_t tag_size; /**< tag size per-sector in bytes */ + uint32_t sector_size; /**< sector size in bytes */ + uint32_t buffer_sectors; /**< number of sectors in one buffer */ + const char *integrity; /**< integrity algorithm, NULL for LUKS2 */ + uint32_t integrity_key_size; /**< integrity key size in bytes, info only, 0 for LUKS2 */ + + const char *journal_integrity; /**< journal integrity algorithm */ + const char *journal_integrity_key; /**< journal integrity key, only for crypt_load */ + uint32_t journal_integrity_key_size; /**< journal integrity key size in bytes, only for crypt_load */ + + const char *journal_crypt; /**< journal encryption algorithm */ + const char *journal_crypt_key; /**< journal crypt key, only for crypt_load */ + uint32_t journal_crypt_key_size; /**< journal crypt key size in bytes, only for crypt_load */ +}; + +/** + * Structure used as parameter for LUKS2 device type. + * + * @see crypt_format, crypt_load + * + * @note during crypt_format @e data_device attribute determines + * if the LUKS2 header is separated from encrypted payload device + * + */ +struct crypt_params_luks2 { + const struct crypt_pbkdf_type *pbkdf; /**< PBKDF (and hash) parameters or @e NULL*/ + const char *integrity; /**< integrity algorithm or @e NULL */ + const struct crypt_params_integrity *integrity_params; /**< Data integrity parameters or @e NULL*/ + size_t data_alignment; /**< data area alignment in 512B sectors, data offset is multiple of this */ + const char *data_device; /**< detached encrypted data device or @e NULL */ + uint32_t sector_size; /**< encryption sector size */ + const char *label; /**< header label or @e NULL*/ + const char *subsystem; /**< header subsystem label or @e NULL*/ +}; /** @} */ /** - * Create (format) new crypt device (and possible header on-disk) but not activates it. + * @defgroup crypt-actions Cryptsetup device context actions + * Set of functions for formatting and manipulating with specific crypt_type + * @addtogroup crypt-actions + * @{ + */ + +/** + * Create (format) new crypt device (and possible header on-disk) but do not activate it. * * @pre @e cd contains initialized and not formatted device context (device type must @b not be set) * @@ -433,13 +615,13 @@ struct crypt_params_tcrypt { * @param uuid requested UUID or @e NULL if it should be generated * @param volume_key pre-generated volume key or @e NULL if it should be generated (only for LUKS) * @param volume_key_size size of volume key in bytes. - * @param params crypt type specific parameters (see @link crypt_type @endlink) + * @param params crypt type specific parameters (see @link crypt-type @endlink) * * @returns @e 0 on success or negative errno value otherwise. * - * @note Note that crypt_format does not enable any keyslot (in case of work with LUKS device), - * but it stores volume key internally and subsequent crypt_keyslot_add_* calls can be used. - * @note For VERITY @link crypt_type @endlink, only uuid parameter is used, others paramaters + * @note Note that crypt_format does not create LUKS keyslot (any version). To create keyslot + * call any crypt_keyslot_add_* function. + * @note For VERITY @link crypt-type @endlink, only uuid parameter is used, other parameters * are ignored and verity specific attributes are set through mandatory params option. */ int crypt_format(struct crypt_device *cd, @@ -452,7 +634,49 @@ int crypt_format(struct crypt_device *cd, void *params); /** - * Set new UUID for already existing device + * Set format compatibility flags. + * + * @param cd crypt device handle + * @param flags CRYPT_COMPATIBILITY_* flags + */ +void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags); + +/** + * Get compatibility flags. + * + * @param cd crypt device handle + * + * @returns compatibility flags + */ +uint32_t crypt_get_compatibility(struct crypt_device *cd); + +/** dm-integrity device uses less effective (legacy) padding (old kernels) */ +#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (1 << 0) + +/** + * Convert to new type for already existing device. + * + * @param cd crypt device handle + * @param type type of device (optional params struct must be of this type) + * @param params crypt type specific parameters (see @link crypt-type @endlink) + * + * @returns 0 on success or negative errno value otherwise. + * + * @note Currently, only LUKS1->LUKS2 and LUKS2->LUKS1 conversions are supported. + * Not all LUKS2 devices may be converted back to LUKS1. To make such a conversion + * possible all active LUKS2 keyslots must be in LUKS1 compatible mode (i.e. pbkdf + * type must be PBKDF2) and device cannot be formatted with any authenticated + * encryption mode. + * + * @note Device must be offline for conversion. UUID change is not possible for active + * devices. + */ +int crypt_convert(struct crypt_device *cd, + const char *type, + void *params); + +/** + * Set new UUID for already existing device. * * @param cd crypt device handle * @param uuid requested UUID or @e NULL if it should be generated @@ -462,14 +686,48 @@ int crypt_format(struct crypt_device *cd, * @note Currently, only LUKS device type are supported */ int crypt_set_uuid(struct crypt_device *cd, - const char *uuid); + const char *uuid); + +/** + * Set new labels (label and subsystem) for already existing device. + * + * @param cd crypt device handle + * @param label requested label or @e NULL + * @param subsystem requested subsystem label or @e NULL + * + * @returns 0 on success or negative errno value otherwise. + * + * @note Currently, only LUKS2 device type is supported + */ +int crypt_set_label(struct crypt_device *cd, + const char *label, + const char *subsystem); + +/** + * Enable or disable loading of volume keys via kernel keyring. When set to + * 'enabled' library loads key in kernel keyring first and pass the key + * description to dm-crypt instead of binary key copy. If set to 'disabled' + * library fallbacks to old method of loading volume key directly in + * dm-crypt target. + * + * @param cd crypt device handle, can be @e NULL + * @param enable 0 to disable loading of volume keys via kernel keyring + * (classical method) otherwise enable it (default) + * + * @returns @e 0 on success or negative errno value otherwise. + * + * @note Currently loading of volume keys via kernel keyring is supported + * (and enabled by default) only for LUKS2 devices. + * @note The switch is global on the library level. + */ +int crypt_volume_key_keyring(struct crypt_device *cd, int enable); /** - * Load crypt device parameters from on-disk header + * Load crypt device parameters from on-disk header. * * @param cd crypt device handle - * @param requested_type @link crypt_type @endlink or @e NULL for all known - * @param params crypt type specific parameters (see @link crypt_type @endlink) + * @param requested_type @link crypt-type @endlink or @e NULL for all known + * @param params crypt type specific parameters (see @link crypt-type @endlink) * * @returns 0 on success or negative errno value otherwise. * @@ -480,38 +738,51 @@ int crypt_set_uuid(struct crypt_device *cd, * */ int crypt_load(struct crypt_device *cd, - const char *requested_type, - void *params); + const char *requested_type, + void *params); /** - * Try to repair crypt device on-disk header if invalid + * Try to repair crypt device LUKS on-disk header if invalid. * * @param cd crypt device handle - * @param requested_type @link crypt_type @endlink or @e NULL for all known - * @param params crypt type specific parameters (see @link crypt_type @endlink) + * @param requested_type @link crypt-type @endlink or @e NULL for all known + * @param params crypt type specific parameters (see @link crypt-type @endlink) * * @returns 0 on success or negative errno value otherwise. * + * @note For LUKS2 device crypt_repair bypass blkid checks and + * perform auto-recovery even though there're third party device + * signatures found by blkid probes. Currently the crypt_repair on LUKS2 + * works only if exactly one header checksum does not match or exactly + * one header is missing. */ int crypt_repair(struct crypt_device *cd, - const char *requested_type, - void *params); + const char *requested_type, + void *params); /** - * Resize crypt device + * Resize crypt device. * * @param cd - crypt device handle * @param name - name of device to resize * @param new_size - new device size in sectors or @e 0 to use all of the underlying device size * * @return @e 0 on success or negative errno value otherwise. + * + * @note Most notably it returns -EPERM when device was activated with volume key + * in kernel keyring and current device handle (context) doesn't have verified key + * loaded in kernel. To load volume key for already active device use any of + * @link crypt_activate_by_passphrase @endlink, @link crypt_activate_by_keyfile @endlink, + * @link crypt_activate_by_keyfile_offset @endlink, @link crypt_activate_by_volume_key @endlink, + * @link crypt_activate_by_keyring @endlink or @link crypt_activate_by_token @endlink with flag + * @e CRYPT_ACTIVATE_KEYRING_KEY raised and @e name parameter set to @e NULL. */ int crypt_resize(struct crypt_device *cd, - const char *name, - uint64_t new_size); + const char *name, + uint64_t new_size); /** - * Suspends crypt device. + * Suspend crypt device. * * @param cd crypt device handle, can be @e NULL * @param name name of device to suspend @@ -522,23 +793,21 @@ int crypt_resize(struct crypt_device *cd, * */ int crypt_suspend(struct crypt_device *cd, - const char *name); + const char *name); /** - * Resumes crypt device using passphrase. + * Resume crypt device using passphrase. * * * @param cd crypt device handle * @param name name of device to resume * @param keyslot requested keyslot or CRYPT_ANY_SLOT - * @param passphrase passphrase used to unlock volume key, @e NULL for query + * @param passphrase passphrase used to unlock volume key * @param passphrase_size size of @e passphrase (binary data) * * @return unlocked key slot number or negative errno otherwise. * * @note Only LUKS device type is supported - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. */ int crypt_resume_by_passphrase(struct crypt_device *cd, const char *name, @@ -547,19 +816,26 @@ int crypt_resume_by_passphrase(struct crypt_device *cd, size_t passphrase_size); /** - * Resumes crypt device using key file. + * Resume crypt device using key file. * * @param cd crypt device handle * @param name name of device to resume * @param keyslot requested keyslot or CRYPT_ANY_SLOT - * @param keyfile key file used to unlock volume key, @e NULL for passphrase query + * @param keyfile key file used to unlock volume key * @param keyfile_size number of bytes to read from keyfile, 0 is unlimited * @param keyfile_offset number of bytes to skip at start of keyfile * * @return unlocked key slot number or negative errno otherwise. - * - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. + */ +int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset); + +/** + * Backward compatible crypt_resume_by_keyfile_device_offset() (with size_t offset). */ int crypt_resume_by_keyfile_offset(struct crypt_device *cd, const char *name, @@ -567,48 +843,53 @@ int crypt_resume_by_keyfile_offset(struct crypt_device *cd, const char *keyfile, size_t keyfile_size, size_t keyfile_offset); + /** - * Backward compatible crypt_resume_by_keyfile_offset() (without offset). + * Backward compatible crypt_resume_by_keyfile_device_offset() (without offset). */ int crypt_resume_by_keyfile(struct crypt_device *cd, const char *name, int keyslot, const char *keyfile, size_t keyfile_size); - /** - * Releases crypt device context and used memory. + * Resume crypt device using provided volume key. * * @param cd crypt device handle + * @param name name of device to resume + * @param volume_key provided volume key + * @param volume_key_size size of volume_key + * + * @return @e 0 on success or negative errno value otherwise. */ -void crypt_free(struct crypt_device *cd); +int crypt_resume_by_volume_key(struct crypt_device *cd, + const char *name, + const char *volume_key, + size_t volume_key_size); +/** @} */ /** - * @defgroup keyslot Cryptsetup LUKS keyslots - * @addtogroup keyslot + * @defgroup crypt-keyslot LUKS keyslots + * @addtogroup crypt-keyslot * @{ - * */ /** iterate through all keyslots and find first one that fits */ #define CRYPT_ANY_SLOT -1 /** - * Add key slot using provided passphrase + * Add key slot using provided passphrase. * * @pre @e cd contains initialized and formatted LUKS device context * * @param cd crypt device handle * @param keyslot requested keyslot or @e CRYPT_ANY_SLOT - * @param passphrase passphrase used to unlock volume key, @e NULL for query + * @param passphrase passphrase used to unlock volume key * @param passphrase_size size of passphrase (binary data) - * @param new_passphrase passphrase for new keyslot, @e NULL for query + * @param new_passphrase passphrase for new keyslot * @param new_passphrase_size size of @e new_passphrase (binary data) * * @return allocated key slot number or negative errno otherwise. - * - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. */ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, int keyslot, @@ -618,26 +899,19 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, size_t new_passphrase_size); /** - * Change defined key slot using provided passphrase + * Change defined key slot using provided passphrase. * * @pre @e cd contains initialized and formatted LUKS device context * * @param cd crypt device handle * @param keyslot_old old keyslot or @e CRYPT_ANY_SLOT * @param keyslot_new new keyslot (can be the same as old) - * @param passphrase passphrase used to unlock volume key, @e NULL for query + * @param passphrase passphrase used to unlock volume key * @param passphrase_size size of passphrase (binary data) - * @param new_passphrase passphrase for new keyslot, @e NULL for query + * @param new_passphrase passphrase for new keyslot * @param new_passphrase_size size of @e new_passphrase (binary data) * * @return allocated key slot number or negative errno otherwise. - * - * @note This function is just internal implementation of luksChange - * command to avoid reading of volume key outside libcryptsetup boundary - * in FIPS mode. - * - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. */ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, int keyslot_old, @@ -648,24 +922,34 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, size_t new_passphrase_size); /** -* Add key slot using provided key file path +* Add key slot using provided key file path. * * @pre @e cd contains initialized and formatted LUKS device context * * @param cd crypt device handle * @param keyslot requested keyslot or @e CRYPT_ANY_SLOT - * @param keyfile key file used to unlock volume key, @e NULL for passphrase query + * @param keyfile key file used to unlock volume key * @param keyfile_size number of bytes to read from keyfile, @e 0 is unlimited * @param keyfile_offset number of bytes to skip at start of keyfile - * @param new_keyfile keyfile for new keyslot, @e NULL for passphrase query + * @param new_keyfile keyfile for new keyslot * @param new_keyfile_size number of bytes to read from @e new_keyfile, @e 0 is unlimited * @param new_keyfile_offset number of bytes to skip at start of new_keyfile * * @return allocated key slot number or negative errno otherwise. - * - * @note Note that @e keyfile can be "-" for STDIN */ -int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, +int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset, + const char *new_keyfile, + size_t new_keyfile_size, + uint64_t new_keyfile_offset); + +/** + * Backward compatible crypt_keyslot_add_by_keyfile_device_offset() (with size_t offset). + */ +int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, int keyslot, const char *keyfile, size_t keyfile_size, @@ -673,8 +957,9 @@ int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, const char *new_keyfile, size_t new_keyfile_size, size_t new_keyfile_offset); + /** - * Backward compatible crypt_keyslot_add_by_keyfile_offset() (without offset). + * Backward compatible crypt_keyslot_add_by_keyfile_device_offset() (without offset). */ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd, int keyslot, @@ -684,7 +969,7 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd, size_t new_keyfile_size); /** - * Add key slot using provided volume key + * Add key slot using provided volume key. * * @pre @e cd contains initialized and formatted LUKS device context * @@ -692,13 +977,10 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd, * @param keyslot requested keyslot or CRYPT_ANY_SLOT * @param volume_key provided volume key or @e NULL if used after crypt_format * @param volume_key_size size of volume_key - * @param passphrase passphrase for new keyslot, @e NULL for query + * @param passphrase passphrase for new keyslot * @param passphrase_size size of passphrase * * @return allocated key slot number or negative errno otherwise. - * - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. */ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, int keyslot, @@ -707,8 +989,54 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, const char *passphrase, size_t passphrase_size); +/** create keyslot with volume key not associated with current dm-crypt segment */ +#define CRYPT_VOLUME_KEY_NO_SEGMENT (1 << 0) + +/** create keyslot with new volume key and assign it to current dm-crypt segment */ +#define CRYPT_VOLUME_KEY_SET (1 << 1) + +/** Assign key to first matching digest before creating new digest */ +#define CRYPT_VOLUME_KEY_DIGEST_REUSE (1 << 2) + /** - * Destroy (and disable) key slot + * Add key slot using provided key. + * + * @pre @e cd contains initialized and formatted LUKS2 device context + * + * @param cd crypt device handle + * @param keyslot requested keyslot or CRYPT_ANY_SLOT + * @param volume_key provided volume key or @e NULL (see note below) + * @param volume_key_size size of volume_key + * @param passphrase passphrase for new keyslot + * @param passphrase_size size of passphrase + * @param flags key flags to set + * + * @return allocated key slot number or negative errno otherwise. + * + * @note in case volume_key is @e NULL following first matching rule will apply: + * @li if cd is device handle used in crypt_format() by current process, the volume + * key generated (or passed) in crypt_format() will be stored in keyslot. + * @li if CRYPT_VOLUME_KEY_NO_SEGMENT flag is raised the new volume_key will be + * generated and stored in keyslot. The keyslot will become unbound (unusable to + * dm-crypt device activation). + * @li fails with -EINVAL otherwise + * + * @warning CRYPT_VOLUME_KEY_SET flag force updates volume key. It is @b not @b reencryption! + * By doing so you will most probably destroy your ciphertext data device. It's supposed + * to be used only in wrapped keys scheme for key refresh process where real (inner) volume + * key stays untouched. It may be involed on active @e keyslot which makes the (previously + * unbound) keyslot new regular keyslot. + */ +int crypt_keyslot_add_by_key(struct crypt_device *cd, + int keyslot, + const char *volume_key, + size_t volume_key_size, + const char *passphrase, + size_t passphrase_size, + uint32_t flags); + +/** + * Destroy (and disable) key slot. * * @pre @e cd contains initialized and formatted LUKS device context * @@ -720,18 +1048,15 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, * @note Note that there is no passphrase verification used. */ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); - /** @} */ /** - * @defgroup aflags Device runtime attributes - * + * @defgroup crypt-aflags Device runtime attributes * Activation flags - * - * @addtogroup aflags + * @addtogroup crypt-aflags * @{ - * */ + /** device is read only */ #define CRYPT_ACTIVATE_READONLY (1 << 0) /** only reported for device without uuid */ @@ -748,20 +1073,49 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6) /** use submit_from_crypt_cpus for dm-crypt */ #define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (1 << 7) - +/** dm-verity: ignore_corruption flag - ignore corruption, log it only */ +#define CRYPT_ACTIVATE_IGNORE_CORRUPTION (1 << 8) +/** dm-verity: restart_on_corruption flag - restart kernel on corruption */ +#define CRYPT_ACTIVATE_RESTART_ON_CORRUPTION (1 << 9) +/** dm-verity: ignore_zero_blocks - do not verify zero blocks */ +#define CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS (1 << 10) +/** key loaded in kernel keyring instead directly in dm-crypt */ +#define CRYPT_ACTIVATE_KEYRING_KEY (1 << 11) +/** dm-integrity: direct writes, do not use journal */ +#define CRYPT_ACTIVATE_NO_JOURNAL (1 << 12) +/** dm-integrity: recovery mode - no journal, no integrity checks */ +#define CRYPT_ACTIVATE_RECOVERY (1 << 13) +/** ignore persistently stored flags */ +#define CRYPT_ACTIVATE_IGNORE_PERSISTENT (1 << 14) +/** dm-verity: check_at_most_once - check data blocks only the first time */ +#define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (1 << 15) +/** allow activation check including unbound keyslots (keyslots without segments) */ +#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (1 << 16) +/** dm-integrity: activate automatic recalculation */ +#define CRYPT_ACTIVATE_RECALCULATE (1 << 17) +/** reactivate existing and update flags, input only */ +#define CRYPT_ACTIVATE_REFRESH (1 << 18) +/** Use global lock to serialize memory hard KDF on activation (OOM workaround) */ +#define CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF (1 << 19) +/** dm-integrity: direct writes, use bitmap to track dirty sectors */ +#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (1 << 20) +/** device is suspended (key should be wiped from memory), output only */ +#define CRYPT_ACTIVATE_SUSPENDED (1 << 21) +/** use IV sector counted in sector_size instead of default 512 bytes sectors */ +#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (1 << 22) /** * Active device runtime attributes */ struct crypt_active_device { - uint64_t offset; /**< offset in sectors */ + uint64_t offset; /**< offset in sectors */ uint64_t iv_offset; /**< IV initialization sector */ - uint64_t size; /**< active device size */ - uint32_t flags; /**< activation flags */ + uint64_t size; /**< active device size */ + uint32_t flags; /**< activation flags */ }; /** - * Receives runtime attributes of active crypt device + * Receive runtime attributes of active crypt device. * * @param cd crypt device handle (can be @e NULL) * @param name name of active device @@ -771,25 +1125,99 @@ struct crypt_active_device { * */ int crypt_get_active_device(struct crypt_device *cd, - const char *name, - struct crypt_active_device *cad); + const char *name, + struct crypt_active_device *cad); +/** + * Get detected number of integrity failures. + * + * @param cd crypt device handle (can be @e NULL) + * @param name name of active device + * + * @return number of integrity failures or @e 0 otherwise + * + */ +uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd, + const char *name); /** @} */ /** - * Activate device or check passphrase + * @defgroup crypt-pflags LUKS2 Device persistent flags and requirements + * @addtogroup crypt-pflags + * @{ + */ + +/** + * LUKS2 header requirements + */ +/** Unfinished offline reencryption */ +#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (1 << 0) +/** Online reencryption in-progress */ +#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (1 << 1) +/** unknown requirement in header (output only) */ +#define CRYPT_REQUIREMENT_UNKNOWN (1 << 31) + +/** + * Persistent flags type + */ +typedef enum { + CRYPT_FLAGS_ACTIVATION, /**< activation flags, @see aflags */ + CRYPT_FLAGS_REQUIREMENTS /**< requirements flags */ +} crypt_flags_type; + +/** + * Set persistent flags. + * + * @param cd crypt device handle (can be @e NULL) + * @param type type to set (CRYPT_FLAGS_ACTIVATION or CRYPT_FLAGS_REQUIREMENTS) + * @param flags flags to set + * + * @return @e 0 on success or negative errno value otherwise + * + * @note Valid only for LUKS2. + * + * @note Not all activation flags can be stored. Only ALLOW_DISCARD, + * SAME_CPU_CRYPT, SUBMIT_FROM_CRYPT_CPU and NO_JOURNAL can be + * stored persistently. + * + * @note Only requirements flags recognised by current library may be set. + * CRYPT_REQUIREMENT_UNKNOWN is illegal (output only) in set operation. + */ +int crypt_persistent_flags_set(struct crypt_device *cd, + crypt_flags_type type, + uint32_t flags); + +/** + * Get persistent flags stored in header. + * + * @param cd crypt device handle (can be @e NULL) + * @param type flags type to retrieve (CRYPT_FLAGS_ACTIVATION or CRYPT_FLAGS_REQUIREMENTS) + * @param flags reference to output variable + * + * @return @e 0 on success or negative errno value otherwise + */ +int crypt_persistent_flags_get(struct crypt_device *cd, + crypt_flags_type type, + uint32_t *flags); +/** @} */ + +/** + * @defgroup crypt-activation Device activation + * @addtogroup crypt-activation + * @{ + */ + +/** + * Activate device or check passphrase. * * @param cd crypt device handle * @param name name of device to create, if @e NULL only check passphrase * @param keyslot requested keyslot to check or @e CRYPT_ANY_SLOT - * @param passphrase passphrase used to unlock volume key, @e NULL for query + * @param passphrase passphrase used to unlock volume key * @param passphrase_size size of @e passphrase * @param flags activation flags * * @return unlocked key slot number or negative errno otherwise. - * - * @note If passphrase is @e NULL always use crypt_set_password_callback. - * Internal terminal password query is DEPRECATED and will be removed in next version. */ int crypt_activate_by_passphrase(struct crypt_device *cd, const char *name, @@ -799,7 +1227,7 @@ int crypt_activate_by_passphrase(struct crypt_device *cd, uint32_t flags); /** - * Activate device or check using key file + * Activate device or check using key file. * * @param cd crypt device handle * @param name name of device to create, if @e NULL only check keyfile @@ -811,6 +1239,17 @@ int crypt_activate_by_passphrase(struct crypt_device *cd, * * @return unlocked key slot number or negative errno otherwise. */ +int crypt_activate_by_keyfile_device_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset, + uint32_t flags); + +/** + * Backward compatible crypt_activate_by_keyfile_device_offset() (with size_t offset). + */ int crypt_activate_by_keyfile_offset(struct crypt_device *cd, const char *name, int keyslot, @@ -818,8 +1257,9 @@ int crypt_activate_by_keyfile_offset(struct crypt_device *cd, size_t keyfile_size, size_t keyfile_offset, uint32_t flags); + /** - * Backward compatible crypt_activate_by_keyfile_offset() (without offset). + * Backward compatible crypt_activate_by_keyfile_device_offset() (without offset). */ int crypt_activate_by_keyfile(struct crypt_device *cd, const char *name, @@ -829,8 +1269,7 @@ int crypt_activate_by_keyfile(struct crypt_device *cd, uint32_t flags); /** - * Activate device using provided volume key - * + * Activate device using provided volume key. * * @param cd crypt device handle * @param name name of device to create, if @e NULL only check volume key @@ -856,20 +1295,87 @@ int crypt_activate_by_volume_key(struct crypt_device *cd, uint32_t flags); /** + * Activate VERITY device using provided key and optional signature). + * + * @param cd crypt device handle + * @param name name of device to create + * @param volume_key provided volume key + * @param volume_key_size size of volume_key + * @param signature buffer with signature for the key + * @param signature_size bsize of signature buffer + * @param flags activation flags + * + * @return @e 0 on success or negative errno value otherwise. + * + * @note For VERITY the volume key means root hash required for activation. + * Because kernel dm-verity is always read only, you have to provide + * CRYPT_ACTIVATE_READONLY flag always. + */ +int crypt_activate_by_signed_key(struct crypt_device *cd, + const char *name, + const char *volume_key, + size_t volume_key_size, + const char *signature, + size_t signature_size, + uint32_t flags); + +/** + * Activate device using passphrase stored in kernel keyring. + * + * @param cd crypt device handle + * @param name name of device to create, if @e NULL only check passphrase in keyring + * @param key_description kernel keyring key description library should look + * for passphrase in + * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT + * @param flags activation flags + * + * @return @e unlocked keyslot number on success or negative errno value otherwise. + * + * @note Keyslot passphrase must be stored in 'user' key type + * and the key has to be reachable for process context + * on behalf of which this function is called. + */ +int crypt_activate_by_keyring(struct crypt_device *cd, + const char *name, + const char *key_description, + int keyslot, + uint32_t flags); + +/** lazy deactivation - remove once last user releases it */ +#define CRYPT_DEACTIVATE_DEFERRED (1 << 0) +/** force deactivation - if the device is busy, it is replaced by error device */ +#define CRYPT_DEACTIVATE_FORCE (1 << 1) + +/** * Deactivate crypt device. This function tries to remove active device-mapper * mapping from kernel. Also, sensitive data like the volume key are removed from * memory * * @param cd crypt device handle, can be @e NULL * @param name name of device to deactivate + * @param flags deactivation flags * * @return @e 0 on success or negative errno value otherwise. * */ +int crypt_deactivate_by_name(struct crypt_device *cd, + const char *name, + uint32_t flags); + +/** + * Deactivate crypt device. See @ref crypt_deactivate_by_name with empty @e flags. + */ int crypt_deactivate(struct crypt_device *cd, const char *name); +/** @} */ /** - * Get volume key from of crypt device + * @defgroup crypt-key Volume Key manipulation + * @addtogroup crypt-key + * @{ + */ + +/** + * Get volume key from crypt device. * * @param cd crypt device handle * @param keyslot use this keyslot or @e CRYPT_ANY_SLOT @@ -881,8 +1387,9 @@ int crypt_deactivate(struct crypt_device *cd, const char *name); * * @return unlocked key slot number or negative errno otherwise. * - * @note For TCRYPT cipher chain is the volume key concatenated + * @note For TCRYPT cipher chain is the volume key concatenated * for all ciphers in chain. + * @note For VERITY the volume key means root hash used for activation. */ int crypt_volume_key_get(struct crypt_device *cd, int keyslot, @@ -892,7 +1399,7 @@ int crypt_volume_key_get(struct crypt_device *cd, size_t passphrase_size); /** - * Verify that provided volume key is valid for crypt device + * Verify that provided volume key is valid for crypt device. * * @param cd crypt device handle * @param volume_key provided volume key @@ -903,10 +1410,11 @@ int crypt_volume_key_get(struct crypt_device *cd, int crypt_volume_key_verify(struct crypt_device *cd, const char *volume_key, size_t volume_key_size); +/** @} */ /** - * @defgroup devstat Crypt and Verity device status - * @addtogroup devstat + * @defgroup crypt-devstat Crypt and Verity device status + * @addtogroup crypt-devstat * @{ */ @@ -914,14 +1422,14 @@ int crypt_volume_key_verify(struct crypt_device *cd, * Device status */ typedef enum { - CRYPT_INVALID, /**< device mapping is invalid in this context */ + CRYPT_INVALID, /**< device mapping is invalid in this context */ CRYPT_INACTIVE, /**< no such mapped device */ - CRYPT_ACTIVE, /**< device is active */ - CRYPT_BUSY /**< device is active and has open count > 0 */ + CRYPT_ACTIVE, /**< device is active */ + CRYPT_BUSY /**< device is active and has open count > 0 */ } crypt_status_info; /** - * Get status info about device name + * Get status info about device name. * * @param cd crypt device handle, can be @e NULL * @param name crypt device name @@ -932,7 +1440,7 @@ typedef enum { crypt_status_info crypt_status(struct crypt_device *cd, const char *name); /** - * Dump text-formatted information about crypt or verity device to log output + * Dump text-formatted information about crypt or verity device to log output. * * @param cd crypt device handle * @@ -941,7 +1449,7 @@ crypt_status_info crypt_status(struct crypt_device *cd, const char *name); int crypt_dump(struct crypt_device *cd); /** - * Get cipher used in device + * Get cipher used in device. * * @param cd crypt device handle * @@ -951,7 +1459,7 @@ int crypt_dump(struct crypt_device *cd); const char *crypt_get_cipher(struct crypt_device *cd); /** - * Get cipher mode used in device + * Get cipher mode used in device. * * @param cd crypt device handle * @@ -961,7 +1469,7 @@ const char *crypt_get_cipher(struct crypt_device *cd); const char *crypt_get_cipher_mode(struct crypt_device *cd); /** - * Get device UUID + * Get device UUID. * * @param cd crypt device handle * @@ -971,7 +1479,7 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd); const char *crypt_get_uuid(struct crypt_device *cd); /** - * Get path to underlaying device + * Get path to underlaying device. * * @param cd crypt device handle * @@ -981,7 +1489,17 @@ const char *crypt_get_uuid(struct crypt_device *cd); const char *crypt_get_device_name(struct crypt_device *cd); /** - * Get device offset in sectors where real data starts on underlying device) + * Get path to detached metadata device or @e NULL if it is not detached. + * + * @param cd crypt device handle + * + * @return path to underlaying device name + * + */ +const char *crypt_get_metadata_device_name(struct crypt_device *cd); + +/** + * Get device offset in 512-bytes sectors where real data starts (on underlying device). * * @param cd crypt device handle * @@ -991,7 +1509,7 @@ const char *crypt_get_device_name(struct crypt_device *cd); uint64_t crypt_get_data_offset(struct crypt_device *cd); /** - * Get IV offset in sectors (skip) + * Get IV offset in 512-bytes sectors (skip). * * @param cd crypt device handle * @@ -1001,17 +1519,29 @@ uint64_t crypt_get_data_offset(struct crypt_device *cd); uint64_t crypt_get_iv_offset(struct crypt_device *cd); /** - * Get size (in bytes) of volume key for crypt device + * Get size (in bytes) of volume key for crypt device. * * @param cd crypt device handle * * @return volume key size * + * @note For LUKS2, this function can be used only if there is at least + * one keyslot assigned to data segment. */ int crypt_get_volume_key_size(struct crypt_device *cd); /** - * Get device parameters for VERITY device + * Get size (in bytes) of encryption sector for crypt device. + * + * @param cd crypt device handle + * + * @return sector size + * + */ +int crypt_get_sector_size(struct crypt_device *cd); + +/** + * Get device parameters for VERITY device. * * @param cd crypt device handle * @param vp verity device info @@ -1021,20 +1551,29 @@ int crypt_get_volume_key_size(struct crypt_device *cd); */ int crypt_get_verity_info(struct crypt_device *cd, struct crypt_params_verity *vp); -/** @} */ /** - * @defgroup benchmark Benchmarking + * Get device parameters for INTEGRITY device. * - * Benchmarking of algorithms + * @param cd crypt device handle + * @param ip verity device info * - * @addtogroup benchmark - * @{ + * @e 0 on success or negative errno value otherwise. * */ +int crypt_get_integrity_info(struct crypt_device *cd, + struct crypt_params_integrity *ip); +/** @} */ /** - * Informational benchmark for ciphers + * @defgroup crypt-benchmark Benchmarking + * Benchmarking of algorithms + * @addtogroup crypt-benchmark + * @{ + */ + +/** + * Informational benchmark for ciphers. * * @param cd crypt device handle * @param cipher (e.g. "aes") @@ -1060,49 +1599,51 @@ int crypt_benchmark(struct crypt_device *cd, double *decryption_mbs); /** - * Informational benchmark for KDF + * Informational benchmark for PBKDF. * * @param cd crypt device handle - * @param kdf Key derivation function (e.g. "pbkdf2") - * @param hash Hash algorithm used in KDF (e.g. "sha256") + * @param pbkdf PBKDF parameters * @param password password for benchmark * @param password_size size of password * @param salt salt for benchmark * @param salt_size size of salt - * @param iterations_sec returns measured KDF iterations per second + * @param volume_key_size output volume key size + * @param progress callback function + * @param usrptr provided identification in callback * * @return @e 0 on success or negative errno value otherwise. */ -int crypt_benchmark_kdf(struct crypt_device *cd, - const char *kdf, - const char *hash, +int crypt_benchmark_pbkdf(struct crypt_device *cd, + struct crypt_pbkdf_type *pbkdf, const char *password, size_t password_size, const char *salt, size_t salt_size, - uint64_t *iterations_sec); + size_t volume_key_size, + int (*progress)(uint32_t time_ms, void *usrptr), + void *usrptr); /** @} */ /** - * @addtogroup keyslot + * @addtogroup crypt-keyslot * @{ - * */ /** * Crypt keyslot info */ typedef enum { - CRYPT_SLOT_INVALID, /**< invalid keyslot */ - CRYPT_SLOT_INACTIVE, /**< keyslot is inactive (free) */ - CRYPT_SLOT_ACTIVE, /**< keyslot is active (used) */ - CRYPT_SLOT_ACTIVE_LAST /**< keylost is active (used) - * and last used at the same time */ + CRYPT_SLOT_INVALID, /**< invalid keyslot */ + CRYPT_SLOT_INACTIVE, /**< keyslot is inactive (free) */ + CRYPT_SLOT_ACTIVE, /**< keyslot is active (used) */ + CRYPT_SLOT_ACTIVE_LAST,/**< keylost is active (used) + * and last used at the same time */ + CRYPT_SLOT_UNBOUND /**< keyslot is active and not bound + * to any crypt segment (LUKS2 only) */ } crypt_keyslot_info; /** - * Get information about particular key slot - * + * Get information about particular key slot. * * @param cd crypt device handle * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT @@ -1111,7 +1652,37 @@ typedef enum { * */ crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot); -/** @} */ + +/** + * Crypt keyslot priority + */ +typedef enum { + CRYPT_SLOT_PRIORITY_INVALID =-1, /**< no such slot */ + CRYPT_SLOT_PRIORITY_IGNORE = 0, /**< CRYPT_ANY_SLOT will ignore it for open */ + CRYPT_SLOT_PRIORITY_NORMAL = 1, /**< default priority, tried after preferred */ + CRYPT_SLOT_PRIORITY_PREFER = 2, /**< will try to open first */ +} crypt_keyslot_priority; + +/** + * Get keyslot priority (LUKS2) + * + * @param cd crypt device handle + * @param keyslot keyslot number + * + * @return value defined by crypt_keyslot_priority + */ +crypt_keyslot_priority crypt_keyslot_get_priority(struct crypt_device *cd, int keyslot); + +/** + * Set keyslot priority (LUKS2) + * + * @param cd crypt device handle + * @param keyslot keyslot number + * @param priority priority defined in crypt_keyslot_priority + * + * @return @e 0 on success or negative errno value otherwise. + */ +int crypt_keyslot_set_priority(struct crypt_device *cd, int keyslot, crypt_keyslot_priority priority); /** * Get number of keyslots supported for device type. @@ -1124,7 +1695,7 @@ crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot); int crypt_keyslot_max(const char *type); /** - * Get keyslot area pointers (relative to metadata device) + * Get keyslot area pointers (relative to metadata device). * * @param cd crypt device handle * @param keyslot keyslot number @@ -1140,56 +1711,60 @@ int crypt_keyslot_area(struct crypt_device *cd, uint64_t *length); /** - * Backup header and keyslots to file + * Get size (in bytes) of stored key in particular keyslot. + * Use for LUKS2 unbound keyslots, for other keyslots it is the same as @ref crypt_get_volume_key_size * * @param cd crypt device handle - * @param requested_type @link crypt_type @endlink or @e NULL for all known - * @param backup_file file to backup header to + * @param keyslot keyslot number * - * @return @e 0 on success or negative errno value otherwise. + * @return volume key size or negative errno value otherwise. * */ -int crypt_header_backup(struct crypt_device *cd, - const char *requested_type, - const char *backup_file); +int crypt_keyslot_get_key_size(struct crypt_device *cd, int keyslot); /** - * Restore header and keyslots from backup file - * + * Get cipher and key size for keyslot encryption. + * Use for LUKS2 keyslot to set different encryption type than for data encryption. + * Parameters will be used for next keyslot operations. * * @param cd crypt device handle - * @param requested_type @link crypt_type @endlink or @e NULL for all known - * @param backup_file file to restore header from + * @param keyslot keyslot number of CRYPT_ANY_SLOT for default + * @param key_size encryption key size (in bytes) * - * @return @e 0 on success or negative errno value otherwise. + * @return cipher specification on success or @e NULL. * + * @note This is the encryption of keyslot itself, not the data encryption algorithm! */ -int crypt_header_restore(struct crypt_device *cd, - const char *requested_type, - const char *backup_file); +const char *crypt_keyslot_get_encryption(struct crypt_device *cd, int keyslot, size_t *key_size); /** - * Receives last reported error + * Get PBKDF parameters for keyslot. * * @param cd crypt device handle - * @param buf buffef for message - * @param size size of buffer + * @param keyslot keyslot number + * @param pbkdf struct with returned PBKDF parameters * - * @note Note that this is old API function using global context. - * All error messages are reported also through log callback. + * @return @e 0 on success or negative errno value otherwise. */ -void crypt_last_error(struct crypt_device *cd, char *buf, size_t size); +int crypt_keyslot_get_pbkdf(struct crypt_device *cd, int keyslot, struct crypt_pbkdf_type *pbkdf); /** - * Receives last reported error, DEPRECATED + * Set encryption for keyslot. + * Use for LUKS2 keyslot to set different encryption type than for data encryption. + * Parameters will be used for next keyslot operations that create or change a keyslot. + * + * @param cd crypt device handle + * @param cipher (e.g. "aes-xts-plain64") + * @param key_size encryption key size (in bytes) * - * @param buf buffef for message - * @param size size of buffer + * @return @e 0 on success or negative errno value otherwise. * - * @note Note that this is old API function using global context. - * All error messages are reported also through log callback. + * @note To reset to default keyslot encryption (the same as for data) + * set cipher to NULL and key size to 0. */ -void crypt_get_error(char *buf, size_t size); +int crypt_keyslot_set_encryption(struct crypt_device *cd, + const char *cipher, + size_t key_size); /** * Get directory where mapped crypt devices are created @@ -1198,17 +1773,53 @@ void crypt_get_error(char *buf, size_t size); */ const char *crypt_get_dir(void); +/** @} */ + +/** + * @defgroup crypt-backup Device metadata backup + * @addtogroup crypt-backup + * @{ + */ +/** + * Backup header and keyslots to file. + * + * @param cd crypt device handle + * @param requested_type @link crypt-type @endlink or @e NULL for all known + * @param backup_file file to backup header to + * + * @return @e 0 on success or negative errno value otherwise. + * + */ +int crypt_header_backup(struct crypt_device *cd, + const char *requested_type, + const char *backup_file); + /** - * @defgroup dbg Library debug level + * Restore header and keyslots from backup file. * - * Set library debug level + * @param cd crypt device handle + * @param requested_type @link crypt-type @endlink or @e NULL for all known + * @param backup_file file to restore header from * - * @addtogroup dbg + * @return @e 0 on success or negative errno value otherwise. + * + */ +int crypt_header_restore(struct crypt_device *cd, + const char *requested_type, + const char *backup_file); +/** @} */ + +/** + * @defgroup crypt-dbg Library debug level + * Set library debug level + * @addtogroup crypt-dbg * @{ */ /** Debug all */ #define CRYPT_DEBUG_ALL -1 +/** Debug all with additional JSON dump (for LUKS2) */ +#define CRYPT_DEBUG_JSON -2 /** Debug none */ #define CRYPT_DEBUG_NONE 0 @@ -1219,6 +1830,539 @@ const char *crypt_get_dir(void); * */ void crypt_set_debug_level(int level); +/** @} */ + +/** + * @defgroup crypt-keyfile Function to read keyfile + * @addtogroup crypt-keyfile + * @{ + */ + +/** + * Read keyfile + * + * @param cd crypt device handle + * @param keyfile keyfile to read + * @param key buffer for key + * @param key_size_read size of read key + * @param keyfile_offset key offset in keyfile + * @param key_size exact key length to read from file or 0 + * @param flags keyfile read flags + * + * @return @e 0 on success or negative errno value otherwise. + * + * @note If key_size is set to zero we read internal max length + * and actual size read is returned via key_size_read parameter. + */ +int crypt_keyfile_device_read(struct crypt_device *cd, + const char *keyfile, + char **key, size_t *key_size_read, + uint64_t keyfile_offset, + size_t key_size, + uint32_t flags); + +/** + * Backward compatible crypt_keyfile_device_read() (with size_t offset). + */ +int crypt_keyfile_read(struct crypt_device *cd, + const char *keyfile, + char **key, size_t *key_size_read, + size_t keyfile_offset, + size_t key_size, + uint32_t flags); + +/** Read key only to the first end of line (\\n). */ +#define CRYPT_KEYFILE_STOP_EOL (1 << 0) +/** @} */ + +/** + * @defgroup crypt-wipe Function to wipe device + * @addtogroup crypt-wipe + * @{ + */ +/** + * Wipe pattern + */ +typedef enum { + CRYPT_WIPE_ZERO, /**< Fill with zeroes */ + CRYPT_WIPE_RANDOM, /**< Use RNG to fill data */ + CRYPT_WIPE_ENCRYPTED_ZERO, /**< Add encryption and fill with zeroes as plaintext */ + CRYPT_WIPE_SPECIAL, /**< Compatibility only, do not use (Gutmann method) */ +} crypt_wipe_pattern; + +/** + * Wipe/Fill (part of) a device with the selected pattern. + * + * @param cd crypt device handle + * @param dev_path path to device to wipe or @e NULL if data device should be used + * @param pattern selected wipe pattern + * @param offset offset on device (in bytes) + * @param length length of area to be wiped (in bytes) + * @param wipe_block_size used block for wiping (one step) (in bytes) + * @param flags wipe flags + * @param progress callback function called after each @e wipe_block_size or @e NULL + * @param usrptr provided identification in callback + * + * @return @e 0 on success or negative errno value otherwise. + * + * @note A @e progress callback can interrupt wipe process by returning non-zero code. + * + * @note If the error values is -EIO or -EINTR, some part of the device could + * be overwritten. Other error codes (-EINVAL, -ENOMEM) means that no IO was performed. + */ +int crypt_wipe(struct crypt_device *cd, + const char *dev_path, /* if null, use data device */ + crypt_wipe_pattern pattern, + uint64_t offset, + uint64_t length, + size_t wipe_block_size, + uint32_t flags, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr), + void *usrptr +); + +/** Use direct-io */ +#define CRYPT_WIPE_NO_DIRECT_IO (1 << 0) +/** @} */ + +/** + * @defgroup crypt-tokens LUKS2 token wrapper access + * + * Utilities for handling tokens LUKS2 + * Token is a device or a method how to read password for particular keyslot + * automatically. It can be chunk of data stored on hardware token or + * just a metadata how to generate the password. + * + * @addtogroup crypt-tokens + * @{ + */ + +/** Iterate through all tokens */ +#define CRYPT_ANY_TOKEN -1 + +/** + * Get content of a token definition in JSON format. + * + * @param cd crypt device handle + * @param token token id + * @param json buffer with JSON + * + * @return allocated token id or negative errno otherwise. + */ +int crypt_token_json_get(struct crypt_device *cd, + int token, + const char **json); + +/** + * Store content of a token definition in JSON format. + * + * @param cd crypt device handle + * @param token token id or @e CRYPT_ANY_TOKEN to allocate new one + * @param json buffer with JSON or @e NULL to remove token + * + * @return allocated token id or negative errno otherwise. + * + * @note The buffer must be in proper JSON format and must contain at least + * string "type" with slot type and an array of string names "keyslots". + * Keyslots array contains assignments to particular slots and can be empty. + */ +int crypt_token_json_set(struct crypt_device *cd, + int token, + const char *json); + +/** + * Token info + */ +typedef enum { + CRYPT_TOKEN_INVALID, /**< token is invalid */ + CRYPT_TOKEN_INACTIVE, /**< token is empty (free) */ + CRYPT_TOKEN_INTERNAL, /**< active internal token with driver */ + CRYPT_TOKEN_INTERNAL_UNKNOWN, /**< active internal token (reserved name) with missing token driver */ + CRYPT_TOKEN_EXTERNAL, /**< active external (user defined) token with driver */ + CRYPT_TOKEN_EXTERNAL_UNKNOWN, /**< active external (user defined) token with missing token driver */ +} crypt_token_info; + +/** + * Get info for specific token. + * + * @param cd crypt device handle + * @param token existing token id + * @param type pointer for returned type string + * + * @return token status info. For any returned status (besides CRYPT_TOKEN_INVALID + * and CRYPT_TOKEN_INACTIVE) and if type parameter is not NULL it will + * contain address of type string. + * + * @note if required, create a copy of string referenced in *type before calling next + * libcryptsetup API function. The reference may become invalid. + */ +crypt_token_info crypt_token_status(struct crypt_device *cd, int token, const char **type); + +/** + * LUKS2 keyring token parameters. + * + * @see crypt_token_builtin_set + * + */ +struct crypt_token_params_luks2_keyring { + const char *key_description; /**< Reference in keyring */ +}; + +/** + * Create a new luks2 keyring token. + * + * @param cd crypt device handle + * @param token token id or @e CRYPT_ANY_TOKEN to allocate new one + * @param params luks2 keyring token params + * + * @return allocated token id or negative errno otherwise. + * + */ +int crypt_token_luks2_keyring_set(struct crypt_device *cd, + int token, + const struct crypt_token_params_luks2_keyring *params); + +/** + * Get LUKS2 keyring token params + * + * @param cd crypt device handle + * @param token existing luks2 keyring token id + * @param params returned luks2 keyring token params + * + * @return allocated token id or negative errno otherwise. + * + * @note do not call free() on params members. Members are valid only + * until next libcryptsetup function is called. + */ +int crypt_token_luks2_keyring_get(struct crypt_device *cd, + int token, + struct crypt_token_params_luks2_keyring *params); + +/** + * Assign a token to particular keyslot. + * (There can be more keyslots assigned to one token id.) + * + * @param cd crypt device handle + * @param token token id + * @param keyslot keyslot to be assigned to token (CRYPT_ANY SLOT + * assigns all active keyslots to token) + * + * @return allocated token id or negative errno otherwise. + */ +int crypt_token_assign_keyslot(struct crypt_device *cd, + int token, + int keyslot); + +/** + * Unassign a token from particular keyslot. + * (There can be more keyslots assigned to one token id.) + * + * @param cd crypt device handle + * @param token token id + * @param keyslot keyslot to be unassigned from token (CRYPT_ANY SLOT + * unassigns all active keyslots from token) + * + * @return allocated token id or negative errno otherwise. + */ +int crypt_token_unassign_keyslot(struct crypt_device *cd, + int token, + int keyslot); + +/** + * Get info about token assignment to particular keyslot. + * + * @param cd crypt device handle + * @param token token id + * @param keyslot keyslot + * + * @return 0 on success (token exists and is assigned to the keyslot), + * -ENOENT if token is not assigned to a keyslot (token, keyslot + * or both may be inactive) or other negative errno otherwise. + */ +int crypt_token_is_assigned(struct crypt_device *cd, + int token, + int keyslot); + +/** + * Token handler open function prototype. + * This function retrieves password from a token and return allocated buffer + * containing this password. This buffer has to be deallocated by calling + * free() function and content should be wiped before deallocation. + * + * @param cd crypt device handle + * @param token token id + * @param buffer returned allocated buffer with password + * @param buffer_len length of the buffer + * @param usrptr user data in @link crypt_activate_by_token @endlink + */ +typedef int (*crypt_token_open_func) ( + struct crypt_device *cd, + int token, + char **buffer, + size_t *buffer_len, + void *usrptr); + +/** + * Token handler buffer free function prototype. + * This function is used by library to free the buffer with keyslot + * passphrase when it's no longer needed. If not defined the library + * overwrites buffer with zeroes and call free(). + * + * @param buffer the buffer with keyslot passphrase + * @param buffer_len the buffer length + */ +typedef void (*crypt_token_buffer_free_func) (void *buffer, size_t buffer_len); + +/** + * Token handler validate function prototype. + * This function validates JSON representation of user defined token for additional data + * specific for its token type. If defined in the handler, it's called + * during @link crypt_activate_by_token @endlink. It may also be called during + * @link crypt_token_json_set @endlink when appropriate token handler was registered before + * with @link crypt_token_register @endlink. + * + * @param cd crypt device handle + * @param json buffer with JSON + */ +typedef int (*crypt_token_validate_func) (struct crypt_device *cd, const char *json); + +/** + * Token handler dump function prototype. + * This function is supposed to print token implementation specific details. It gets + * called during @link crypt_dump @endlink if token handler was registered before. + * + * @param cd crypt device handle + * @param json buffer with token JSON + * + * @note dump implementations are advised to use @link crypt_log @endlink function + * to dump token details. + */ +typedef void (*crypt_token_dump_func) (struct crypt_device *cd, const char *json); + +/** + * Token handler + */ +typedef struct { + const char *name; /**< token handler name */ + crypt_token_open_func open; /**< token handler open function */ + crypt_token_buffer_free_func buffer_free; /**< token handler buffer_free function (optional) */ + crypt_token_validate_func validate; /**< token handler validate function (optional) */ + crypt_token_dump_func dump; /**< token handler dump function (optional) */ +} crypt_token_handler; + +/** + * Register token handler + * + * @param handler token handler to register + * + * @return @e 0 on success or negative errno value otherwise. + */ +int crypt_token_register(const crypt_token_handler *handler); + +/** + * Activate device or check key using a token. + * + * @param cd crypt device handle + * @param name name of device to create, if @e NULL only check token + * @param token requested token to check or CRYPT_ANY_TOKEN to check all + * @param usrptr provided identification in callback + * @param flags activation flags + * + * @return unlocked key slot number or negative errno otherwise. + */ +int crypt_activate_by_token(struct crypt_device *cd, + const char *name, + int token, + void *usrptr, + uint32_t flags); +/** @} */ + +/** + * @defgroup crypt-reencryption LUKS2 volume reencryption support + * + * Set of functions to handling LUKS2 volume reencryption + * + * @addtogroup crypt-reencryption + * @{ + */ + +/** Initialize reencryption metadata but do not run reencryption yet. (in) */ +#define CRYPT_REENCRYPT_INITIALIZE_ONLY (1 << 0) +/** Move the first segment, used only with data shift. (in/out) */ +#define CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT (1 << 1) +/** Resume already initialized reencryption only. (in) */ +#define CRYPT_REENCRYPT_RESUME_ONLY (1 << 2) +/** Run reencryption recovery only. (in) */ +#define CRYPT_REENCRYPT_RECOVERY (1 << 3) + +/** + * Reencryption direction + */ +typedef enum { + CRYPT_REENCRYPT_FORWARD = 0, /**< forward direction */ + CRYPT_REENCRYPT_BACKWARD /**< backward direction */ +} crypt_reencrypt_direction_info; + +/** + * Reencryption mode + */ +typedef enum { + CRYPT_REENCRYPT_REENCRYPT = 0, /**< Reencryption mode */ + CRYPT_REENCRYPT_ENCRYPT, /**< Encryption mode */ + CRYPT_REENCRYPT_DECRYPT, /**< Decryption mode */ +} crypt_reencrypt_mode_info; + +/** + * LUKS2 reencryption options. + */ +struct crypt_params_reencrypt { + crypt_reencrypt_mode_info mode; /**< Reencryption mode, immutable after first init. */ + crypt_reencrypt_direction_info direction; /**< Reencryption direction, immutable after first init. */ + const char *resilience; /**< Resilience mode: "none", "checksum", "journal" or "shift" (only "shift" is immutable after init) */ + const char *hash; /**< Used hash for "checksum" resilience type, ignored otherwise. */ + uint64_t data_shift; /**< Used in "shift" mode, must be non-zero, immutable after first init. */ + uint64_t max_hotzone_size; /**< Exact hotzone size for "none" mode. Maximum hotzone size for "checksum" and "journal" modes. */ + uint64_t device_size; /**< Reencrypt only initial part of the data device. */ + const struct crypt_params_luks2 *luks2; /**< LUKS2 parameters for the final reencryption volume.*/ + uint32_t flags; /**< Reencryption flags. */ +}; + +/** + * Initialize reencryption metadata using passphrase. + * + * This function initializes on-disk metadata to include all reencryption segments, + * according to the provided options. + * If metadata already contains ongoing reencryption metadata, it loads these parameters + * (in this situation all parameters except @e name and @e passphrase can be omitted). + * + * @param cd crypt device handle + * @param name name of active device or @e NULL for offline reencryption + * @param passphrase passphrase used to unlock volume key + * @param passphrase_size size of @e passphrase (binary data) + * @param keyslot_old keyslot to unlock existing device or CRYPT_ANY_SLOT + * @param keyslot_new existing (unbound) reencryption keyslot; must be set except for decryption + * @param cipher cipher specification (e.g. "aes") + * @param cipher_mode cipher mode and IV (e.g. "xts-plain64") + * @param params reencryption parameters @link crypt_params_reencrypt @endlink. + * + * @return reencryption key slot number or negative errno otherwise. + */ +int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd, + const char *name, + const char *passphrase, + size_t passphrase_size, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params); + +/** + * Initialize reencryption metadata using passphrase in keyring. + * + * This function initializes on-disk metadata to include all reencryption segments, + * according to the provided options. + * If metadata already contains ongoing reencryption metadata, it loads these parameters + * (in this situation all parameters except @e name and @e key_description can be omitted). + * + * @param cd crypt device handle + * @param name name of active device or @e NULL for offline reencryption + * @param key_description passphrase (key) identification in keyring + * @param keyslot_old keyslot to unlock existing device or CRYPT_ANY_SLOT + * @param keyslot_new existing (unbound) reencryption keyslot; must be set except for decryption + * @param cipher cipher specification (e.g. "aes") + * @param cipher_mode cipher mode and IV (e.g. "xts-plain64") + * @param params reencryption parameters @link crypt_params_reencrypt @endlink. + * + * @return reencryption key slot number or negative errno otherwise. + */ +int crypt_reencrypt_init_by_keyring(struct crypt_device *cd, + const char *name, + const char *key_description, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params); + +/** + * Run data reencryption. + * + * @param cd crypt device handle + * @param progress is a callback funtion reporting device \b size, + * current \b offset of reencryption and provided \b usrptr identification + * + * @return @e 0 on success or negative errno value otherwise. + */ +int crypt_reencrypt(struct crypt_device *cd, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr)); + +/** + * Reencryption status info + */ +typedef enum { + CRYPT_REENCRYPT_NONE = 0, /**< No reencryption in progress */ + CRYPT_REENCRYPT_CLEAN, /**< Ongoing reencryption in a clean state. */ + CRYPT_REENCRYPT_CRASH, /**< Aborted reencryption that need internal recovery. */ + CRYPT_REENCRYPT_INVALID /**< Invalid state. */ +} crypt_reencrypt_info; + +/** + * LUKS2 reencryption status. + * + * @param cd crypt device handle + * @param params reencryption parameters + * + * @return reencryption status info and parameters. + */ +crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd, + struct crypt_params_reencrypt *params); +/** @} */ + +/** + * @defgroup crypt-memory Safe memory helpers functions + * @addtogroup crypt-memory + * @{ + */ + +/** + * Allocate safe memory (content is safely wiped on deallocation). + * + * @param size size of memory in bytes + * + * @return pointer to allocate memory or @e NULL. + */ +void *crypt_safe_alloc(size_t size); + +/** + * Release safe memory, content is safely wiped + * The pointer must be allocated with @link crypt_safe_alloc @endlink + * + * @param data pointer to memory to be deallocated + * + * @return pointer to allocate memory or @e NULL. + */ +void crypt_safe_free(void *data); + +/** + * Reallocate safe memory (content is copied and safely wiped on deallocation). + * + * @param data pointer to memory to be deallocated + * @param size new size of memory in bytes + * + * @return pointer to allocate memory or @e NULL. + */ +void *crypt_safe_realloc(void *data, size_t size); + +/** + * Safe clear memory area (compile should not compile this call out). + * + * @param data pointer to memory to cleared + * @param size new size of memory in bytes + * + * @return pointer to allocate memory or @e NULL. + */ +void crypt_safe_memzero(void *data, size_t size); /** @} */ diff --git a/lib/libcryptsetup.sym b/lib/libcryptsetup.sym index 27c5cb4..59a998c 100644 --- a/lib/libcryptsetup.sym +++ b/lib/libcryptsetup.sym @@ -1,21 +1,24 @@ -CRYPTSETUP_1.0 { +CRYPTSETUP_2.0 { global: crypt_init; + crypt_init_data_device; crypt_init_by_name; crypt_init_by_name_and_header; + crypt_set_log_callback; crypt_set_confirm_callback; - crypt_set_password_callback; - crypt_set_timeout; - crypt_set_password_retry; - crypt_set_iterarion_time; crypt_set_iteration_time; - crypt_set_password_verify; crypt_set_uuid; + crypt_set_label; crypt_set_data_device; + crypt_set_compatibility; + crypt_get_compatibility; + crypt_memory_lock; + crypt_metadata_locking; crypt_format; + crypt_convert; crypt_load; crypt_repair; crypt_resize; @@ -23,51 +26,108 @@ CRYPTSETUP_1.0 { crypt_resume_by_passphrase; crypt_resume_by_keyfile; crypt_resume_by_keyfile_offset; + crypt_resume_by_keyfile_device_offset; + crypt_resume_by_volume_key; crypt_free; crypt_keyslot_add_by_passphrase; crypt_keyslot_change_by_passphrase; crypt_keyslot_add_by_keyfile; crypt_keyslot_add_by_keyfile_offset; + crypt_keyslot_add_by_keyfile_device_offset; crypt_keyslot_add_by_volume_key; + crypt_keyslot_add_by_key; + + crypt_keyslot_set_priority; + crypt_keyslot_get_priority; + + crypt_token_json_get; + crypt_token_json_set; + crypt_token_status; + crypt_token_luks2_keyring_get; + crypt_token_luks2_keyring_set; + crypt_token_assign_keyslot; + crypt_token_unassign_keyslot; + crypt_token_is_assigned; + crypt_token_register; + + crypt_activate_by_token; + crypt_keyslot_destroy; crypt_activate_by_passphrase; crypt_activate_by_keyfile; crypt_activate_by_keyfile_offset; + crypt_activate_by_keyfile_device_offset; crypt_activate_by_volume_key; + crypt_activate_by_signed_key; + crypt_activate_by_keyring; crypt_deactivate; + crypt_deactivate_by_name; crypt_volume_key_get; crypt_volume_key_verify; + crypt_volume_key_keyring; crypt_status; crypt_dump; crypt_benchmark; - crypt_benchmark_kdf; + crypt_benchmark_pbkdf; crypt_get_cipher; crypt_get_cipher_mode; + crypt_get_integrity_info; crypt_get_uuid; + crypt_set_data_offset; crypt_get_data_offset; crypt_get_iv_offset; crypt_get_volume_key_size; crypt_get_device_name; + crypt_get_metadata_device_name; + crypt_get_metadata_size; + crypt_set_metadata_size; crypt_get_verity_info; + crypt_get_sector_size; crypt_get_type; + crypt_get_default_type; crypt_get_active_device; + crypt_get_active_integrity_failures; + crypt_persistent_flags_set; + crypt_persistent_flags_get; crypt_set_rng_type; crypt_get_rng_type; + crypt_set_pbkdf_type; + crypt_get_pbkdf_type; + crypt_get_pbkdf_type_params; + crypt_get_pbkdf_default; crypt_keyslot_max; crypt_keyslot_area; crypt_keyslot_status; - crypt_last_error; - crypt_get_error; + crypt_keyslot_get_key_size; + crypt_keyslot_set_encryption; + crypt_keyslot_get_encryption; + crypt_keyslot_get_pbkdf; + crypt_get_dir; crypt_set_debug_level; crypt_log; crypt_header_backup; crypt_header_restore; + + crypt_keyfile_read; + crypt_keyfile_device_read; + + crypt_wipe; + + crypt_reencrypt_init_by_passphrase; + crypt_reencrypt_init_by_keyring; + crypt_reencrypt; + crypt_reencrypt_status; + + crypt_safe_alloc; + crypt_safe_realloc; + crypt_safe_free; + crypt_safe_memzero; local: *; }; diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 316fa5f..a82163b 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -1,10 +1,10 @@ /* * libdevmapper - device-mapper backend for cryptsetup * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2015, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,26 +22,41 @@ */ #include +#include +#include #include #include #include -#include #include #include +#include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif #include "internal.h" #define DM_UUID_LEN 129 +#define DM_BY_ID_PREFIX "dm-uuid-" +#define DM_BY_ID_PREFIX_LEN 8 #define DM_UUID_PREFIX "CRYPT-" #define DM_UUID_PREFIX_LEN 6 #define DM_CRYPT_TARGET "crypt" #define DM_VERITY_TARGET "verity" +#define DM_INTEGRITY_TARGET "integrity" +#define DM_LINEAR_TARGET "linear" +#define DM_ERROR_TARGET "error" +#define DM_ZERO_TARGET "zero" #define RETRY_COUNT 5 -/* Set if dm-crypt version was probed */ -static int _dm_crypt_checked = 0; +/* Set if DM target versions were probed */ +static bool _dm_ioctl_checked = false; +static bool _dm_crypt_checked = false; +static bool _dm_verity_checked = false; +static bool _dm_integrity_checked = false; + static int _quiet_log = 0; -static uint32_t _dm_crypt_flags = 0; +static uint32_t _dm_flags = 0; static struct crypt_device *_context = NULL; static int _dm_use_count = 0; @@ -86,96 +101,194 @@ static void set_dm_error(int level, if (vasprintf(&msg, f, va) > 0) { if (level < 4 && !_quiet_log) { log_err(_context, "%s", msg); - log_err(_context, "\n"); } else { /* We do not use DM visual stack backtrace here */ if (strncmp(msg, "", 11)) - log_dbg("%s", msg); + log_dbg(_context, "%s", msg); } } free(msg); va_end(va); } -static int _dm_simple(int task, const char *name, int udev_wait); - -static int _dm_satisfies_version(unsigned target_maj, unsigned target_min, - unsigned actual_maj, unsigned actual_min) +static int _dm_satisfies_version(unsigned target_maj, unsigned target_min, unsigned target_patch, + unsigned actual_maj, unsigned actual_min, unsigned actual_patch) { if (actual_maj > target_maj) return 1; - if (actual_maj == target_maj && actual_min >= target_min) + if (actual_maj == target_maj && actual_min > target_min) + return 1; + + if (actual_maj == target_maj && actual_min == target_min && actual_patch >= target_patch) return 1; return 0; } -static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj, - unsigned crypt_min, unsigned crypt_patch) +static void _dm_set_crypt_compat(struct crypt_device *cd, + unsigned crypt_maj, + unsigned crypt_min, + unsigned crypt_patch) { - unsigned dm_maj, dm_min, dm_patch; + if (_dm_crypt_checked || crypt_maj == 0) + return; - if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3) - dm_maj = dm_min = dm_patch = 0; + log_dbg(cd, "Detected dm-crypt version %i.%i.%i.", + crypt_maj, crypt_min, crypt_patch); - log_dbg("Detected dm-crypt version %i.%i.%i, dm-ioctl version %u.%u.%u.", - crypt_maj, crypt_min, crypt_patch, dm_maj, dm_min, dm_patch); - - if (_dm_satisfies_version(1, 2, crypt_maj, crypt_min)) - _dm_crypt_flags |= DM_KEY_WIPE_SUPPORTED; + if (_dm_satisfies_version(1, 2, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_KEY_WIPE_SUPPORTED; else - log_dbg("Suspend and resume disabled, no wipe key support."); - - if (_dm_satisfies_version(1, 10, crypt_maj, crypt_min)) - _dm_crypt_flags |= DM_LMK_SUPPORTED; + log_dbg(cd, "Suspend and resume disabled, no wipe key support."); - if (_dm_satisfies_version(4, 20, dm_maj, dm_min)) - _dm_crypt_flags |= DM_SECURE_SUPPORTED; + if (_dm_satisfies_version(1, 10, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_LMK_SUPPORTED; /* not perfect, 2.6.33 supports with 1.7.0 */ - if (_dm_satisfies_version(1, 8, crypt_maj, crypt_min)) - _dm_crypt_flags |= DM_PLAIN64_SUPPORTED; + if (_dm_satisfies_version(1, 8, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_PLAIN64_SUPPORTED; - if (_dm_satisfies_version(1, 11, crypt_maj, crypt_min)) - _dm_crypt_flags |= DM_DISCARDS_SUPPORTED; + if (_dm_satisfies_version(1, 11, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_DISCARDS_SUPPORTED; - if (_dm_satisfies_version(1, 13, crypt_maj, crypt_min)) - _dm_crypt_flags |= DM_TCW_SUPPORTED; + if (_dm_satisfies_version(1, 13, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_TCW_SUPPORTED; - if (_dm_satisfies_version(1, 14, crypt_maj, crypt_min)) { - _dm_crypt_flags |= DM_SAME_CPU_CRYPT_SUPPORTED; - _dm_crypt_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED; + if (_dm_satisfies_version(1, 14, 0, crypt_maj, crypt_min, crypt_patch)) { + _dm_flags |= DM_SAME_CPU_CRYPT_SUPPORTED; + _dm_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED; } - /* Repeat test if dm-crypt is not present */ - if (crypt_maj > 0) - _dm_crypt_checked = 1; + if (_dm_satisfies_version(1, 18, 1, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_KERNEL_KEYRING_SUPPORTED; + + if (_dm_satisfies_version(1, 17, 0, crypt_maj, crypt_min, crypt_patch)) { + _dm_flags |= DM_SECTOR_SIZE_SUPPORTED; + _dm_flags |= DM_CAPI_STRING_SUPPORTED; + } + + if (_dm_satisfies_version(1, 19, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_BITLK_EBOIV_SUPPORTED; + + if (_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch)) + _dm_flags |= DM_BITLK_ELEPHANT_SUPPORTED; + + _dm_crypt_checked = true; } -static void _dm_set_verity_compat(const char *dm_version, unsigned verity_maj, - unsigned verity_min, unsigned verity_patch) +static void _dm_set_verity_compat(struct crypt_device *cd, + unsigned verity_maj, + unsigned verity_min, + unsigned verity_patch) { - if (verity_maj > 0) - _dm_crypt_flags |= DM_VERITY_SUPPORTED; + if (_dm_verity_checked || verity_maj == 0) + return; - log_dbg("Detected dm-verity version %i.%i.%i.", + log_dbg(cd, "Detected dm-verity version %i.%i.%i.", verity_maj, verity_min, verity_patch); + + _dm_flags |= DM_VERITY_SUPPORTED; + + /* + * ignore_corruption, restart_on corruption is available since 1.2 (kernel 4.1) + * ignore_zero_blocks since 1.3 (kernel 4.5) + * (but some dm-verity targets 1.2 don't support it) + * FEC is added in 1.3 as well. + * Check at most once is added in 1.4 (kernel 4.17). + */ + if (_dm_satisfies_version(1, 3, 0, verity_maj, verity_min, verity_patch)) { + _dm_flags |= DM_VERITY_ON_CORRUPTION_SUPPORTED; + _dm_flags |= DM_VERITY_FEC_SUPPORTED; + } + + if (_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch)) + _dm_flags |= DM_VERITY_SIGNATURE_SUPPORTED; + + _dm_verity_checked = true; +} + +static void _dm_set_integrity_compat(struct crypt_device *cd, + unsigned integrity_maj, + unsigned integrity_min, + unsigned integrity_patch) +{ + if (_dm_integrity_checked || integrity_maj == 0) + return; + + log_dbg(cd, "Detected dm-integrity version %i.%i.%i.", + integrity_maj, integrity_min, integrity_patch); + + _dm_flags |= DM_INTEGRITY_SUPPORTED; + + if (_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch)) + _dm_flags |= DM_INTEGRITY_RECALC_SUPPORTED; + + if (_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch)) + _dm_flags |= DM_INTEGRITY_BITMAP_SUPPORTED; + + if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch)) + _dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED; + + if (_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch)) + _dm_flags |= DM_INTEGRITY_DISCARDS_SUPPORTED; + + _dm_integrity_checked = true; +} + +/* We use this for loading target module */ +static void _dm_check_target(dm_target_type target_type) +{ +#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION + struct dm_task *dmt; + const char *target_name = NULL; + + if (!(_dm_flags & DM_GET_TARGET_VERSION_SUPPORTED)) + return; + + if (target_type == DM_CRYPT) + target_name = DM_CRYPT_TARGET; + else if (target_type == DM_VERITY) + target_name = DM_VERITY_TARGET; + else if (target_type == DM_INTEGRITY) + target_name = DM_INTEGRITY_TARGET; + else + return; + + if (!(dmt = dm_task_create(DM_DEVICE_GET_TARGET_VERSION))) + goto out; + + if (!dm_task_set_name(dmt, target_name)) + goto out; + + if (!dm_task_run(dmt)) + goto out; +out: + if (dmt) + dm_task_destroy(dmt); +#endif } -static int _dm_check_versions(void) +static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_type) { struct dm_task *dmt; struct dm_versions *target, *last_target; char dm_version[16]; + unsigned dm_maj, dm_min, dm_patch; int r = 0; - if (_dm_crypt_checked) + if ((target_type == DM_CRYPT && _dm_crypt_checked) || + (target_type == DM_VERITY && _dm_verity_checked) || + (target_type == DM_INTEGRITY && _dm_integrity_checked) || + (target_type == DM_LINEAR) || (target_type == DM_ZERO) || + (_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked)) return 1; /* Shut up DM while checking */ _quiet_log = 1; + _dm_check_target(target_type); + /* FIXME: add support to DM so it forces crypt target module load here */ if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) goto out; @@ -186,26 +299,48 @@ static int _dm_check_versions(void) if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version))) goto out; + if (!_dm_ioctl_checked) { + if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3) + goto out; + log_dbg(cd, "Detected dm-ioctl version %u.%u.%u.", dm_maj, dm_min, dm_patch); + + if (_dm_satisfies_version(4, 20, 0, dm_maj, dm_min, dm_patch)) + _dm_flags |= DM_SECURE_SUPPORTED; +#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE + if (_dm_satisfies_version(4, 27, 0, dm_maj, dm_min, dm_patch)) + _dm_flags |= DM_DEFERRED_SUPPORTED; +#endif +#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION + if (_dm_satisfies_version(4, 41, 0, dm_maj, dm_min, dm_patch)) + _dm_flags |= DM_GET_TARGET_VERSION_SUPPORTED; +#endif + } + target = dm_task_get_versions(dmt); do { last_target = target; if (!strcmp(DM_CRYPT_TARGET, target->name)) { - _dm_set_crypt_compat(dm_version, - (unsigned)target->version[0], + _dm_set_crypt_compat(cd, (unsigned)target->version[0], (unsigned)target->version[1], (unsigned)target->version[2]); } else if (!strcmp(DM_VERITY_TARGET, target->name)) { - _dm_set_verity_compat(dm_version, - (unsigned)target->version[0], - (unsigned)target->version[1], - (unsigned)target->version[2]); + _dm_set_verity_compat(cd, (unsigned)target->version[0], + (unsigned)target->version[1], + (unsigned)target->version[2]); + } else if (!strcmp(DM_INTEGRITY_TARGET, target->name)) { + _dm_set_integrity_compat(cd, (unsigned)target->version[0], + (unsigned)target->version[1], + (unsigned)target->version[2]); } target = (struct dm_versions *)((char *) target + target->next); } while (last_target != target); r = 1; - log_dbg("Device-mapper backend running with UDEV support %sabled.", - _dm_use_udev() ? "en" : "dis"); + if (!_dm_ioctl_checked) + log_dbg(cd, "Device-mapper backend running with UDEV support %sabled.", + _dm_use_udev() ? "en" : "dis"); + + _dm_ioctl_checked = true; out: if (dmt) dm_task_destroy(dmt); @@ -214,26 +349,38 @@ out: return r; } -uint32_t dm_flags(void) +int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags) { - _dm_check_versions(); - return _dm_crypt_flags; + _dm_check_versions(cd, target); + *flags = _dm_flags; + + if (target == DM_UNKNOWN && + _dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked) + return 0; + + if ((target == DM_CRYPT && _dm_crypt_checked) || + (target == DM_VERITY && _dm_verity_checked) || + (target == DM_INTEGRITY && _dm_integrity_checked) || + (target == DM_LINEAR) || (target == DM_ZERO)) /* nothing to check */ + return 0; + + return -ENODEV; } /* This doesn't run any kernel checks, just set up userspace libdevmapper */ -void dm_backend_init(void) +void dm_backend_init(struct crypt_device *cd) { if (!_dm_use_count++) { - log_dbg("Initialising device-mapper backend library."); + log_dbg(cd, "Initialising device-mapper backend library."); dm_log_init(set_dm_error); dm_log_init_verbose(10); } } -void dm_backend_exit(void) +void dm_backend_exit(struct crypt_device *cd) { if (_dm_use_count && (!--_dm_use_count)) { - log_dbg("Releasing device-mapper backend."); + log_dbg(cd, "Releasing device-mapper backend."); dm_log_init_verbose(0); dm_log_init(NULL); dm_lib_release(); @@ -244,16 +391,16 @@ void dm_backend_exit(void) * libdevmapper is not context friendly, switch context on every DM call. * FIXME: this is not safe if called in parallel but neither is DM lib. */ -static int dm_init_context(struct crypt_device *cd) +static int dm_init_context(struct crypt_device *cd, dm_target_type target) { _context = cd; - if (!_dm_check_versions()) { + if (!_dm_check_versions(cd, target)) { if (getuid() || geteuid()) log_err(cd, _("Cannot initialize device-mapper, " - "running as non-root user.\n")); + "running as non-root user.")); else log_err(cd, _("Cannot initialize device-mapper. " - "Is dm_mod kernel module loaded?\n")); + "Is dm_mod kernel module loaded?")); _context = NULL; return -ENOTSUP; } @@ -275,6 +422,7 @@ char *dm_device_path(const char *prefix, int major, int minor) return NULL; if (!dm_task_set_minor(dmt, minor) || !dm_task_set_major(dmt, major) || + !dm_task_no_flush(dmt) || !dm_task_run(dmt) || !(name = dm_task_get_name(dmt))) { dm_task_destroy(dmt); @@ -289,6 +437,16 @@ char *dm_device_path(const char *prefix, int major, int minor) return strdup(path); } +char *dm_device_name(const char *path) +{ + struct stat st; + + if (stat(path, &st) < 0 || !S_ISBLK(st.st_mode)) + return NULL; + + return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev)); +} + static void hex_key(char *hexkey, size_t key_size, const char *key) { unsigned i; @@ -297,14 +455,158 @@ static void hex_key(char *hexkey, size_t key_size, const char *key) sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]); } +static size_t int_log10(uint64_t x) +{ + uint64_t r = 0; + for (x /= 10; x > 0; x /= 10) + r++; + return r; +} + +#define CLEN 64 /* 2*MAX_CIPHER_LEN */ +#define CLENS "63" /* for sscanf length + '\0' */ +#define CAPIL 144 /* should be enough to fit whole capi string */ +#define CAPIS "143" /* for sscanf of crypto API string + 16 + \0 */ + +static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size, + char *c_dm, int c_dm_size, + char *i_dm, int i_dm_size) +{ + int c_size = 0, i_size = 0, i; + char cipher[CLEN], mode[CLEN], iv[CLEN+1], tmp[CLEN]; + char capi[CAPIL]; + + if (!c_dm || !c_dm_size || !i_dm || !i_dm_size) + return -EINVAL; + + i = sscanf(org_c, "%" CLENS "[^-]-%" CLENS "s", cipher, tmp); + if (i != 2) + return -EINVAL; + + i = sscanf(tmp, "%" CLENS "[^-]-%" CLENS "s", mode, iv); + if (i == 1) { + memset(iv, 0, sizeof(iv)); + strncpy(iv, mode, sizeof(iv)-1); + *mode = '\0'; + if (snprintf(capi, sizeof(capi), "%s", cipher) < 0) + return -EINVAL; + } else if (i == 2) { + if (snprintf(capi, sizeof(capi), "%s(%s)", mode, cipher) < 0) + return -EINVAL; + } else + return -EINVAL; + + if (!org_i) { + /* legacy mode: CIPHER-MODE-IV*/ + i_size = snprintf(i_dm, i_dm_size, "%s", ""); + c_size = snprintf(c_dm, c_dm_size, "%s", org_c); + } else if (!strcmp(org_i, "none")) { + /* IV only: capi:MODE(CIPHER)-IV */ + i_size = snprintf(i_dm, i_dm_size, " integrity:%u:none", tag_size); + c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv); + } else if (!strcmp(org_i, "aead") && !strcmp(mode, "ccm")) { + /* CCM AEAD: capi:rfc4309(MODE(CIPHER))-IV */ + i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size); + c_size = snprintf(c_dm, c_dm_size, "capi:rfc4309(%s)-%s", capi, iv); + } else if (!strcmp(org_i, "aead")) { + /* AEAD: capi:MODE(CIPHER))-IV */ + i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size); + c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv); + } else if (!strcmp(org_i, "poly1305")) { + /* POLY1305 AEAD: capi:rfc7539(MODE(CIPHER),POLY1305)-IV */ + i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size); + c_size = snprintf(c_dm, c_dm_size, "capi:rfc7539(%s,poly1305)-%s", capi, iv); + } else { + /* other AEAD: capi:authenc(,MODE(CIPHER))-IV */ + i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size); + c_size = snprintf(c_dm, c_dm_size, "capi:authenc(%s,%s)-%s", org_i, capi, iv); + } + + if (c_size < 0 || c_size == c_dm_size) + return -EINVAL; + if (i_size < 0 || i_size == i_dm_size) + return -EINVAL; + + return 0; +} + +static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char *i_dm) +{ + char cipher[CLEN], mode[CLEN], iv[CLEN], auth[CLEN]; + char tmp[CAPIL], dmcrypt_tmp[CAPIL*2], capi[CAPIL+1]; + size_t len; + int i; + + if (!c_dm) + return -EINVAL; + + /* legacy mode */ + if (strncmp(c_dm, "capi:", 4)) { + if (!(*org_c = strdup(c_dm))) + return -ENOMEM; + *org_i = NULL; + return 0; + } + + /* modes with capi: prefix */ + i = sscanf(c_dm, "capi:%" CAPIS "[^-]-%" CLENS "s", tmp, iv); + if (i != 2) + return -EINVAL; + + len = strlen(tmp); + if (len < 2) + return -EINVAL; + + if (tmp[len-1] == ')') + tmp[len-1] = '\0'; + + if (sscanf(tmp, "rfc4309(%" CAPIS "s", capi) == 1) { + if (!(*org_i = strdup("aead"))) + return -ENOMEM; + } else if (sscanf(tmp, "rfc7539(%" CAPIS "[^,],%" CLENS "s", capi, auth) == 2) { + if (!(*org_i = strdup(auth))) + return -ENOMEM; + } else if (sscanf(tmp, "authenc(%" CLENS "[^,],%" CAPIS "s", auth, capi) == 2) { + if (!(*org_i = strdup(auth))) + return -ENOMEM; + } else { + if (i_dm) { + if (!(*org_i = strdup(i_dm))) + return -ENOMEM; + } else + *org_i = NULL; + memset(capi, 0, sizeof(capi)); + strncpy(capi, tmp, sizeof(capi)-1); + } + + i = sscanf(capi, "%" CLENS "[^(](%" CLENS "[^)])", mode, cipher); + if (i == 2) + snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv); + else + snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv); + + if (!(*org_c = strdup(dmcrypt_tmp))) { + free(*org_i); + *org_i = NULL; + return -ENOMEM; + } + + return 0; +} + /* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */ -static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd, uint32_t flags) +static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags) { - int r, max_size, null_cipher = 0, num_options = 0; + int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0; char *params, *hexkey; - char features[256]; + char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256]; - if (!dmd) + if (!tgt) + return NULL; + + r = cipher_c2dm(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size, + cipher_dm, sizeof(cipher_dm), integrity_dm, sizeof(integrity_dm)); + if (r < 0) return NULL; if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) @@ -313,37 +615,60 @@ static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd, uint32_t fl num_options++; if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) num_options++; + if (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) + num_options++; + if (tgt->u.crypt.integrity) + num_options++; - if (num_options) - snprintf(features, sizeof(features)-1, " %d%s%s%s", num_options, + if (tgt->u.crypt.sector_size != SECTOR_SIZE) { + num_options++; + snprintf(sector_feature, sizeof(sector_feature), " sector_size:%u", tgt->u.crypt.sector_size); + } else + *sector_feature = '\0'; + + if (num_options) { + snprintf(features, sizeof(features)-1, " %d%s%s%s%s%s%s", num_options, (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "", (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "", - (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : ""); - else + (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "", + (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) ? " iv_large_sectors" : "", + sector_feature, integrity_dm); + } else *features = '\0'; - if (!strncmp(dmd->u.crypt.cipher, "cipher_null-", 12)) + if (!strncmp(cipher_dm, "cipher_null-", 12)) null_cipher = 1; - hexkey = crypt_safe_alloc(null_cipher ? 2 : (dmd->u.crypt.vk->keylength * 2 + 1)); + if (flags & CRYPT_ACTIVATE_KEYRING_KEY) { + keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10; + hexkey = crypt_safe_alloc(keystr_len); + } else + hexkey = crypt_safe_alloc(null_cipher ? 2 : (tgt->u.crypt.vk->keylength * 2 + 1)); + if (!hexkey) return NULL; if (null_cipher) strncpy(hexkey, "-", 2); - else - hex_key(hexkey, dmd->u.crypt.vk->keylength, dmd->u.crypt.vk->key); + else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) { + r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description); + if (r < 0 || r >= keystr_len) { + params = NULL; + goto out; + } + } else + hex_key(hexkey, tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key); - max_size = strlen(hexkey) + strlen(dmd->u.crypt.cipher) + - strlen(device_block_path(dmd->data_device)) + + max_size = strlen(hexkey) + strlen(cipher_dm) + + strlen(device_block_path(tgt->data_device)) + strlen(features) + 64; params = crypt_safe_alloc(max_size); if (!params) goto out; r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s", - dmd->u.crypt.cipher, hexkey, dmd->u.crypt.iv_offset, - device_block_path(dmd->data_device), dmd->u.crypt.offset, + cipher_dm, hexkey, tgt->u.crypt.iv_offset, + device_block_path(tgt->data_device), tgt->u.crypt.offset, features); if (r < 0 || r >= max_size) { crypt_safe_free(params); @@ -355,19 +680,61 @@ out: } /* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */ -static char *get_dm_verity_params(struct crypt_params_verity *vp, - struct crypt_dm_active_device *dmd) +static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags) { - int max_size, r; + int max_size, r, num_options = 0; + struct crypt_params_verity *vp; char *params = NULL, *hexroot = NULL, *hexsalt = NULL; + char features[256], fec_features[256], verity_verify_args[512+32]; - if (!vp || !dmd) + if (!tgt || !tgt->u.verity.vp) return NULL; - hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1); + vp = tgt->u.verity.vp; + + /* These flags are not compatible */ + if ((flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) && + (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION)) + flags &= ~CRYPT_ACTIVATE_IGNORE_CORRUPTION; + + if (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) + num_options++; + if (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) + num_options++; + if (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) + num_options++; + if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) + num_options++; + + if (tgt->u.verity.fec_device) { + num_options += 8; + snprintf(fec_features, sizeof(fec_features)-1, + " use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32, + device_block_path(tgt->u.verity.fec_device), tgt->u.verity.fec_offset, + vp->data_size + tgt->u.verity.hash_blocks, vp->fec_roots); + } else + *fec_features = '\0'; + + if (tgt->u.verity.root_hash_sig_key_desc) { + num_options += 2; + snprintf(verity_verify_args, sizeof(verity_verify_args)-1, + " root_hash_sig_key_desc %s", tgt->u.verity.root_hash_sig_key_desc); + } else + *verity_verify_args = '\0'; + + if (num_options) + snprintf(features, sizeof(features)-1, " %d%s%s%s%s", num_options, + (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "", + (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "", + (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "", + (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : ""); + else + *features = '\0'; + + hexroot = crypt_safe_alloc(tgt->u.verity.root_hash_size * 2 + 1); if (!hexroot) goto out; - hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash); + hex_key(hexroot, tgt->u.verity.root_hash_size, tgt->u.verity.root_hash); hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2); if (!hexsalt) @@ -378,21 +745,24 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp, strncpy(hexsalt, "-", 2); max_size = strlen(hexroot) + strlen(hexsalt) + - strlen(device_block_path(dmd->data_device)) + - strlen(device_block_path(dmd->u.verity.hash_device)) + - strlen(vp->hash_name) + 128; + strlen(device_block_path(tgt->data_device)) + + strlen(device_block_path(tgt->u.verity.hash_device)) + + strlen(vp->hash_name) + strlen(features) + strlen(fec_features) + 128 + + strlen(verity_verify_args); params = crypt_safe_alloc(max_size); if (!params) goto out; r = snprintf(params, max_size, - "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s", - vp->hash_type, device_block_path(dmd->data_device), - device_block_path(dmd->u.verity.hash_device), + "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s%s%s%s", + vp->hash_type, device_block_path(tgt->data_device), + device_block_path(tgt->u.verity.hash_device), vp->data_block_size, vp->hash_block_size, - vp->data_size, dmd->u.verity.hash_offset, - vp->hash_name, hexroot, hexsalt); + vp->data_size, tgt->u.verity.hash_offset, + vp->hash_name, hexroot, hexsalt, features, fec_features, + verity_verify_args); + if (r < 0 || r >= max_size) { crypt_safe_free(params); params = NULL; @@ -401,11 +771,208 @@ out: crypt_safe_free(hexroot); crypt_safe_free(hexsalt); return params; +} + +static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags) +{ + int r, max_size, num_options = 0; + char *params, *hexkey, mode; + char features[512], feature[256]; + + if (!tgt) + return NULL; + + max_size = strlen(device_block_path(tgt->data_device)) + + (tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) + + (tgt->u.integrity.vk ? tgt->u.integrity.vk->keylength * 2 : 0) + + (tgt->u.integrity.journal_integrity_key ? tgt->u.integrity.journal_integrity_key->keylength * 2 : 0) + + (tgt->u.integrity.journal_crypt_key ? tgt->u.integrity.journal_crypt_key->keylength * 2 : 0) + + (tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) + + (tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) + + (tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 128; + + params = crypt_safe_alloc(max_size); + if (!params) + return NULL; + + *features = '\0'; + if (tgt->u.integrity.journal_size) { + num_options++; + snprintf(feature, sizeof(feature), "journal_sectors:%u ", + (unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE)); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.journal_watermark) { + num_options++; + snprintf(feature, sizeof(feature), + /* bitmap overloaded values */ + (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit:%u " : "journal_watermark:%u ", + tgt->u.integrity.journal_watermark); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.journal_commit_time) { + num_options++; + snprintf(feature, sizeof(feature), + /* bitmap overloaded values */ + (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval:%u " : "commit_time:%u ", + tgt->u.integrity.journal_commit_time); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.interleave_sectors) { + num_options++; + snprintf(feature, sizeof(feature), "interleave_sectors:%u ", + tgt->u.integrity.interleave_sectors); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.sector_size) { + num_options++; + snprintf(feature, sizeof(feature), "block_size:%u ", + tgt->u.integrity.sector_size); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.buffer_sectors) { + num_options++; + snprintf(feature, sizeof(feature), "buffer_sectors:%u ", + tgt->u.integrity.buffer_sectors); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (tgt->u.integrity.integrity) { + num_options++; + + if (tgt->u.integrity.vk) { + hexkey = crypt_safe_alloc(tgt->u.integrity.vk->keylength * 2 + 1); + if (!hexkey) { + crypt_safe_free(params); + return NULL; + } + hex_key(hexkey, tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key); + } else + hexkey = NULL; + + snprintf(feature, sizeof(feature), "internal_hash:%s%s%s ", + tgt->u.integrity.integrity, hexkey ? ":" : "", hexkey ?: ""); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + crypt_safe_free(hexkey); + } + + if (tgt->u.integrity.journal_integrity) { + num_options++; + + if (tgt->u.integrity.journal_integrity_key) { + hexkey = crypt_safe_alloc(tgt->u.integrity.journal_integrity_key->keylength * 2 + 1); + if (!hexkey) { + crypt_safe_free(params); + return NULL; + } + hex_key(hexkey, tgt->u.integrity.journal_integrity_key->keylength, + tgt->u.integrity.journal_integrity_key->key); + } else + hexkey = NULL; + + snprintf(feature, sizeof(feature), "journal_mac:%s%s%s ", + tgt->u.integrity.journal_integrity, hexkey ? ":" : "", hexkey ?: ""); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + crypt_safe_free(hexkey); + } + + if (tgt->u.integrity.journal_crypt) { + num_options++; + + if (tgt->u.integrity.journal_crypt_key) { + hexkey = crypt_safe_alloc(tgt->u.integrity.journal_crypt_key->keylength * 2 + 1); + if (!hexkey) { + crypt_safe_free(params); + return NULL; + } + hex_key(hexkey, tgt->u.integrity.journal_crypt_key->keylength, + tgt->u.integrity.journal_crypt_key->key); + } else + hexkey = NULL; + + snprintf(feature, sizeof(feature), "journal_crypt:%s%s%s ", + tgt->u.integrity.journal_crypt, hexkey ? ":" : "", hexkey ?: ""); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + crypt_safe_free(hexkey); + } + if (tgt->u.integrity.fix_padding) { + num_options++; + snprintf(feature, sizeof(feature), "fix_padding "); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + + if (flags & CRYPT_ACTIVATE_RECALCULATE) { + num_options++; + snprintf(feature, sizeof(feature), "recalculate "); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + + if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) { + num_options++; + snprintf(feature, sizeof(feature), "allow_discards "); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + + if (tgt->u.integrity.meta_device) { + num_options++; + snprintf(feature, sizeof(feature), "meta_device:%s ", + device_block_path(tgt->u.integrity.meta_device)); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + + if (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) + mode = 'B'; + else if (flags & CRYPT_ACTIVATE_RECOVERY) + mode = 'R'; + else if (flags & CRYPT_ACTIVATE_NO_JOURNAL) + mode = 'D'; + else + mode = 'J'; + + r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %d %s", + device_block_path(tgt->data_device), tgt->u.integrity.offset, + tgt->u.integrity.tag_size, mode, + num_options, *features ? features : ""); + if (r < 0 || r >= max_size) { + crypt_safe_free(params); + params = NULL; + } + + return params; +} + +static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags) +{ + char *params; + int r; + int max_size = strlen(device_block_path(tgt->data_device)) + int_log10(tgt->u.linear.offset) + 3; + + params = crypt_safe_alloc(max_size); + if (!params) + return NULL; + + r = snprintf(params, max_size, "%s %" PRIu64, + device_block_path(tgt->data_device), tgt->u.linear.offset); + + if (r < 0 || r >= max_size) { + crypt_safe_free(params); + params = NULL; + } + + return params; +} + +static char *get_dm_zero_params(const struct dm_target *tgt, uint32_t flags) +{ + char *params = crypt_safe_alloc(1); + if (!params) + return NULL; + params[0] = 0; + return params; } /* DM helpers */ -static int _dm_simple(int task, const char *name, int udev_wait) +static int _dm_remove(const char *name, int udev_wait, int deferred) { int r = 0; struct dm_task *dmt; @@ -414,46 +981,75 @@ static int _dm_simple(int task, const char *name, int udev_wait) if (!_dm_use_udev()) udev_wait = 0; - if (!(dmt = dm_task_create(task))) + if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) return 0; - if (name && !dm_task_set_name(dmt, name)) + if (!dm_task_set_name(dmt, name)) goto out; #if HAVE_DECL_DM_TASK_RETRY_REMOVE - /* Used only in DM_DEVICE_REMOVE */ - if (name && !dm_task_retry_remove(dmt)) + if (!dm_task_retry_remove(dmt)) + goto out; +#endif +#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE + if (deferred && !dm_task_deferred_remove(dmt)) goto out; #endif - if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, 0)) + if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK)) goto out; r = dm_task_run(dmt); if (udev_wait) (void)_dm_udev_wait(cookie); - - out: +out: dm_task_destroy(dmt); return r; } -static int _error_device(const char *name, size_t size) +static int _dm_simple(int task, const char *name, uint32_t dmflags) { - struct dm_task *dmt; int r = 0; + struct dm_task *dmt; - if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) + if (!(dmt = dm_task_create(task))) return 0; - if (!dm_task_set_name(dmt, name)) - goto error; + if (name && !dm_task_set_name(dmt, name)) + goto out; - if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", "")) - goto error; + if (task == DM_DEVICE_SUSPEND && + (dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt)) + goto out; - if (!dm_task_set_ro(dmt)) - goto error; + if (task == DM_DEVICE_SUSPEND && + (dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt)) + goto out; + + r = dm_task_run(dmt); +out: + dm_task_destroy(dmt); + return r; +} + +static int _dm_resume_device(const char *name, uint32_t flags); + +static int _error_device(const char *name, size_t size) +{ + struct dm_task *dmt; + int r = 0; + + if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) + return 0; + + if (!dm_task_set_name(dmt, name)) + goto error; + + if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", "")) + goto error; + + if (!dm_task_set_ro(dmt)) + goto error; if (!dm_task_no_open_count(dmt)) goto error; @@ -461,7 +1057,7 @@ static int _error_device(const char *name, size_t size) if (!dm_task_run(dmt)) goto error; - if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) { + if (_dm_resume_device(name, 0)) { _dm_simple(DM_DEVICE_CLEAR, name, 0); goto error; } @@ -473,36 +1069,87 @@ error: return r; } -int dm_remove_device(struct crypt_device *cd, const char *name, - int force, uint64_t size) +int dm_error_device(struct crypt_device *cd, const char *name) +{ + int r; + struct crypt_dm_active_device dmd; + + if (!name) + return -EINVAL; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + if ((dm_query_device(cd, name, 0, &dmd) >= 0) && _error_device(name, dmd.size)) + r = 0; + else + r = -EINVAL; + + dm_targets_free(cd, &dmd); + + dm_exit_context(); + + return r; +} + +int dm_clear_device(struct crypt_device *cd, const char *name) +{ + int r; + + if (!name) + return -EINVAL; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + if (_dm_simple(DM_DEVICE_CLEAR, name, 0)) + r = 0; + else + r = -EINVAL; + + dm_exit_context(); + + return r; +} + +int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags) { + struct crypt_dm_active_device dmd = {}; int r = -EINVAL; - int retries = force ? RETRY_COUNT : 1; + int retries = (flags & CRYPT_DEACTIVATE_FORCE) ? RETRY_COUNT : 1; + int deferred = (flags & CRYPT_DEACTIVATE_DEFERRED) ? 1 : 0; int error_target = 0; + uint32_t dmt_flags; - if (!name || (force && !size)) + if (!name) return -EINVAL; - if (dm_init_context(cd)) + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + if (deferred && !dm_flags(cd, DM_UNKNOWN, &dmt_flags) && !(dmt_flags & DM_DEFERRED_SUPPORTED)) { + log_err(cd, _("Requested deferred flag is not supported.")); + dm_exit_context(); return -ENOTSUP; + } do { - r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL; + r = _dm_remove(name, 1, deferred) ? 0 : -EINVAL; if (--retries && r) { - log_dbg("WARNING: other process locked internal device %s, %s.", + log_dbg(cd, "WARNING: other process locked internal device %s, %s.", name, retries ? "retrying remove" : "giving up"); sleep(1); - if (force && !error_target) { + if ((flags & CRYPT_DEACTIVATE_FORCE) && !error_target) { /* If force flag is set, replace device with error, read-only target. * it should stop processes from reading it and also removed underlying * device from mapping, so it is usable again. - * Force flag should be used only for temporary devices, which are - * intended to work inside cryptsetup only! * Anyway, if some process try to read temporary cryptsetup device, * it is bug - no other process should try touch it (e.g. udev). */ - _error_device(name, size); - error_target = 1; + if (!dm_query_device(cd, name, 0, &dmd)) { + _error_device(name, dmd.size); + error_target = 1; + } } } } while (r == -EINVAL && retries); @@ -520,7 +1167,8 @@ int dm_remove_device(struct crypt_device *cd, const char *name, * CRYPT-LUKS1-00000000000000000000000000000000-name * CRYPT-TEMP-name */ -static int dm_prepare_uuid(const char *name, const char *type, const char *uuid, char *buf, size_t buflen) +static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char *type, + const char *uuid, char *buf, size_t buflen) { char *ptr, uuid2[UUID_LEN] = {0}; uuid_t uu; @@ -529,7 +1177,7 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid, /* Remove '-' chars */ if (uuid) { if (uuid_parse(uuid, uu) < 0) { - log_dbg("Requested UUID %s has invalid format.", uuid); + log_dbg(cd, "Requested UUID %s has invalid format.", uuid); return 0; } @@ -545,102 +1193,182 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid, uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "", name); - log_dbg("DM-UUID is %s", buf); + log_dbg(cd, "DM-UUID is %s", buf); if (i >= buflen) - log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name); + log_err(cd, _("DM-UUID for device %s was truncated."), name); return 1; } -static int _dm_create_device(const char *name, const char *type, - struct device *device, uint32_t flags, - const char *uuid, uint64_t size, - char *params, int reload) +int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type) +{ + int r; + char *c; + char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX; + + if (!dm_prepare_uuid(cd, "", type, uuid, dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN)) + return -EINVAL; + + c = strrchr(dev_uuid, '-'); + if (!c) + return -EINVAL; + + /* cut of dm name */ + *c = '\0'; + + r = lookup_by_disk_id(dev_uuid); + if (r == -ENOENT) { + log_dbg(cd, "Search by disk id not available. Using sysfs instead."); + r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN); + } + + return r; +} + +static int _add_dm_targets(struct dm_task *dmt, struct crypt_dm_active_device *dmd) +{ + const char *target; + struct dm_target *tgt = &dmd->segment; + + do { + switch (tgt->type) { + case DM_CRYPT: + target = DM_CRYPT_TARGET; + break; + case DM_VERITY: + target = DM_VERITY_TARGET; + break; + case DM_INTEGRITY: + target = DM_INTEGRITY_TARGET; + break; + case DM_LINEAR: + target = DM_LINEAR_TARGET; + break; + case DM_ZERO: + target = DM_ZERO_TARGET; + break; + default: + return -ENOTSUP; + } + + if (!dm_task_add_target(dmt, tgt->offset, tgt->size, target, tgt->params)) + return -EINVAL; + + tgt = tgt->next; + } while (tgt); + + return 0; +} + +static void _destroy_dm_targets_params(struct crypt_dm_active_device *dmd) +{ + struct dm_target *t = &dmd->segment; + + do { + crypt_safe_free(t->params); + t->params = NULL; + t = t->next; + } while (t); +} + +static int _create_dm_targets_params(struct crypt_dm_active_device *dmd) +{ + int r; + struct dm_target *tgt = &dmd->segment; + + do { + if (tgt->type == DM_CRYPT) + tgt->params = get_dm_crypt_params(tgt, dmd->flags); + else if (tgt->type == DM_VERITY) + tgt->params = get_dm_verity_params(tgt, dmd->flags); + else if (tgt->type == DM_INTEGRITY) + tgt->params = get_dm_integrity_params(tgt, dmd->flags); + else if (tgt->type == DM_LINEAR) + tgt->params = get_dm_linear_params(tgt, dmd->flags); + else if (tgt->type == DM_ZERO) + tgt->params = get_dm_zero_params(tgt, dmd->flags); + else { + r = -ENOTSUP; + goto err; + } + + if (!tgt->params) { + r = -EINVAL; + goto err; + } + tgt = tgt->next; + } while (tgt); + + return 0; +err: + _destroy_dm_targets_params(dmd); + return r; +} + +static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type, + const char *uuid, struct crypt_dm_active_device *dmd) { struct dm_task *dmt = NULL; struct dm_info dmi; char dev_uuid[DM_UUID_LEN] = {0}; int r = -EINVAL; - uint32_t read_ahead = 0; - uint32_t cookie = 0; - uint16_t udev_flags = 0; + uint32_t cookie = 0, read_ahead = 0; + uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; - if (!params) - return -EINVAL; - - if (flags & CRYPT_ACTIVATE_PRIVATE) - udev_flags = CRYPT_TEMP_UDEV_FLAGS; + if (dmd->flags & CRYPT_ACTIVATE_PRIVATE) + udev_flags |= CRYPT_TEMP_UDEV_FLAGS; /* All devices must have DM_UUID, only resize on old device is exception */ - if (reload) { - if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) - goto out_no_removal; + if (!dm_prepare_uuid(cd, name, type, dmd->uuid, dev_uuid, sizeof(dev_uuid))) + goto out; - if (!dm_task_set_name(dmt, name)) - goto out_no_removal; - } else { - if (!dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid))) - goto out_no_removal; + if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) + goto out; - if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) - goto out_no_removal; + if (!dm_task_set_name(dmt, name)) + goto out; - if (!dm_task_set_name(dmt, name)) - goto out_no_removal; + if (!dm_task_set_uuid(dmt, dev_uuid)) + goto out; - if (!dm_task_set_uuid(dmt, dev_uuid)) - goto out_no_removal; + if (!dm_task_secure_data(dmt)) + goto out; + if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt)) + goto out; - if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags)) - goto out_no_removal; - } + r = _create_dm_targets_params(dmd); + if (r) + goto out; - if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt)) - goto out_no_removal; - if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt)) - goto out_no_removal; + r = _add_dm_targets(dmt, dmd); + if (r) + goto out; - if (!dm_task_add_target(dmt, 0, size, - !strcmp("VERITY", type) ? DM_VERITY_TARGET : DM_CRYPT_TARGET, params)) - goto out_no_removal; + r = -EINVAL; #ifdef DM_READ_AHEAD_MINIMUM_FLAG - if (device_read_ahead(device, &read_ahead) && + if (device_read_ahead(dmd->segment.data_device, &read_ahead) && !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG)) - goto out_no_removal; + goto out; #endif + if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto out; if (!dm_task_run(dmt)) - goto out_no_removal; - - if (reload) { - dm_task_destroy(dmt); - if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) - goto out; - if (!dm_task_set_name(dmt, name)) - goto out; - if (uuid && !dm_task_set_uuid(dmt, dev_uuid)) - goto out; - if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags)) - goto out; - if (!dm_task_run(dmt)) - goto out; - } - - if (!dm_task_get_info(dmt, &dmi)) goto out; - r = 0; -out: + if (dm_task_get_info(dmt, &dmi)) + r = 0; + if (_dm_use_udev()) { (void)_dm_udev_wait(cookie); cookie = 0; } - if (r < 0 && !reload) - _dm_simple(DM_DEVICE_REMOVE, name, 1); + if (r < 0) + _dm_remove(name, 1, 0); -out_no_removal: +out: if (cookie && _dm_use_udev()) (void)_dm_udev_wait(cookie); @@ -650,301 +1378,664 @@ out_no_removal: dm_task_update_nodes(); /* If code just loaded target module, update versions */ - _dm_check_versions(); + _dm_check_versions(cd, dmd->segment.type); + + _destroy_dm_targets_params(dmd); return r; } -int dm_create_device(struct crypt_device *cd, const char *name, - const char *type, - struct crypt_dm_active_device *dmd, - int reload) +static int _dm_resume_device(const char *name, uint32_t dmflags) { - char *table_params = NULL; - uint32_t dmd_flags; - int r; + struct dm_task *dmt; + int r = -EINVAL; + uint32_t cookie = 0; + uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; - if (!type) - return -EINVAL; + if (dmflags & DM_RESUME_PRIVATE) + udev_flags |= CRYPT_TEMP_UDEV_FLAGS; - if (dm_init_context(cd)) - return -ENOTSUP; + if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) + return r; - dmd_flags = dmd->flags; + if (!dm_task_set_name(dmt, name)) + goto out; - if (dmd->target == DM_CRYPT) - table_params = get_dm_crypt_params(dmd, dmd_flags); - else if (dmd->target == DM_VERITY) - table_params = get_dm_verity_params(dmd->u.verity.vp, dmd); + if ((dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt)) + goto out; - r = _dm_create_device(name, type, dmd->data_device, dmd_flags, - dmd->uuid, dmd->size, table_params, reload); + if ((dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt)) + goto out; - /* If discard not supported try to load without discard */ - if (!reload && r && dmd->target == DM_CRYPT && - (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && - !(dm_flags() & DM_DISCARDS_SUPPORTED)) { - log_dbg("Discard/TRIM is not supported, retrying activation."); - dmd_flags = dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS; - crypt_safe_free(table_params); - table_params = get_dm_crypt_params(dmd, dmd_flags); - r = _dm_create_device(name, type, dmd->data_device, dmd_flags, - dmd->uuid, dmd->size, table_params, reload); - } + if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto out; - if (r == -EINVAL && - dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) && - !(dm_flags() & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) - log_err(cd, _("Requested dmcrypt performance options are not supported.\n")); + if (dm_task_run(dmt)) + r = 0; +out: + if (cookie && _dm_use_udev()) + (void)_dm_udev_wait(cookie); + + dm_task_destroy(dmt); + + dm_task_update_nodes(); - crypt_safe_free(table_params); - dm_exit_context(); return r; } -static int dm_status_dmi(const char *name, struct dm_info *dmi, - const char *target, char **status_line) +static int _dm_reload_device(struct crypt_device *cd, const char *name, + struct crypt_dm_active_device *dmd) { - struct dm_task *dmt; - uint64_t start, length; - char *target_type, *params = NULL; - void *next = NULL; int r = -EINVAL; + struct dm_task *dmt = NULL; + uint32_t read_ahead = 0; - if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) + /* All devices must have DM_UUID, only resize on old device is exception */ + if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) goto out; if (!dm_task_set_name(dmt, name)) goto out; - if (!dm_task_run(dmt)) + if (!dm_task_secure_data(dmt)) goto out; - - if (!dm_task_get_info(dmt, dmi)) + if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt)) goto out; - if (!dmi->exists) { - r = -ENODEV; + r = _create_dm_targets_params(dmd); + if (r) goto out; - } - next = dm_get_next_target(dmt, next, &start, &length, - &target_type, ¶ms); - - if (!target_type || start != 0 || next) + r = _add_dm_targets(dmt, dmd); + if (r) goto out; - if (target && strcmp(target_type, target)) - goto out; + r = -EINVAL; - /* for target == NULL check all supported */ - if (!target && (strcmp(target_type, DM_CRYPT_TARGET) && - strcmp(target_type, DM_VERITY_TARGET))) +#ifdef DM_READ_AHEAD_MINIMUM_FLAG + if (device_read_ahead(dmd->segment.data_device, &read_ahead) && + !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG)) goto out; - r = 0; -out: - if (!r && status_line && !(*status_line = strdup(params))) - r = -ENOMEM; +#endif + if (dm_task_run(dmt)) + r = 0; +out: if (dmt) dm_task_destroy(dmt); + /* If code just loaded target module, update versions */ + _dm_check_versions(cd, dmd->segment.type); + + _destroy_dm_targets_params(dmd); + return r; } -int dm_status_device(struct crypt_device *cd, const char *name) +static void crypt_free_verity_params(struct crypt_params_verity *vp) { - int r; - struct dm_info dmi; - struct stat st; - - /* libdevmapper is too clever and handles - * path argument differenly with error. - * Fail early here if parameter is non-existent path. - */ - if (strchr(name, '/') && stat(name, &st) < 0) - return -ENODEV; + if (!vp) + return; + + free(CONST_CAST(void*)vp->hash_name); + free(CONST_CAST(void*)vp->data_device); + free(CONST_CAST(void*)vp->hash_device); + free(CONST_CAST(void*)vp->fec_device); + free(CONST_CAST(void*)vp->salt); + free(vp); +} - if (dm_init_context(cd)) - return -ENOTSUP; - r = dm_status_dmi(name, &dmi, NULL, NULL); - dm_exit_context(); - if (r < 0) - return r; +static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target *tgt) +{ + switch(tgt->type) { + case DM_CRYPT: + crypt_free_volume_key(tgt->u.crypt.vk); + free(CONST_CAST(void*)tgt->u.crypt.cipher); + break; + case DM_INTEGRITY: + free(CONST_CAST(void*)tgt->u.integrity.integrity); + crypt_free_volume_key(tgt->u.integrity.vk); + + free(CONST_CAST(void*)tgt->u.integrity.journal_integrity); + crypt_free_volume_key(tgt->u.integrity.journal_integrity_key); + + free(CONST_CAST(void*)tgt->u.integrity.journal_crypt); + crypt_free_volume_key(tgt->u.integrity.journal_crypt_key); + + device_free(cd, tgt->u.integrity.meta_device); + break; + case DM_VERITY: + crypt_free_verity_params(tgt->u.verity.vp); + device_free(cd, tgt->u.verity.hash_device); + free(CONST_CAST(void*)tgt->u.verity.root_hash); + free(CONST_CAST(void*)tgt->u.verity.root_hash_sig_key_desc); + /* fall through */ + case DM_LINEAR: + /* fall through */ + case DM_ERROR: + /* fall through */ + case DM_ZERO: + break; + default: + log_err(cd, _("Unknown dm target type.")); + return; + } - return (dmi.open_count > 0); + device_free(cd, tgt->data_device); } -int dm_status_suspended(struct crypt_device *cd, const char *name) +static void _dm_target_erase(struct crypt_device *cd, struct dm_target *tgt) { - int r; - struct dm_info dmi; - - if (dm_init_context(cd)) - return -ENOTSUP; - r = dm_status_dmi(name, &dmi, DM_CRYPT_TARGET, NULL); - dm_exit_context(); - if (r < 0) - return r; + if (tgt->direction == TARGET_QUERY) + _dm_target_free_query_path(cd, tgt); - return dmi.suspended ? 1 : 0; + if (tgt->type == DM_CRYPT) + free(CONST_CAST(void*)tgt->u.crypt.integrity); } -static int _dm_status_verity_ok(const char *name) +void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd) { - int r; - struct dm_info dmi; - char *status_line = NULL; + struct dm_target *t = &dmd->segment, *next = t->next; - r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line); - if (r < 0 || !status_line) { - free(status_line); - return r; - } + _dm_target_erase(cd, t); - log_dbg("Verity volume %s status is %s.", name, status_line ?: ""); - r = status_line[0] == 'V' ? 1 : 0; - free(status_line); + while (next) { + t = next; + next = t->next; + _dm_target_erase(cd, t); + free(t); + } - return r; + memset(&dmd->segment, 0, sizeof(dmd->segment)); } -int dm_status_verity_ok(struct crypt_device *cd, const char *name) +int dm_targets_allocate(struct dm_target *first, unsigned count) { - int r; + if (!first || first->next || !count) + return -EINVAL; - if (dm_init_context(cd)) - return -ENOTSUP; - r = _dm_status_verity_ok(name); - dm_exit_context(); - return r; + while (--count) { + first->next = crypt_zalloc(sizeof(*first)); + if (!first->next) + return -ENOMEM; + first = first->next; + } + + return 0; } -/* FIXME use hex wrapper, user val wrappers for line parsing */ -static int _dm_query_crypt(uint32_t get_flags, - struct dm_info *dmi, - char *params, - struct crypt_dm_active_device *dmd) +static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dmt_flags) { - uint64_t val64; - char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg; - unsigned int i; - int r; + int ret = 0; - memset(dmd, 0, sizeof(*dmd)); - dmd->target = DM_CRYPT; + /* If discard not supported try to load without discard */ + if ((*dmd_flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && + !(dmt_flags & DM_DISCARDS_SUPPORTED)) { + log_dbg(cd, "Discard/TRIM is not supported"); + *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS; + ret = 1; + } + + /* If kernel keyring is not supported load key directly in dm-crypt */ + if ((*dmd_flags & CRYPT_ACTIVATE_KEYRING_KEY) && + !(dmt_flags & DM_KERNEL_KEYRING_SUPPORTED)) { + log_dbg(cd, "dm-crypt does not support kernel keyring"); + *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_KEYRING_KEY; + ret = 1; + } + + /* Drop performance options if not supported */ + if ((*dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) && + !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) { + log_dbg(cd, "dm-crypt does not support performance options"); + *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS); + ret = 1; + } + + return ret; +} + +int dm_create_device(struct crypt_device *cd, const char *name, + const char *type, + struct crypt_dm_active_device *dmd) +{ + uint32_t dmt_flags = 0; + int r = -EINVAL; + + if (!type || !dmd) + return -EINVAL; + + if (dm_init_context(cd, dmd->segment.type)) + return -ENOTSUP; + + r = _dm_create_device(cd, name, type, dmd->uuid, dmd); + + if (r < 0 && dm_flags(cd, dmd->segment.type, &dmt_flags)) + goto out; + + if (r && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) && + check_retry(cd, &dmd->flags, dmt_flags)) + r = _dm_create_device(cd, name, type, dmd->uuid, dmd); + + if (r == -EINVAL && + dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) && + !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) + log_err(cd, _("Requested dm-crypt performance options are not supported.")); + + if (r == -EINVAL && dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION| + CRYPT_ACTIVATE_RESTART_ON_CORRUPTION| + CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS| + CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) && + !(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED)) + log_err(cd, _("Requested dm-verity data corruption handling options are not supported.")); + + if (r == -EINVAL && dmd->segment.type == DM_VERITY && + dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED)) + log_err(cd, _("Requested dm-verity FEC options are not supported.")); + + if (r == -EINVAL && dmd->segment.type == DM_CRYPT) { + if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED)) + log_err(cd, _("Requested data integrity options are not supported.")); + if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) + log_err(cd, _("Requested sector_size option is not supported.")); + } + + if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) && + !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) + log_err(cd, _("Requested automatic recalculation of integrity tags is not supported.")); + + if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && + !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) + log_err(cd, _("Discard/TRIM is not supported.")); + + if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) && + !(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED)) + log_err(cd, _("Requested dm-integrity bitmap mode is not supported.")); +out: + dm_exit_context(); + return r; +} + +int dm_reload_device(struct crypt_device *cd, const char *name, + struct crypt_dm_active_device *dmd, uint32_t dmflags, unsigned resume) +{ + int r; + uint32_t dmt_flags; + + if (!dmd) + return -EINVAL; + + if (dm_init_context(cd, dmd->segment.type)) + return -ENOTSUP; + + if (dm_flags(cd, DM_INTEGRITY, &dmt_flags) || !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) + dmd->flags &= ~CRYPT_ACTIVATE_RECALCULATE; + + r = _dm_reload_device(cd, name, dmd); + + if (r == -EINVAL && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR)) { + if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) && + !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) + log_err(cd, _("Requested dm-crypt performance options are not supported.")); + if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && + !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED)) + log_err(cd, _("Discard/TRIM is not supported.")); + if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && + !dm_flags(cd, DM_INTEGRITY, &dmt_flags) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) + log_err(cd, _("Discard/TRIM is not supported.")); + } + + if (!r && resume) + r = _dm_resume_device(name, dmflags | act2dmflags(dmd->flags)); + + dm_exit_context(); + return r; +} + +static int dm_status_dmi(const char *name, struct dm_info *dmi, + const char *target, char **status_line) +{ + struct dm_task *dmt; + uint64_t start, length; + char *target_type, *params = NULL; + int r = -EINVAL; + + if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) + goto out; + + if (!dm_task_no_flush(dmt)) + goto out; + + if (!dm_task_set_name(dmt, name)) + goto out; + + if (!dm_task_run(dmt)) + goto out; + + if (!dm_task_get_info(dmt, dmi)) + goto out; + + if (!dmi->exists) { + r = -ENODEV; + goto out; + } + + dm_get_next_target(dmt, NULL, &start, &length, + &target_type, ¶ms); + + if (!target_type || start != 0) + goto out; + + if (target && strcmp(target_type, target)) + goto out; + + /* for target == NULL check all supported */ + if (!target && (strcmp(target_type, DM_CRYPT_TARGET) && + strcmp(target_type, DM_VERITY_TARGET) && + strcmp(target_type, DM_INTEGRITY_TARGET) && + strcmp(target_type, DM_LINEAR_TARGET) && + strcmp(target_type, DM_ZERO_TARGET) && + strcmp(target_type, DM_ERROR_TARGET))) + goto out; + r = 0; +out: + if (!r && status_line && !(*status_line = strdup(params))) + r = -ENOMEM; + + if (dmt) + dm_task_destroy(dmt); + + return r; +} + +int dm_status_device(struct crypt_device *cd, const char *name) +{ + int r; + struct dm_info dmi; + struct stat st; + + /* libdevmapper is too clever and handles + * path argument differently with error. + * Fail early here if parameter is non-existent path. + */ + if (strchr(name, '/') && stat(name, &st) < 0) + return -ENODEV; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + r = dm_status_dmi(name, &dmi, NULL, NULL); + dm_exit_context(); + + if (r < 0) + return r; + + return (dmi.open_count > 0) ? 1 : 0; +} + +int dm_status_suspended(struct crypt_device *cd, const char *name) +{ + int r; + struct dm_info dmi; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + r = dm_status_dmi(name, &dmi, NULL, NULL); + dm_exit_context(); + + if (r < 0) + return r; + + return dmi.suspended ? 1 : 0; +} + +static int _dm_status_verity_ok(struct crypt_device *cd, const char *name) +{ + int r; + struct dm_info dmi; + char *status_line = NULL; + + r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line); + if (r < 0 || !status_line) { + free(status_line); + return r; + } + + log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: ""); + r = status_line[0] == 'V' ? 1 : 0; + free(status_line); + + return r; +} + +int dm_status_verity_ok(struct crypt_device *cd, const char *name) +{ + int r; + + if (dm_init_context(cd, DM_VERITY)) + return -ENOTSUP; + r = _dm_status_verity_ok(cd, name); + dm_exit_context(); + return r; +} + +int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count) +{ + int r; + struct dm_info dmi; + char *status_line = NULL; + + if (dm_init_context(cd, DM_INTEGRITY)) + return -ENOTSUP; + + r = dm_status_dmi(name, &dmi, DM_INTEGRITY_TARGET, &status_line); + if (r < 0 || !status_line) { + free(status_line); + dm_exit_context(); + return r; + } + + log_dbg(cd, "Integrity volume %s failure status is %s.", name, status_line ?: ""); + *count = strtoull(status_line, NULL, 10); + free(status_line); + dm_exit_context(); + + return 0; +} + +/* FIXME use hex wrapper, user val wrappers for line parsing */ +static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags, + char *params, struct dm_target *tgt, + uint32_t *act_flags) +{ + uint64_t val64; + char *rcipher, *rintegrity, *key_, *rdevice, *endp, buffer[3], *arg, *key_desc; + unsigned int i, val; + int r; + size_t key_size; + struct device *data_device = NULL; + char *cipher = NULL, *integrity = NULL; + struct volume_key *vk = NULL; + + tgt->type = DM_CRYPT; + tgt->direction = TARGET_QUERY; + tgt->u.crypt.sector_size = SECTOR_SIZE; + + r = -EINVAL; rcipher = strsep(¶ms, " "); - /* cipher */ - if (get_flags & DM_ACTIVE_CRYPT_CIPHER) - dmd->u.crypt.cipher = strdup(rcipher); + rintegrity = NULL; /* skip */ key_ = strsep(¶ms, " "); if (!params) - return -EINVAL; + goto err; val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; + goto err; params++; - dmd->u.crypt.iv_offset = val64; + tgt->u.crypt.iv_offset = val64; /* device */ rdevice = strsep(¶ms, " "); if (get_flags & DM_ACTIVE_DEVICE) { arg = crypt_lookup_dev(rdevice); - r = device_alloc(&dmd->data_device, arg); + r = device_alloc(cd, &data_device, arg); free(arg); if (r < 0 && r != -ENOTBLK) - return r; + goto err; } + r = -EINVAL; + /*offset */ if (!params) - return -EINVAL; + goto err; val64 = strtoull(params, ¶ms, 10); - dmd->u.crypt.offset = val64; + tgt->u.crypt.offset = val64; + + tgt->u.crypt.tag_size = 0; /* Features section, available since crypt target version 1.11 */ if (*params) { if (*params != ' ') - return -EINVAL; + goto err; params++; /* Number of arguments */ val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; + goto err; params++; for (i = 0; i < val64; i++) { if (!params) - return -EINVAL; + goto err; arg = strsep(¶ms, " "); if (!strcasecmp(arg, "allow_discards")) - dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; else if (!strcasecmp(arg, "same_cpu_crypt")) - dmd->flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT; + *act_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT; else if (!strcasecmp(arg, "submit_from_crypt_cpus")) - dmd->flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS; - else /* unknown option */ - return -EINVAL; + *act_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS; + else if (!strcasecmp(arg, "iv_large_sectors")) + *act_flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS; + else if (sscanf(arg, "integrity:%u:", &val) == 1) { + tgt->u.crypt.tag_size = val; + rintegrity = strchr(arg + strlen("integrity:"), ':'); + if (!rintegrity) + goto err; + rintegrity++; + } else if (sscanf(arg, "sector_size:%u", &val) == 1) { + tgt->u.crypt.sector_size = val; + } else /* unknown option */ + goto err; } - /* All parameters shold be processed */ + /* All parameters should be processed */ if (params) - return -EINVAL; + goto err; } - /* Never allow to return empty key */ - if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi->suspended) { - log_dbg("Cannot read volume key while suspended."); - return -EINVAL; + /* cipher */ + if (get_flags & DM_ACTIVE_CRYPT_CIPHER) { + r = cipher_dm2c(CONST_CAST(char**)&cipher, + CONST_CAST(char**)&integrity, + rcipher, rintegrity); + if (r < 0) + goto err; } + r = -EINVAL; + + if (key_[0] == ':') + *act_flags |= CRYPT_ACTIVATE_KEYRING_KEY; + if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) { - dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL); - if (!dmd->u.crypt.vk) - return -ENOMEM; + /* we will trust kernel the key_string is in expected format */ + if (key_[0] == ':') { + if (sscanf(key_ + 1, "%zu", &key_size) != 1) + goto err; + } else + key_size = strlen(key_) / 2; + + vk = crypt_alloc_volume_key(key_size, NULL); + if (!vk) { + r = -ENOMEM; + goto err; + } if (get_flags & DM_ACTIVE_CRYPT_KEY) { - buffer[2] = '\0'; - for(i = 0; i < dmd->u.crypt.vk->keylength; i++) { - memcpy(buffer, &key_[i * 2], 2); - dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16); - if (endp != &buffer[2]) { - crypt_free_volume_key(dmd->u.crypt.vk); - dmd->u.crypt.vk = NULL; - return -EINVAL; + if (key_[0] == ':') { + /* ::: */ + key_desc = NULL; + endp = strpbrk(key_ + 1, ":"); + if (endp) + key_desc = strpbrk(endp + 1, ":"); + if (!key_desc) { + r = -ENOMEM; + goto err; + } + key_desc++; + crypt_volume_key_set_description(vk, key_desc); + } else { + buffer[2] = '\0'; + for(i = 0; i < vk->keylength; i++) { + memcpy(buffer, &key_[i * 2], 2); + vk->key[i] = strtoul(buffer, &endp, 16); + if (endp != &buffer[2]) { + r = -EINVAL; + goto err; + } } } } } memset(key_, 0, strlen(key_)); + if (cipher) + tgt->u.crypt.cipher = cipher; + if (integrity) + tgt->u.crypt.integrity = integrity; + if (data_device) + tgt->data_device = data_device; + if (vk) + tgt->u.crypt.vk = vk; return 0; +err: + free(cipher); + free(integrity); + device_free(cd, data_device); + crypt_free_volume_key(vk); + return r; } -static int _dm_query_verity(uint32_t get_flags, - struct dm_info *dmi, - char *params, - struct crypt_dm_active_device *dmd) +static int _dm_target_query_verity(struct crypt_device *cd, + uint32_t get_flags, + char *params, + struct dm_target *tgt, + uint32_t *act_flags) { struct crypt_params_verity *vp = NULL; uint32_t val32; uint64_t val64; ssize_t len; - char *str, *str2; + char *str, *str2, *arg; + unsigned int i, features; int r; + struct device *data_device = NULL, *hash_device = NULL, *fec_device = NULL; + char *hash_name = NULL, *root_hash = NULL, *salt = NULL, *fec_dev_str = NULL; + char *root_hash_sig_key_desc = NULL; - if (get_flags & DM_ACTIVE_VERITY_PARAMS) - vp = dmd->u.verity.vp; - - memset(dmd, 0, sizeof(*dmd)); + if (get_flags & DM_ACTIVE_VERITY_PARAMS) { + vp = crypt_zalloc(sizeof(*vp)); + if (!vp) + return -ENOMEM; + } - dmd->target = DM_VERITY; - dmd->u.verity.vp = vp; + tgt->type = DM_VERITY; + tgt->direction = TARGET_QUERY; + tgt->u.verity.vp = vp; /* version */ val32 = strtoul(params, ¶ms, 10); @@ -960,28 +2051,32 @@ static int _dm_query_verity(uint32_t get_flags, return -EINVAL; if (get_flags & DM_ACTIVE_DEVICE) { str2 = crypt_lookup_dev(str); - r = device_alloc(&dmd->data_device, str2); + r = device_alloc(cd, &data_device, str2); free(str2); if (r < 0 && r != -ENOTBLK) return r; } + r = -EINVAL; + /* hash device */ str = strsep(¶ms, " "); if (!params) - return -EINVAL; + goto err; if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) { str2 = crypt_lookup_dev(str); - r = device_alloc(&dmd->u.verity.hash_device, str2); + r = device_alloc(cd, &hash_device, str2); free(str2); if (r < 0 && r != -ENOTBLK) - return r; + goto err; } + r = -EINVAL; + /* data block size*/ val32 = strtoul(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; + goto err; if (vp) vp->data_block_size = val32; params++; @@ -989,7 +2084,7 @@ static int _dm_query_verity(uint32_t get_flags, /* hash block size */ val32 = strtoul(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; + goto err; if (vp) vp->hash_block_size = val32; params++; @@ -997,7 +2092,7 @@ static int _dm_query_verity(uint32_t get_flags, /* data blocks */ val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; + goto err; if (vp) vp->data_size = val64; params++; @@ -1005,66 +2100,465 @@ static int _dm_query_verity(uint32_t get_flags, /* hash start */ val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - return -EINVAL; - dmd->u.verity.hash_offset = val64; + goto err; + tgt->u.verity.hash_offset = val64; params++; /* hash algorithm */ str = strsep(¶ms, " "); if (!params) - return -EINVAL; - if (vp) - vp->hash_name = strdup(str); + goto err; + if (vp) { + hash_name = strdup(str); + if (!hash_name) { + r = -ENOMEM; + goto err; + } + } /* root digest */ str = strsep(¶ms, " "); if (!params) - return -EINVAL; + goto err; len = crypt_hex_to_bytes(str, &str2, 0); - if (len < 0) - return len; - dmd->u.verity.root_hash_size = len; + if (len < 0) { + r = len; + goto err; + } + tgt->u.verity.root_hash_size = len; if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH) - dmd->u.verity.root_hash = str2; + root_hash = str2; else free(str2); /* salt */ str = strsep(¶ms, " "); - if (params) - return -EINVAL; if (vp) { if (!strcmp(str, "-")) { vp->salt_size = 0; vp->salt = NULL; } else { len = crypt_hex_to_bytes(str, &str2, 0); - if (len < 0) - return len; + if (len < 0) { + r = len; + goto err; + } vp->salt_size = len; - vp->salt = str2; + salt = str2; + } + } + + r = -EINVAL; + + /* Features section, available since verity target version 1.3 */ + if (params) { + /* Number of arguments */ + val64 = strtoull(params, ¶ms, 10); + if (*params != ' ') + goto err; + params++; + + features = (int)val64; + for (i = 0; i < features; i++) { + r = -EINVAL; + if (!params) + goto err; + arg = strsep(¶ms, " "); + if (!strcasecmp(arg, "ignore_corruption")) + *act_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION; + else if (!strcasecmp(arg, "restart_on_corruption")) + *act_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION; + else if (!strcasecmp(arg, "ignore_zero_blocks")) + *act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS; + else if (!strcasecmp(arg, "check_at_most_once")) + *act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE; + else if (!strcasecmp(arg, "use_fec_from_device")) { + str = strsep(¶ms, " "); + str2 = crypt_lookup_dev(str); + if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) { + r = device_alloc(cd, &fec_device, str2); + if (r < 0 && r != -ENOTBLK) { + free(str2); + goto err; + } + } + if (vp) { + free(fec_dev_str); + fec_dev_str = str2; + } else + free(str2); + i++; + } else if (!strcasecmp(arg, "fec_start")) { + val64 = strtoull(params, ¶ms, 10); + if (*params) + params++; + tgt->u.verity.fec_offset = val64; + if (vp) + vp->fec_area_offset = val64 * vp->hash_block_size; + i++; + } else if (!strcasecmp(arg, "fec_blocks")) { + val64 = strtoull(params, ¶ms, 10); + if (*params) + params++; + tgt->u.verity.fec_blocks = val64; + i++; + } else if (!strcasecmp(arg, "fec_roots")) { + val32 = strtoul(params, ¶ms, 10); + if (*params) + params++; + if (vp) + vp->fec_roots = val32; + i++; + } else if (!strcasecmp(arg, "root_hash_sig_key_desc")) { + str = strsep(¶ms, " "); + if (!str) + goto err; + if (!root_hash_sig_key_desc) + root_hash_sig_key_desc = strdup(str); + i++; + if (vp) + vp->flags |= CRYPT_VERITY_ROOT_HASH_SIGNATURE; + } else /* unknown option */ + goto err; + } + + /* All parameters should be processed */ + if (params && *params) { + r = -EINVAL; + goto err; } } + if (data_device) + tgt->data_device = data_device; + if (hash_device) + tgt->u.verity.hash_device = hash_device; + if (fec_device) + tgt->u.verity.fec_device = fec_device; + if (root_hash) + tgt->u.verity.root_hash = root_hash; + if (vp && hash_name) + vp->hash_name = hash_name; + if (vp && salt) + vp->salt = salt; + if (vp && fec_dev_str) + vp->fec_device = fec_dev_str; + if (root_hash_sig_key_desc) + tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc; + return 0; +err: + device_free(cd, data_device); + device_free(cd, hash_device); + device_free(cd, fec_device); + free(root_hash_sig_key_desc); + free(root_hash); + free(hash_name); + free(salt); + free(fec_dev_str); + free(vp); + return r; } -int dm_query_device(struct crypt_device *cd, const char *name, - uint32_t get_flags, struct crypt_dm_active_device *dmd) +static int _dm_target_query_integrity(struct crypt_device *cd, + uint32_t get_flags, + char *params, + struct dm_target *tgt, + uint32_t *act_flags) { - struct dm_task *dmt; - struct dm_info dmi; - uint64_t start, length; - char *target_type, *params; - const char *tmp_uuid; - void *next = NULL; - int r = -EINVAL; + uint32_t val32; + uint64_t val64; + char c, *str, *str2, *arg; + unsigned int i, features, val; + ssize_t len; + int r; + struct device *data_device = NULL, *meta_device = NULL; + char *integrity = NULL, *journal_crypt = NULL, *journal_integrity = NULL; + struct volume_key *vk = NULL; + + tgt->type = DM_INTEGRITY; + tgt->direction = TARGET_QUERY; + + /* data device */ + str = strsep(¶ms, " "); + if (get_flags & DM_ACTIVE_DEVICE) { + str2 = crypt_lookup_dev(str); + r = device_alloc(cd, &data_device, str2); + free(str2); + if (r < 0 && r != -ENOTBLK) + return r; + } + + r = -EINVAL; + + /*offset */ + if (!params) + goto err; + val64 = strtoull(params, ¶ms, 10); + if (!*params || *params != ' ') + goto err; + tgt->u.integrity.offset = val64; + + /* tag size*/ + val32 = strtoul(params, ¶ms, 10); + tgt->u.integrity.tag_size = val32; + if (!*params || *params != ' ') + goto err; + + /* journal */ + c = toupper(*(++params)); + if (!*params || *(++params) != ' ' || (c != 'D' && c != 'J' && c != 'R' && c != 'B')) + goto err; + if (c == 'D') + *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL; + if (c == 'R') + *act_flags |= CRYPT_ACTIVATE_RECOVERY; + if (c == 'B') { + *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL; + *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP; + } + + tgt->u.integrity.sector_size = SECTOR_SIZE; + + /* Features section */ + if (params) { + /* Number of arguments */ + val64 = strtoull(params, ¶ms, 10); + if (*params != ' ') + goto err; + params++; + + features = (int)val64; + for (i = 0; i < features; i++) { + r = -EINVAL; + if (!params) + goto err; + arg = strsep(¶ms, " "); + if (sscanf(arg, "journal_sectors:%u", &val) == 1) + tgt->u.integrity.journal_size = val * SECTOR_SIZE; + else if (sscanf(arg, "journal_watermark:%u", &val) == 1) + tgt->u.integrity.journal_watermark = val; + else if (sscanf(arg, "sectors_per_bit:%" PRIu64, &val64) == 1) { + if (val64 > UINT_MAX) + goto err; + /* overloaded value for bitmap mode */ + tgt->u.integrity.journal_watermark = (unsigned int)val64; + } else if (sscanf(arg, "commit_time:%u", &val) == 1) + tgt->u.integrity.journal_commit_time = val; + else if (sscanf(arg, "bitmap_flush_interval:%u", &val) == 1) + /* overloaded value for bitmap mode */ + tgt->u.integrity.journal_commit_time = val; + else if (sscanf(arg, "interleave_sectors:%u", &val) == 1) + tgt->u.integrity.interleave_sectors = val; + else if (sscanf(arg, "block_size:%u", &val) == 1) + tgt->u.integrity.sector_size = val; + else if (sscanf(arg, "buffer_sectors:%u", &val) == 1) + tgt->u.integrity.buffer_sectors = val; + else if (!strncmp(arg, "internal_hash:", 14) && !integrity) { + str = &arg[14]; + arg = strsep(&str, ":"); + if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) { + integrity = strdup(arg); + if (!integrity) { + r = -ENOMEM; + goto err; + } + } + + if (str) { + len = crypt_hex_to_bytes(str, &str2, 1); + if (len < 0) { + r = len; + goto err; + } + + r = 0; + if (get_flags & DM_ACTIVE_CRYPT_KEY) { + vk = crypt_alloc_volume_key(len, str2); + if (!vk) + r = -ENOMEM; + } else if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) { + vk = crypt_alloc_volume_key(len, NULL); + if (!vk) + r = -ENOMEM; + } + crypt_safe_free(str2); + if (r < 0) + goto err; + } + } else if (!strncmp(arg, "meta_device:", 12) && !meta_device) { + if (get_flags & DM_ACTIVE_DEVICE) { + str = crypt_lookup_dev(&arg[12]); + r = device_alloc(cd, &meta_device, str); + free(str); + if (r < 0 && r != -ENOTBLK) + goto err; + } + } else if (!strncmp(arg, "journal_crypt:", 14) && !journal_crypt) { + str = &arg[14]; + arg = strsep(&str, ":"); + if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) { + journal_crypt = strdup(arg); + if (!journal_crypt) { + r = -ENOMEM; + goto err; + } + } + } else if (!strncmp(arg, "journal_mac:", 12) && !journal_integrity) { + str = &arg[12]; + arg = strsep(&str, ":"); + if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) { + journal_integrity = strdup(arg); + if (!journal_integrity) { + r = -ENOMEM; + goto err; + } + } + } else if (!strcmp(arg, "recalculate")) { + *act_flags |= CRYPT_ACTIVATE_RECALCULATE; + } else if (!strcmp(arg, "fix_padding")) { + tgt->u.integrity.fix_padding = true; + } else if (!strcmp(arg, "allow_discards")) { + *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + } else /* unknown option */ + goto err; + } + + /* All parameters should be processed */ + if (params && *params) { + r = -EINVAL; + goto err; + } + } + + if (data_device) + tgt->data_device = data_device; + if (meta_device) + tgt->u.integrity.meta_device = meta_device; + if (integrity) + tgt->u.integrity.integrity = integrity; + if (journal_crypt) + tgt->u.integrity.journal_crypt = journal_crypt; + if (journal_integrity) + tgt->u.integrity.journal_integrity = journal_integrity; + if (vk) + tgt->u.integrity.vk = vk; + return 0; +err: + device_free(cd, data_device); + device_free(cd, meta_device); + free(integrity); + free(journal_crypt); + free(journal_integrity); + crypt_free_volume_key(vk); + return r; +} + +static int _dm_target_query_linear(struct crypt_device *cd, struct dm_target *tgt, + uint32_t get_flags, char *params) +{ + uint64_t val64; + char *rdevice, *arg; + int r; + struct device *device = NULL; + + /* device */ + rdevice = strsep(¶ms, " "); + if (get_flags & DM_ACTIVE_DEVICE) { + arg = crypt_lookup_dev(rdevice); + r = device_alloc(cd, &device, arg); + free(arg); + if (r < 0 && r != -ENOTBLK) + return r; + } + + r = -EINVAL; + + /*offset */ + if (!params) + goto err; + val64 = strtoull(params, ¶ms, 10); + + /* params should be empty now */ + if (*params) + goto err; + + tgt->type = DM_LINEAR; + tgt->direction = TARGET_QUERY; + tgt->data_device = device; + tgt->u.linear.offset = val64; + + return 0; +err: + device_free(cd, device); + return r; +} + +static int _dm_target_query_error(struct crypt_device *cd, struct dm_target *tgt) +{ + tgt->type = DM_ERROR; + tgt->direction = TARGET_QUERY; + + return 0; +} + +static int _dm_target_query_zero(struct crypt_device *cd, struct dm_target *tgt) +{ + tgt->type = DM_ZERO; + tgt->direction = TARGET_QUERY; + + return 0; +} + +/* + * on error retval has to be negative + * + * also currently any _dm_target_query fn does not perform cleanup on error + */ +static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const uint64_t *start, + const uint64_t *length, const char *target_type, + char *params, uint32_t get_flags, uint32_t *act_flags) +{ + int r = -ENOTSUP; + + if (!strcmp(target_type, DM_CRYPT_TARGET)) + r = _dm_target_query_crypt(cd, get_flags, params, tgt, act_flags); + else if (!strcmp(target_type, DM_VERITY_TARGET)) + r = _dm_target_query_verity(cd, get_flags, params, tgt, act_flags); + else if (!strcmp(target_type, DM_INTEGRITY_TARGET)) + r = _dm_target_query_integrity(cd, get_flags, params, tgt, act_flags); + else if (!strcmp(target_type, DM_LINEAR_TARGET)) + r = _dm_target_query_linear(cd, tgt, get_flags, params); + else if (!strcmp(target_type, DM_ERROR_TARGET)) + r = _dm_target_query_error(cd, tgt); + else if (!strcmp(target_type, DM_ZERO_TARGET)) + r = _dm_target_query_zero(cd, tgt); + + if (!r) { + tgt->offset = *start; + tgt->size = *length; + } + + return r; +} + +static int _dm_query_device(struct crypt_device *cd, const char *name, + uint32_t get_flags, struct crypt_dm_active_device *dmd) +{ + struct dm_target *t; + struct dm_task *dmt; + struct dm_info dmi; + uint64_t start, length; + char *target_type, *params; + const char *tmp_uuid; + void *next = NULL; + int r = -EINVAL; + + t = &dmd->segment; - if (dm_init_context(cd)) - return -ENOTSUP; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) - goto out; - if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt)) + return r; + if (!dm_task_secure_data(dmt)) goto out; if (!dm_task_set_name(dmt, name)) goto out; @@ -1081,35 +2575,49 @@ int dm_query_device(struct crypt_device *cd, const char *name, goto out; } - next = dm_get_next_target(dmt, next, &start, &length, - &target_type, ¶ms); - - if (!target_type || start != 0 || next) + if (dmi.target_count <= 0) { + r = -EINVAL; goto out; + } - if (!strcmp(target_type, DM_CRYPT_TARGET)) { - r = _dm_query_crypt(get_flags, &dmi, params, dmd); - } else if (!strcmp(target_type, DM_VERITY_TARGET)) { - r = _dm_query_verity(get_flags, &dmi, params, dmd); - if (r < 0) - goto out; - r = _dm_status_verity_ok(name); - if (r < 0) - goto out; - if (r == 0) - dmd->flags |= CRYPT_ACTIVATE_CORRUPTED; - r = 0; - } else + /* Never allow to return empty key */ + if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi.suspended) { + log_dbg(cd, "Cannot read volume key while suspended."); r = -EINVAL; + goto out; + } - if (r < 0) + r = dm_targets_allocate(&dmd->segment, dmi.target_count); + if (r) goto out; - dmd->size = length; + do { + next = dm_get_next_target(dmt, next, &start, &length, + &target_type, ¶ms); + + r = dm_target_query(cd, t, &start, &length, target_type, params, get_flags, &dmd->flags); + if (!r && t->type == DM_VERITY) { + r = _dm_status_verity_ok(cd, name); + if (r == 0) + dmd->flags |= CRYPT_ACTIVATE_CORRUPTED; + } + + if (r < 0) { + if (r != -ENOTSUP) + log_err(cd, _("Failed to query dm-%s segment."), target_type); + goto out; + } + + dmd->size += length; + t = t->next; + } while (next && t); if (dmi.read_only) dmd->flags |= CRYPT_ACTIVATE_READONLY; + if (dmi.suspended) + dmd->flags |= CRYPT_ACTIVATE_SUSPENDED; + tmp_uuid = dm_task_get_uuid(dmt); if (!tmp_uuid) dmd->flags |= CRYPT_ACTIVATE_NO_UUID; @@ -1118,11 +2626,145 @@ int dm_query_device(struct crypt_device *cd, const char *name, dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN); } + dmd->holders = 0; +#if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS) + if (get_flags & DM_ACTIVE_HOLDERS) + dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) || + dm_device_has_holders(dmi.major, dmi.minor)); +#endif + r = (dmi.open_count > 0); out: if (dmt) dm_task_destroy(dmt); + if (r < 0) + dm_targets_free(cd, dmd); + + return r; +} + +int dm_query_device(struct crypt_device *cd, const char *name, + uint32_t get_flags, struct crypt_dm_active_device *dmd) +{ + int r; + + if (!dmd) + return -EINVAL; + + memset(dmd, 0, sizeof(*dmd)); + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + r = _dm_query_device(cd, name, get_flags, dmd); + + dm_exit_context(); + return r; +} + +static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps, char **names, size_t names_offset, size_t names_length) +{ +#if HAVE_DECL_DM_DEVICE_GET_NAME + struct crypt_dm_active_device dmd; + char dmname[PATH_MAX]; + unsigned i; + int r, major, minor, count = 0; + + if (!prefix || !deps) + return -EINVAL; + + for (i = 0; i < deps->count; i++) { + major = major(deps->device[i]); + if (!dm_is_dm_major(major)) + continue; + + minor = minor(deps->device[i]); + if (!dm_device_get_name(major, minor, 0, dmname, PATH_MAX)) + return -EINVAL; + + memset(&dmd, 0, sizeof(dmd)); + r = _dm_query_device(cd, dmname, DM_ACTIVE_UUID, &dmd); + if (r < 0) + continue; + + if (!dmd.uuid || + strncmp(prefix, dmd.uuid, strlen(prefix)) || + crypt_string_in(dmname, names, names_length)) + *dmname = '\0'; + + dm_targets_free(cd, &dmd); + free(CONST_CAST(void*)dmd.uuid); + + if ((size_t)count >= (names_length - names_offset)) + return -ENOMEM; + + if (*dmname && !(names[names_offset + count++] = strdup(dmname))) + return -ENOMEM; + } + + return count; +#else + return -EINVAL; +#endif +} + +int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, char **names, size_t names_length) +{ + struct dm_task *dmt; + struct dm_info dmi; + struct dm_deps *deps; + int r = -EINVAL; + size_t i, last = 0, offset = 0; + + if (!name || !names_length || !names) + return -EINVAL; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + while (name) { + if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) + goto out; + if (!dm_task_set_name(dmt, name)) + goto out; + + r = -ENODEV; + if (!dm_task_run(dmt)) + goto out; + + r = -EINVAL; + if (!dm_task_get_info(dmt, &dmi)) + goto out; + if (!(deps = dm_task_get_deps(dmt))) + goto out; + + r = -ENODEV; + if (!dmi.exists) + goto out; + + r = _process_deps(cd, prefix, deps, names, offset, names_length - 1); + if (r < 0) + goto out; + + dm_task_destroy(dmt); + dmt = NULL; + + offset += r; + name = names[last++]; + } + + r = 0; +out: + if (r < 0) { + for (i = 0; i < names_length - 1; i++) + free(names[i]); + *names = NULL; + } + + if (dmt) + dm_task_destroy(dmt); + dm_exit_context(); return r; } @@ -1135,7 +2777,7 @@ static int _dm_message(const char *name, const char *msg) if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG))) return 0; - if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt)) + if (!dm_task_secure_data(dmt)) goto out; if (name && !dm_task_set_name(dmt, name)) @@ -1148,51 +2790,78 @@ static int _dm_message(const char *name, const char *msg) goto out; r = dm_task_run(dmt); - - out: +out: dm_task_destroy(dmt); return r; } -int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name) +int dm_suspend_device(struct crypt_device *cd, const char *name, uint32_t dmflags) { + uint32_t dmt_flags; int r = -ENOTSUP; - if (dm_init_context(cd)) - return -ENOTSUP; + if (dm_init_context(cd, DM_UNKNOWN)) + return r; - if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED)) - goto out; + if (dmflags & DM_SUSPEND_WIPE_KEY) { + if (dm_flags(cd, DM_CRYPT, &dmt_flags)) + goto out; - if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0)) { - r = -EINVAL; - goto out; + if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED)) + goto out; } - if (!_dm_message(name, "key wipe")) { - _dm_simple(DM_DEVICE_RESUME, name, 1); - r = -EINVAL; + r = -EINVAL; + + if (!_dm_simple(DM_DEVICE_SUSPEND, name, dmflags)) goto out; + + if (dmflags & DM_SUSPEND_WIPE_KEY) { + if (!_dm_message(name, "key wipe")) { + _dm_resume_device(name, 0); + goto out; + } } + r = 0; out: dm_exit_context(); return r; } +int dm_resume_device(struct crypt_device *cd, const char *name, uint32_t dmflags) +{ + int r; + + if (dm_init_context(cd, DM_UNKNOWN)) + return -ENOTSUP; + + r = _dm_resume_device(name, dmflags); + + dm_exit_context(); + + return r; +} + int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name, - size_t key_size, const char *key) + const struct volume_key *vk) { - int msg_size = key_size * 2 + 10; // key set + uint32_t dmt_flags; + int msg_size; char *msg = NULL; int r = -ENOTSUP; - if (dm_init_context(cd)) + if (dm_init_context(cd, DM_CRYPT) || dm_flags(cd, DM_CRYPT, &dmt_flags)) return -ENOTSUP; - if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED)) + if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED)) goto out; + if (vk->key_description) + msg_size = strlen(vk->key_description) + int_log10(vk->keylength) + 18; + else + msg_size = vk->keylength * 2 + 10; // key set + msg = crypt_safe_alloc(msg_size); if (!msg) { r = -ENOMEM; @@ -1200,10 +2869,13 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name, } strcpy(msg, "key set "); - hex_key(&msg[8], key_size, key); + if (vk->key_description) + snprintf(msg + 8, msg_size - 8, ":%zu:logon:%s", vk->keylength, vk->key_description); + else + hex_key(&msg[8], vk->keylength, vk->key); if (!_dm_message(name, msg) || - !_dm_simple(DM_DEVICE_RESUME, name, 1)) { + _dm_resume_device(name, 0)) { r = -EINVAL; goto out; } @@ -1219,7 +2891,7 @@ const char *dm_get_dir(void) return dm_dir(); } -int dm_is_dm_device(int major, int minor) +int dm_is_dm_device(int major) { return dm_is_dm_major((uint32_t)major); } @@ -1228,3 +2900,147 @@ int dm_is_dm_kernel_name(const char *name) { return strncmp(name, "dm-", 3) ? 0 : 1; } + +int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, struct volume_key *vk, const char *cipher, + uint64_t iv_offset, uint64_t data_offset, const char *integrity, uint32_t tag_size, + uint32_t sector_size) +{ + int r = -EINVAL; + + /* free on error */ + char *dm_integrity = NULL; + + if (tag_size) { + /* Space for IV metadata only */ + dm_integrity = strdup(integrity ?: "none"); + if (!dm_integrity) { + r = -ENOMEM; + goto err; + } + } + + tgt->data_device = data_device; + + tgt->type = DM_CRYPT; + tgt->direction = TARGET_SET; + tgt->u.crypt.vk = vk; + tgt->offset = seg_offset; + tgt->size = seg_size; + + tgt->u.crypt.cipher = cipher; + tgt->u.crypt.integrity = dm_integrity; + tgt->u.crypt.iv_offset = iv_offset; + tgt->u.crypt.offset = data_offset; + tgt->u.crypt.tag_size = tag_size; + tgt->u.crypt.sector_size = sector_size; + + return 0; +err: + free(dm_integrity); + + return r; +} + +int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, struct device *hash_device, struct device *fec_device, + const char *root_hash, uint32_t root_hash_size, const char *root_hash_sig_key_desc, + uint64_t hash_offset_block, uint64_t hash_blocks, struct crypt_params_verity *vp) +{ + if (!data_device || !hash_device || !vp) + return -EINVAL; + + tgt->type = DM_VERITY; + tgt->direction = TARGET_SET; + tgt->offset = seg_offset; + tgt->size = seg_size; + tgt->data_device = data_device; + + tgt->u.verity.hash_device = hash_device; + tgt->u.verity.fec_device = fec_device; + tgt->u.verity.root_hash = root_hash; + tgt->u.verity.root_hash_size = root_hash_size; + tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc; + tgt->u.verity.hash_offset = hash_offset_block; + tgt->u.verity.fec_offset = vp->fec_area_offset / vp->hash_block_size; + tgt->u.verity.hash_blocks = hash_blocks; + tgt->u.verity.vp = vp; + + return 0; +} + +int dm_integrity_target_set(struct crypt_device *cd, + struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *meta_device, + struct device *data_device, uint64_t tag_size, uint64_t offset, + uint32_t sector_size, struct volume_key *vk, + struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key, + const struct crypt_params_integrity *ip) +{ + uint32_t dmi_flags; + + if (!data_device) + return -EINVAL; + + _dm_check_versions(cd, DM_INTEGRITY); + + tgt->type = DM_INTEGRITY; + tgt->direction = TARGET_SET; + tgt->offset = seg_offset; + tgt->size = seg_size; + tgt->data_device = data_device; + if (meta_device != data_device) + tgt->u.integrity.meta_device = meta_device; + tgt->u.integrity.tag_size = tag_size; + tgt->u.integrity.offset = offset; + tgt->u.integrity.sector_size = sector_size; + + tgt->u.integrity.vk = vk; + tgt->u.integrity.journal_crypt_key = journal_crypt_key; + tgt->u.integrity.journal_integrity_key = journal_mac_key; + + if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) && + (dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED) && + !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING)) + tgt->u.integrity.fix_padding = true; + + if (ip) { + tgt->u.integrity.journal_size = ip->journal_size; + tgt->u.integrity.journal_watermark = ip->journal_watermark; + tgt->u.integrity.journal_commit_time = ip->journal_commit_time; + tgt->u.integrity.interleave_sectors = ip->interleave_sectors; + tgt->u.integrity.buffer_sectors = ip->buffer_sectors; + tgt->u.integrity.journal_integrity = ip->journal_integrity; + tgt->u.integrity.journal_crypt = ip->journal_crypt; + tgt->u.integrity.integrity = ip->integrity; + } + + return 0; +} + +int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, uint64_t data_offset) +{ + if (!data_device) + return -EINVAL; + + tgt->type = DM_LINEAR; + tgt->direction = TARGET_SET; + tgt->offset = seg_offset; + tgt->size = seg_size; + tgt->data_device = data_device; + + tgt->u.linear.offset = data_offset; + + return 0; +} + +int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size) +{ + tgt->type = DM_ZERO; + tgt->direction = TARGET_SET; + tgt->offset = seg_offset; + tgt->size = seg_size; + + return 0; +} diff --git a/lib/loopaes/Makefile.am b/lib/loopaes/Makefile.am deleted file mode 100644 index 0687c40..0000000 --- a/lib/loopaes/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -moduledir = $(libdir)/cryptsetup - -noinst_LTLIBRARIES = libloopaes.la - -libloopaes_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ - -libloopaes_la_SOURCES = \ - loopaes.c \ - loopaes.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - diff --git a/lib/loopaes/Makefile.in b/lib/loopaes/Makefile.in deleted file mode 100644 index 24747de..0000000 --- a/lib/loopaes/Makefile.in +++ /dev/null @@ -1,645 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib/loopaes -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libloopaes_la_LIBADD = -am_libloopaes_la_OBJECTS = libloopaes_la-loopaes.lo -libloopaes_la_OBJECTS = $(am_libloopaes_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libloopaes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libloopaes_la_CFLAGS) \ - $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libloopaes_la_SOURCES) -DIST_SOURCES = $(libloopaes_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -moduledir = $(libdir)/cryptsetup -noinst_LTLIBRARIES = libloopaes.la -libloopaes_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ -libloopaes_la_SOURCES = \ - loopaes.c \ - loopaes.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/loopaes/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/loopaes/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libloopaes.la: $(libloopaes_la_OBJECTS) $(libloopaes_la_DEPENDENCIES) $(EXTRA_libloopaes_la_DEPENDENCIES) - $(AM_V_CCLD)$(libloopaes_la_LINK) $(libloopaes_la_OBJECTS) $(libloopaes_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libloopaes_la-loopaes.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libloopaes_la-loopaes.lo: loopaes.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libloopaes_la_CFLAGS) $(CFLAGS) -MT libloopaes_la-loopaes.lo -MD -MP -MF $(DEPDIR)/libloopaes_la-loopaes.Tpo -c -o libloopaes_la-loopaes.lo `test -f 'loopaes.c' || echo '$(srcdir)/'`loopaes.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libloopaes_la-loopaes.Tpo $(DEPDIR)/libloopaes_la-loopaes.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='loopaes.c' object='libloopaes_la-loopaes.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libloopaes_la_CFLAGS) $(CFLAGS) -c -o libloopaes_la-loopaes.lo `test -f 'loopaes.c' || echo '$(srcdir)/'`loopaes.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/loopaes/loopaes.c b/lib/loopaes/loopaes.c index 28a70b8..92090aa 100644 --- a/lib/loopaes/loopaes.c +++ b/lib/loopaes/loopaes.c @@ -1,8 +1,8 @@ /* * loop-AES compatible volume handling * - * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2011-2013, Milan Broz + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -81,18 +81,18 @@ static int hash_keys(struct crypt_device *cd, const char *hash_name; char tweak, *key_ptr; unsigned int i; - int r; + int r = 0; hash_name = hash_override ?: get_hash(key_len_output); tweak = get_tweak(keys_count); if (!keys_count || !key_len_output || !hash_name || !key_len_input) { - log_err(cd, _("Key processing error (using hash %s).\n"), + log_err(cd, _("Key processing error (using hash %s)."), hash_name ?: "[none]"); return -EINVAL; } - *vk = crypt_alloc_volume_key(key_len_output * keys_count, NULL); + *vk = crypt_alloc_volume_key((size_t)key_len_output * keys_count, NULL); if (!*vk) return -ENOMEM; @@ -137,13 +137,13 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd, unsigned int key_lengths[LOOPAES_KEYS_MAX]; unsigned int i, key_index, key_len, offset; - log_dbg("Parsing loop-AES keyfile of size %zu.", buffer_len); + log_dbg(cd, "Parsing loop-AES keyfile of size %zu.", buffer_len); if (!buffer_len) return -EINVAL; if (keyfile_is_gpg(buffer, buffer_len)) { - log_err(cd, _("Detected not yet supported GPG encrypted keyfile.\n")); + log_err(cd, _("Detected not yet supported GPG encrypted keyfile.")); log_std(cd, _("Please use gpg --decrypt | cryptsetup --keyfile=- ...\n")); return -EINVAL; } @@ -164,8 +164,8 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd, key_lengths[key_index]++; } if (offset == buffer_len) { - log_dbg("Unterminated key #%d in keyfile.", key_index); - log_err(cd, _("Incompatible loop-AES keyfile detected.\n")); + log_dbg(cd, "Unterminated key #%d in keyfile.", key_index); + log_err(cd, _("Incompatible loop-AES keyfile detected.")); return -EINVAL; } while (offset < buffer_len && !buffer[offset]) @@ -177,7 +177,7 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd, key_len = key_lengths[0]; for (i = 0; i < key_index; i++) if (!key_lengths[i] || (key_lengths[i] != key_len)) { - log_dbg("Unexpected length %d of key #%d (should be %d).", + log_dbg(cd, "Unexpected length %d of key #%d (should be %d).", key_lengths[i], i, key_len); key_len = 0; break; @@ -185,11 +185,11 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd, if (offset != buffer_len || key_len == 0 || (key_index != 1 && key_index !=64 && key_index != 65)) { - log_err(cd, _("Incompatible loop-AES keyfile detected.\n")); + log_err(cd, _("Incompatible loop-AES keyfile detected.")); return -EINVAL; } - log_dbg("Keyfile: %d keys of length %d.", key_index, key_len); + log_dbg(cd, "Keyfile: %d keys of length %d.", key_index, key_len); *keys_count = key_index; return hash_keys(cd, vk, hash, keys, key_index, @@ -203,24 +203,15 @@ int LOOPAES_activate(struct crypt_device *cd, struct volume_key *vk, uint32_t flags) { - char *cipher = NULL; - uint32_t req_flags; int r; + uint32_t req_flags, dmc_flags; + char *cipher = NULL; struct crypt_dm_active_device dmd = { - .target = DM_CRYPT, - .size = 0, - .flags = flags, - .data_device = crypt_data_device(cd), - .u.crypt = { - .cipher = NULL, - .vk = vk, - .offset = crypt_get_data_offset(cd), - .iv_offset = crypt_get_iv_offset(cd), - } + .flags = flags, }; - r = device_block_adjust(cd, dmd.data_device, DEV_EXCL, - dmd.u.crypt.offset, &dmd.size, &dmd.flags); + r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL, + crypt_get_data_offset(cd), &dmd.size, &dmd.flags); if (r) return r; @@ -234,17 +225,29 @@ int LOOPAES_activate(struct crypt_device *cd, if (r < 0) return -ENOMEM; - dmd.u.crypt.cipher = cipher; - log_dbg("Trying to activate loop-AES device %s using cipher %s.", - name, dmd.u.crypt.cipher); + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), + vk, cipher, crypt_get_iv_offset(cd), + crypt_get_data_offset(cd), crypt_get_integrity(cd), + crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); - r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd, 0); + if (r) { + free(cipher); + return r; + } + + log_dbg(cd, "Trying to activate loop-AES device %s using cipher %s.", + name, cipher); - if (r < 0 && !(dm_flags() & req_flags)) { - log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n")); + r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd); + + if (r < 0 && !dm_flags(cd, DM_CRYPT, &dmc_flags) && + (dmc_flags & req_flags) != req_flags) { + log_err(cd, _("Kernel does not support loop-AES compatible mapping.")); r = -ENOTSUP; } + dm_targets_free(cd, &dmd); free(cipher); + return r; } diff --git a/lib/loopaes/loopaes.h b/lib/loopaes/loopaes.h index 00d1a87..5f6e93f 100644 --- a/lib/loopaes/loopaes.h +++ b/lib/loopaes/loopaes.h @@ -1,8 +1,8 @@ /* * loop-AES compatible volume handling * - * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2011-2013, Milan Broz + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,7 @@ #ifndef _LOOPAES_H #define _LOOPAES_H +#include #include struct crypt_device; diff --git a/lib/luks1/Makefile.am b/lib/luks1/Makefile.am deleted file mode 100644 index 5d6800e..0000000 --- a/lib/luks1/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -moduledir = $(libdir)/cryptsetup - -noinst_LTLIBRARIES = libluks1.la - -libluks1_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ - -libluks1_la_SOURCES = \ - af.c \ - keymanage.c \ - keyencryption.c \ - af.h \ - luks.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - diff --git a/lib/luks1/Makefile.in b/lib/luks1/Makefile.in deleted file mode 100644 index f5d3fde..0000000 --- a/lib/luks1/Makefile.in +++ /dev/null @@ -1,665 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib/luks1 -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libluks1_la_LIBADD = -am_libluks1_la_OBJECTS = libluks1_la-af.lo libluks1_la-keymanage.lo \ - libluks1_la-keyencryption.lo -libluks1_la_OBJECTS = $(am_libluks1_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libluks1_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libluks1_la_CFLAGS) \ - $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libluks1_la_SOURCES) -DIST_SOURCES = $(libluks1_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -moduledir = $(libdir)/cryptsetup -noinst_LTLIBRARIES = libluks1.la -libluks1_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ -libluks1_la_SOURCES = \ - af.c \ - keymanage.c \ - keyencryption.c \ - af.h \ - luks.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/luks1/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/luks1/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libluks1.la: $(libluks1_la_OBJECTS) $(libluks1_la_DEPENDENCIES) $(EXTRA_libluks1_la_DEPENDENCIES) - $(AM_V_CCLD)$(libluks1_la_LINK) $(libluks1_la_OBJECTS) $(libluks1_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libluks1_la-af.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libluks1_la-keyencryption.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libluks1_la-keymanage.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libluks1_la-af.lo: af.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -MT libluks1_la-af.lo -MD -MP -MF $(DEPDIR)/libluks1_la-af.Tpo -c -o libluks1_la-af.lo `test -f 'af.c' || echo '$(srcdir)/'`af.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libluks1_la-af.Tpo $(DEPDIR)/libluks1_la-af.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='af.c' object='libluks1_la-af.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -c -o libluks1_la-af.lo `test -f 'af.c' || echo '$(srcdir)/'`af.c - -libluks1_la-keymanage.lo: keymanage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -MT libluks1_la-keymanage.lo -MD -MP -MF $(DEPDIR)/libluks1_la-keymanage.Tpo -c -o libluks1_la-keymanage.lo `test -f 'keymanage.c' || echo '$(srcdir)/'`keymanage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libluks1_la-keymanage.Tpo $(DEPDIR)/libluks1_la-keymanage.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keymanage.c' object='libluks1_la-keymanage.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -c -o libluks1_la-keymanage.lo `test -f 'keymanage.c' || echo '$(srcdir)/'`keymanage.c - -libluks1_la-keyencryption.lo: keyencryption.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -MT libluks1_la-keyencryption.lo -MD -MP -MF $(DEPDIR)/libluks1_la-keyencryption.Tpo -c -o libluks1_la-keyencryption.lo `test -f 'keyencryption.c' || echo '$(srcdir)/'`keyencryption.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libluks1_la-keyencryption.Tpo $(DEPDIR)/libluks1_la-keyencryption.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyencryption.c' object='libluks1_la-keyencryption.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libluks1_la_CFLAGS) $(CFLAGS) -c -o libluks1_la-keyencryption.lo `test -f 'keyencryption.c' || echo '$(srcdir)/'`keyencryption.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/luks1/af.c b/lib/luks1/af.c index 835d997..a781376 100644 --- a/lib/luks1/af.c +++ b/lib/luks1/af.c @@ -1,11 +1,11 @@ /* * AFsplitter - Anti forensic information splitter * - * Copyright (C) 2004, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. * * AFsplitter diffuses information over a large stripe of data, - * therefor supporting secure data destruction. + * therefore supporting secure data destruction. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "internal.h" #include "af.h" @@ -34,7 +33,7 @@ static void XORblock(const char *src1, const char *src2, char *dst, size_t n) { size_t j; - for(j = 0; j < n; ++j) + for (j = 0; j < n; j++) dst[j] = src1[j] ^ src2[j]; } @@ -45,7 +44,7 @@ static int hash_buf(const char *src, char *dst, uint32_t iv, char *iv_char = (char *)&iv; int r; - iv = htonl(iv); + iv = be32_to_cpu(iv); if (crypt_hash_init(&hd, hash_name)) return -EINVAL; @@ -61,34 +60,38 @@ out: return r; } -/* diffuse: Information spreading over the whole dataset with +/* + * diffuse: Information spreading over the whole dataset with * the help of hash function. */ - static int diffuse(char *src, char *dst, size_t size, const char *hash_name) { - int hash_size = crypt_hash_size(hash_name); + int r, hash_size = crypt_hash_size(hash_name); unsigned int digest_size; unsigned int i, blocks, padding; if (hash_size <= 0) - return 1; + return -EINVAL; digest_size = hash_size; blocks = size / digest_size; padding = size % digest_size; - for (i = 0; i < blocks; i++) - if(hash_buf(src + digest_size * i, + for (i = 0; i < blocks; i++) { + r = hash_buf(src + digest_size * i, dst + digest_size * i, - i, (size_t)digest_size, hash_name)) - return 1; + i, (size_t)digest_size, hash_name); + if (r < 0) + return r; + } - if(padding) - if(hash_buf(src + digest_size * i, + if (padding) { + r = hash_buf(src + digest_size * i, dst + digest_size * i, - i, (size_t)padding, hash_name)) - return 1; + i, (size_t)padding, hash_name); + if (r < 0) + return r; + } return 0; } @@ -98,53 +101,57 @@ static int diffuse(char *src, char *dst, size_t size, const char *hash_name) * blocknumbers. The same blocksize and blocknumbers values * must be supplied to AF_merge to recover information. */ - -int AF_split(char *src, char *dst, size_t blocksize, - unsigned int blocknumbers, const char *hash) +int AF_split(struct crypt_device *ctx, const char *src, char *dst, + size_t blocksize, unsigned int blocknumbers, const char *hash) { unsigned int i; char *bufblock; - int r = -EINVAL; + int r; - if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM; + bufblock = crypt_safe_alloc(blocksize); + if (!bufblock) + return -ENOMEM; /* process everything except the last block */ - for(i=0; i - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. * * AFsplitter diffuses information over a large stripe of data, - * therefor supporting secure data destruction. + * therefore supporting secure data destruction. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,6 +24,8 @@ #ifndef INCLUDED_CRYPTSETUP_LUKS_AF_H #define INCLUDED_CRYPTSETUP_LUKS_AF_H +#include + /* * AF_split operates on src and produces information split data in * dst. src is assumed to be of the length blocksize. The data stripe @@ -37,8 +39,26 @@ * On error, both functions return -1, 0 otherwise. */ -int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash); -int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash); +int AF_split(struct crypt_device *ctx, const char *src, char *dst, + size_t blocksize, unsigned int blocknumbers, const char *hash); +int AF_merge(struct crypt_device *ctx, const char *src, char *dst, size_t blocksize, + unsigned int blocknumbers, const char *hash); size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers); +int LUKS_encrypt_to_storage( + char *src, size_t srcLength, + const char *cipher, + const char *cipher_mode, + struct volume_key *vk, + unsigned int sector, + struct crypt_device *ctx); + +int LUKS_decrypt_from_storage( + char *dst, size_t dstLength, + const char *cipher, + const char *cipher_mode, + struct volume_key *vk, + unsigned int sector, + struct crypt_device *ctx); + #endif diff --git a/lib/luks1/keyencryption.c b/lib/luks1/keyencryption.c index 3bc9c33..fdab63a 100644 --- a/lib/luks1/keyencryption.c +++ b/lib/luks1/keyencryption.c @@ -1,9 +1,9 @@ /* * LUKS - Linux Unified Key Setup * - * Copyright (C) 2004-2006, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2014, Milan Broz + * Copyright (C) 2004-2006 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,58 +21,59 @@ */ #include -#include +#include #include +#include #include "luks.h" +#include "af.h" #include "internal.h" static void _error_hint(struct crypt_device *ctx, const char *device, const char *cipher, const char *mode, size_t keyLength) { - char cipher_spec[MAX_CIPHER_LEN * 3]; + char *c, cipher_spec[MAX_CIPHER_LEN * 3]; if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0) return; log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n" - "Check that kernel supports %s cipher (check syslog for more info).\n"), + "Check that kernel supports %s cipher (check syslog for more info)."), device, cipher_spec); if (!strncmp(mode, "xts", 3) && (keyLength != 256 && keyLength != 512)) - log_err(ctx, _("Key size in XTS mode must be 256 or 512 bits.\n")); + log_err(ctx, _("Key size in XTS mode must be 256 or 512 bits.")); + else if (!(c = strchr(mode, '-')) || strlen(c) < 4) + log_err(ctx, _("Cipher specification should be in [cipher]-[mode]-[iv] format.")); } static int LUKS_endec_template(char *src, size_t srcLength, const char *cipher, const char *cipher_mode, struct volume_key *vk, unsigned int sector, - ssize_t (*func)(int, int, void *, size_t), + ssize_t (*func)(int, size_t, size_t, void *, size_t), int mode, struct crypt_device *ctx) { char name[PATH_MAX], path[PATH_MAX]; char cipher_spec[MAX_CIPHER_LEN * 3]; struct crypt_dm_active_device dmd = { - .target = DM_CRYPT, - .uuid = NULL, - .flags = CRYPT_ACTIVATE_PRIVATE, - .data_device = crypt_metadata_device(ctx), - .u.crypt = { - .cipher = cipher_spec, - .vk = vk, - .offset = sector, - .iv_offset = 0, - } + .flags = CRYPT_ACTIVATE_PRIVATE, }; - int r, bsize, devfd = -1; + int r, devfd = -1, remove_dev = 0; + size_t bsize, keyslot_alignment, alignment; - log_dbg("Using dmcrypt to access keyslot area."); + log_dbg(ctx, "Using dmcrypt to access keyslot area."); - bsize = device_block_size(dmd.data_device); - if (bsize <= 0) + bsize = device_block_size(ctx, crypt_metadata_device(ctx)); + alignment = device_alignment(crypt_metadata_device(ctx)); + if (!bsize || !alignment) return -EINVAL; - dmd.size = size_round_up(srcLength, bsize) / SECTOR_SIZE; + if (bsize > LUKS_ALIGN_KEYSLOTS) + keyslot_alignment = LUKS_ALIGN_KEYSLOTS; + else + keyslot_alignment = bsize; + dmd.size = size_round_up(srcLength, keyslot_alignment) / SECTOR_SIZE; if (mode == O_RDONLY) dmd.flags |= CRYPT_ACTIVATE_READONLY; @@ -84,45 +85,55 @@ static int LUKS_endec_template(char *src, size_t srcLength, if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, cipher_mode) < 0) return -ENOMEM; - r = device_block_adjust(ctx, dmd.data_device, DEV_OK, - dmd.u.crypt.offset, &dmd.size, &dmd.flags); + r = device_block_adjust(ctx, crypt_metadata_device(ctx), DEV_OK, + sector, &dmd.size, &dmd.flags); if (r < 0) { - log_err(ctx, _("Device %s doesn't exist or access denied.\n"), - device_path(dmd.data_device)); + log_err(ctx, _("Device %s does not exist or access denied."), + device_path(crypt_metadata_device(ctx))); return -EIO; } if (mode != O_RDONLY && dmd.flags & CRYPT_ACTIVATE_READONLY) { - log_err(ctx, _("Cannot write to device %s, permission denied.\n"), - device_path(dmd.data_device)); + log_err(ctx, _("Cannot write to device %s, permission denied."), + device_path(crypt_metadata_device(ctx))); return -EACCES; } - r = dm_create_device(ctx, name, "TEMP", &dmd, 0); + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, + crypt_metadata_device(ctx), vk, cipher_spec, 0, sector, + NULL, 0, SECTOR_SIZE); + if (r) + goto out; + + r = dm_create_device(ctx, name, "TEMP", &dmd); if (r < 0) { if (r != -EACCES && r != -ENOTSUP) - _error_hint(ctx, device_path(dmd.data_device), + _error_hint(ctx, device_path(crypt_metadata_device(ctx)), cipher, cipher_mode, vk->keylength * 8); - return -EIO; + r = -EIO; + goto out; } + remove_dev = 1; devfd = open(path, mode | O_DIRECT | O_SYNC); if (devfd == -1) { - log_err(ctx, _("Failed to open temporary keystore device.\n")); + log_err(ctx, _("Failed to open temporary keystore device.")); r = -EIO; goto out; } - r = func(devfd, bsize, src, srcLength); + r = func(devfd, bsize, alignment, src, srcLength); if (r < 0) { - log_err(ctx, _("Failed to access temporary keystore device.\n")); + log_err(ctx, _("Failed to access temporary keystore device.")); r = -EIO; } else r = 0; out: - if(devfd != -1) + dm_targets_free(ctx, &dmd); + if (devfd != -1) close(devfd); - dm_remove_device(ctx, name, 1, dmd.size); + if (remove_dev) + dm_remove_device(ctx, name, CRYPT_DEACTIVATE_FORCE); return r; } @@ -133,20 +144,19 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength, unsigned int sector, struct crypt_device *ctx) { - struct device *device = crypt_metadata_device(ctx); struct crypt_storage *s; - int devfd = -1, bsize, r = 0; + int devfd, r = 0; /* Only whole sector writes supported */ - if (srcLength % SECTOR_SIZE) + if (MISALIGNED_512(srcLength)) return -EINVAL; /* Encrypt buffer */ - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) - log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).", + log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).", cipher, cipher_mode, r); /* Fallback to old temporary dmcrypt device */ @@ -160,9 +170,9 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength, return r; } - log_dbg("Using userspace crypto wrapper to access keyslot area."); + log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area."); - r = crypt_storage_encrypt(s, 0, srcLength / SECTOR_SIZE, src); + r = crypt_storage_encrypt(s, 0, srcLength, src); crypt_storage_destroy(s); if (r) @@ -171,24 +181,23 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength, r = -EIO; /* Write buffer to device */ - bsize = device_block_size(device); - if (bsize <= 0) - goto out; - - devfd = device_open(device, O_RDWR); - if (devfd == -1) + if (device_is_locked(device)) + devfd = device_open_locked(ctx, device, O_RDWR); + else + devfd = device_open(ctx, device, O_RDWR); + if (devfd < 0) goto out; - if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 || - write_blockwise(devfd, bsize, src, srcLength) == -1) + if (write_lseek_blockwise(devfd, device_block_size(ctx, device), + device_alignment(device), src, srcLength, + sector * SECTOR_SIZE) < 0) goto out; r = 0; out: - if(devfd != -1) - close(devfd); + device_sync(ctx, device); if (r) - log_err(ctx, _("IO error while encrypting keyslot.\n")); + log_err(ctx, _("IO error while encrypting keyslot.")); return r; } @@ -202,16 +211,17 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength, { struct device *device = crypt_metadata_device(ctx); struct crypt_storage *s; - int devfd = -1, bsize, r = 0; + struct stat st; + int devfd, r = 0; /* Only whole sector reads supported */ - if (dstLength % SECTOR_SIZE) + if (MISALIGNED_512(dstLength)) return -EINVAL; - r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength); + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); if (r) - log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).", + log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).", cipher, cipher_mode, r); /* Fallback to old temporary dmcrypt device */ @@ -225,35 +235,33 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength, return r; } - log_dbg("Using userspace crypto wrapper to access keyslot area."); - - r = -EIO; + log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area."); /* Read buffer from device */ - bsize = device_block_size(device); - if (bsize <= 0) - goto bad; - - devfd = device_open(device, O_RDONLY); - if (devfd == -1) - goto bad; + if (device_is_locked(device)) + devfd = device_open_locked(ctx, device, O_RDONLY); + else + devfd = device_open(ctx, device, O_RDONLY); + if (devfd < 0) { + log_err(ctx, _("Cannot open device %s."), device_path(device)); + crypt_storage_destroy(s); + return -EIO; + } - if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 || - read_blockwise(devfd, bsize, dst, dstLength) == -1) - goto bad; + if (read_lseek_blockwise(devfd, device_block_size(ctx, device), + device_alignment(device), dst, dstLength, + sector * SECTOR_SIZE) < 0) { + if (!fstat(devfd, &st) && (st.st_size < (off_t)dstLength)) + log_err(ctx, _("Device %s is too small."), device_path(device)); + else + log_err(ctx, _("IO error while decrypting keyslot.")); - close(devfd); + crypt_storage_destroy(s); + return -EIO; + } /* Decrypt buffer */ - r = crypt_storage_decrypt(s, 0, dstLength / SECTOR_SIZE, dst); - crypt_storage_destroy(s); - - return r; -bad: - if(devfd != -1) - close(devfd); - - log_err(ctx, _("IO error while decrypting keyslot.\n")); + r = crypt_storage_decrypt(s, 0, dstLength, dst); crypt_storage_destroy(s); return r; diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c index 8ae2af8..a08ff50 100644 --- a/lib/luks1/keymanage.c +++ b/lib/luks1/keymanage.c @@ -1,9 +1,9 @@ /* * LUKS - Linux Unified Key Setup * - * Copyright (C) 2004-2006, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2013-2014, Milan Broz + * Copyright (C) 2004-2006 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2013-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,24 +36,7 @@ #include "af.h" #include "internal.h" -/* Get size of struct luks_phdr with all keyslots material space */ -static size_t LUKS_device_sectors(size_t keyLen) -{ - size_t keyslot_sectors, sector; - int i; - - keyslot_sectors = AF_split_sectors(keyLen, LUKS_STRIPES); - sector = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE; - - for (i = 0; i < LUKS_NUMKEYS; i++) { - sector = size_round_up(sector, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE); - sector += keyslot_sectors; - } - - return sector; -} - -int LUKS_keyslot_area(struct luks_phdr *hdr, +int LUKS_keyslot_area(const struct luks_phdr *hdr, int keyslot, uint64_t *offset, uint64_t *length) @@ -62,32 +44,70 @@ int LUKS_keyslot_area(struct luks_phdr *hdr, if(keyslot >= LUKS_NUMKEYS || keyslot < 0) return -EINVAL; - *offset = hdr->keyblock[keyslot].keyMaterialOffset * SECTOR_SIZE; + *offset = (uint64_t)hdr->keyblock[keyslot].keyMaterialOffset * SECTOR_SIZE; *length = AF_split_sectors(hdr->keyBytes, LUKS_STRIPES) * SECTOR_SIZE; return 0; } -static int LUKS_check_device_size(struct crypt_device *ctx, size_t keyLength) +/* insertsort: because the array has 8 elements and it's mostly sorted. that's why */ +static void LUKS_sort_keyslots(const struct luks_phdr *hdr, int *array) +{ + int i, j, x; + + for (i = 1; i < LUKS_NUMKEYS; i++) { + j = i; + while (j > 0 && hdr->keyblock[array[j-1]].keyMaterialOffset > hdr->keyblock[array[j]].keyMaterialOffset) { + x = array[j]; + array[j] = array[j-1]; + array[j-1] = x; + j--; + } + } +} + +size_t LUKS_device_sectors(const struct luks_phdr *hdr) +{ + int sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + + LUKS_sort_keyslots(hdr, sorted_areas); + + return hdr->keyblock[sorted_areas[LUKS_NUMKEYS-1]].keyMaterialOffset + AF_split_sectors(hdr->keyBytes, LUKS_STRIPES); +} + +size_t LUKS_keyslots_offset(const struct luks_phdr *hdr) +{ + int sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + + LUKS_sort_keyslots(hdr, sorted_areas); + + return hdr->keyblock[sorted_areas[0]].keyMaterialOffset; +} + +static int LUKS_check_device_size(struct crypt_device *ctx, const struct luks_phdr *hdr, int falloc) { struct device *device = crypt_metadata_device(ctx); uint64_t dev_sectors, hdr_sectors; - if (!keyLength) + if (!hdr->keyBytes) return -EINVAL; - if(device_size(device, &dev_sectors)) { - log_dbg("Cannot get device size for device %s.", device_path(device)); + if (device_size(device, &dev_sectors)) { + log_dbg(ctx, "Cannot get device size for device %s.", device_path(device)); return -EIO; } dev_sectors >>= SECTOR_SHIFT; - hdr_sectors = LUKS_device_sectors(keyLength); - log_dbg("Key length %zu, device size %" PRIu64 " sectors, header size %" - PRIu64 " sectors.",keyLength, dev_sectors, hdr_sectors); + hdr_sectors = LUKS_device_sectors(hdr); + log_dbg(ctx, "Key length %u, device size %" PRIu64 " sectors, header size %" + PRIu64 " sectors.", hdr->keyBytes, dev_sectors, hdr_sectors); if (hdr_sectors > dev_sectors) { - log_err(ctx, _("Device %s is too small. (LUKS requires at least %" PRIu64 " bytes.)\n"), + /* If it is header file, increase its size */ + if (falloc && !device_fallocate(device, hdr_sectors << SECTOR_SHIFT)) + return 0; + + log_err(ctx, _("Device %s is too small. (LUKS1 requires at least %" PRIu64 " bytes.)"), device_path(device), hdr_sectors * SECTOR_SIZE); return -EINVAL; } @@ -95,40 +115,67 @@ static int LUKS_check_device_size(struct crypt_device *ctx, size_t keyLength) return 0; } -/* Check keyslot to prevent access outside of header and keyslot area */ -static int LUKS_check_keyslot_size(const struct luks_phdr *phdr, unsigned int keyIndex) +static int LUKS_check_keyslots(struct crypt_device *ctx, const struct luks_phdr *phdr) { - uint32_t secs_per_stripes; + int i, prev, next, sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + uint32_t secs_per_stripes = AF_split_sectors(phdr->keyBytes, LUKS_STRIPES); - /* First sectors is the header itself */ - if (phdr->keyblock[keyIndex].keyMaterialOffset * SECTOR_SIZE < sizeof(*phdr)) { - log_dbg("Invalid offset %u in keyslot %u.", - phdr->keyblock[keyIndex].keyMaterialOffset, keyIndex); - return 1; - } + LUKS_sort_keyslots(phdr, sorted_areas); + + /* Check keyslot to prevent access outside of header and keyslot area */ + for (i = 0; i < LUKS_NUMKEYS; i++) { + /* enforce stripes == 4000 */ + if (phdr->keyblock[i].stripes != LUKS_STRIPES) { + log_dbg(ctx, "Invalid stripes count %u in keyslot %u.", + phdr->keyblock[i].stripes, i); + log_err(ctx, _("LUKS keyslot %u is invalid."), i); + return -1; + } - /* Ignore following check for detached header where offset can be zero. */ - if (phdr->payloadOffset == 0) - return 0; + /* First sectors is the header itself */ + if (phdr->keyblock[i].keyMaterialOffset * SECTOR_SIZE < sizeof(*phdr)) { + log_dbg(ctx, "Invalid offset %u in keyslot %u.", + phdr->keyblock[i].keyMaterialOffset, i); + log_err(ctx, _("LUKS keyslot %u is invalid."), i); + return -1; + } - if (phdr->payloadOffset <= phdr->keyblock[keyIndex].keyMaterialOffset) { - log_dbg("Invalid offset %u in keyslot %u (beyond data area offset %u).", - phdr->keyblock[keyIndex].keyMaterialOffset, keyIndex, - phdr->payloadOffset); - return 1; - } + /* Ignore following check for detached header where offset can be zero. */ + if (phdr->payloadOffset == 0) + continue; - secs_per_stripes = AF_split_sectors(phdr->keyBytes, phdr->keyblock[keyIndex].stripes); + if (phdr->payloadOffset <= phdr->keyblock[i].keyMaterialOffset) { + log_dbg(ctx, "Invalid offset %u in keyslot %u (beyond data area offset %u).", + phdr->keyblock[i].keyMaterialOffset, i, + phdr->payloadOffset); + log_err(ctx, _("LUKS keyslot %u is invalid."), i); + return -1; + } + + if (phdr->payloadOffset < (phdr->keyblock[i].keyMaterialOffset + secs_per_stripes)) { + log_dbg(ctx, "Invalid keyslot size %u (offset %u, stripes %u) in " + "keyslot %u (beyond data area offset %u).", + secs_per_stripes, + phdr->keyblock[i].keyMaterialOffset, + phdr->keyblock[i].stripes, + i, phdr->payloadOffset); + log_err(ctx, _("LUKS keyslot %u is invalid."), i); + return -1; + } + } - if (phdr->payloadOffset < (phdr->keyblock[keyIndex].keyMaterialOffset + secs_per_stripes)) { - log_dbg("Invalid keyslot size %u (offset %u, stripes %u) in " - "keyslot %u (beyond data area offset %u).", - secs_per_stripes, - phdr->keyblock[keyIndex].keyMaterialOffset, - phdr->keyblock[keyIndex].stripes, - keyIndex, phdr->payloadOffset); - return 1; + /* check no keyslot overlaps with each other */ + for (i = 1; i < LUKS_NUMKEYS; i++) { + prev = sorted_areas[i-1]; + next = sorted_areas[i]; + if (phdr->keyblock[next].keyMaterialOffset < + (phdr->keyblock[prev].keyMaterialOffset + secs_per_stripes)) { + log_dbg(ctx, "Not enough space in LUKS keyslot %d.", prev); + log_err(ctx, _("LUKS keyslot %u is invalid."), prev); + return -1; + } } + /* do not check last keyslot on purpose, it must be tested in device size check */ return 0; } @@ -152,16 +199,17 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx) { struct device *device = crypt_metadata_device(ctx); struct luks_phdr hdr; - int r = 0, devfd = -1; - ssize_t hdr_size; - ssize_t buffer_size; + int fd, devfd, r = 0; + size_t hdr_size; + size_t buffer_size; + ssize_t ret; char *buffer = NULL; r = LUKS_read_phdr(&hdr, 1, 0, ctx); if (r) return r; - hdr_size = LUKS_device_sectors(hdr.keyBytes) << SECTOR_SHIFT; + hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT; buffer_size = size_round_up(hdr_size, crypt_getpagesize()); buffer = crypt_safe_alloc(buffer_size); @@ -170,49 +218,48 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx) goto out; } - log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes).", + log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes).", sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS); - log_dbg("Output backup file size: %zu bytes.", buffer_size); + log_dbg(ctx, "Output backup file size: %zu bytes.", buffer_size); - devfd = device_open(device, O_RDONLY); - if(devfd == -1) { - log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device_path(device)); + devfd = device_open(ctx, device, O_RDONLY); + if (devfd < 0) { + log_err(ctx, _("Device %s is not a valid LUKS device."), device_path(device)); r = -EINVAL; goto out; } - if (read_blockwise(devfd, device_block_size(device), buffer, hdr_size) < hdr_size) { + if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), + buffer, hdr_size, 0) < (ssize_t)hdr_size) { r = -EIO; goto out; } - close(devfd); /* Wipe unused area, so backup cannot contain old signatures */ if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS) memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr)); - devfd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); - if (devfd == -1) { + fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); + if (fd == -1) { if (errno == EEXIST) - log_err(ctx, _("Requested header backup file %s already exists.\n"), backup_file); + log_err(ctx, _("Requested header backup file %s already exists."), backup_file); else - log_err(ctx, _("Cannot create header backup file %s.\n"), backup_file); + log_err(ctx, _("Cannot create header backup file %s."), backup_file); r = -EINVAL; goto out; } - if (write(devfd, buffer, buffer_size) < buffer_size) { - log_err(ctx, _("Cannot write header backup file %s.\n"), backup_file); + ret = write_buffer(fd, buffer, buffer_size); + close(fd); + if (ret < (ssize_t)buffer_size) { + log_err(ctx, _("Cannot write header backup file %s."), backup_file); r = -EIO; goto out; } - close(devfd); r = 0; out: - if (devfd != -1) - close(devfd); - crypt_memzero(&hdr, sizeof(hdr)); + crypt_safe_memzero(&hdr, sizeof(hdr)); crypt_safe_free(buffer); return r; } @@ -223,8 +270,8 @@ int LUKS_hdr_restore( struct crypt_device *ctx) { struct device *device = crypt_metadata_device(ctx); - int r = 0, devfd = -1, diff_uuid = 0; - ssize_t buffer_size = 0; + int fd, r = 0, devfd = -1, diff_uuid = 0; + ssize_t ret, buffer_size = 0; char *buffer = NULL, msg[200]; struct luks_phdr hdr_file; @@ -233,10 +280,10 @@ int LUKS_hdr_restore( return r; if (!r) - buffer_size = LUKS_device_sectors(hdr_file.keyBytes) << SECTOR_SHIFT; + buffer_size = LUKS_device_sectors(&hdr_file) << SECTOR_SHIFT; if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) { - log_err(ctx, _("Backup file doesn't contain valid LUKS header.\n")); + log_err(ctx, _("Backup file does not contain valid LUKS header.")); r = -EINVAL; goto out; } @@ -247,26 +294,27 @@ int LUKS_hdr_restore( goto out; } - devfd = open(backup_file, O_RDONLY); - if (devfd == -1) { - log_err(ctx, _("Cannot open header backup file %s.\n"), backup_file); + fd = open(backup_file, O_RDONLY); + if (fd == -1) { + log_err(ctx, _("Cannot open header backup file %s."), backup_file); r = -EINVAL; goto out; } - if (read(devfd, buffer, buffer_size) < buffer_size) { - log_err(ctx, _("Cannot read header backup file %s.\n"), backup_file); + ret = read_buffer(fd, buffer, buffer_size); + close(fd); + if (ret < buffer_size) { + log_err(ctx, _("Cannot read header backup file %s."), backup_file); r = -EIO; goto out; } - close(devfd); r = LUKS_read_phdr(hdr, 0, 0, ctx); if (r == 0) { - log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device_path(device)); + log_dbg(ctx, "Device %s already contains LUKS header, checking UUID and offset.", device_path(device)); if(hdr->payloadOffset != hdr_file.payloadOffset || hdr->keyBytes != hdr_file.keyBytes) { - log_err(ctx, _("Data offset or key size differs on device and backup, restore failed.\n")); + log_err(ctx, _("Data offset or key size differs on device and backup, restore failed.")); r = -EINVAL; goto out; } @@ -287,31 +335,30 @@ int LUKS_hdr_restore( goto out; } - log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.", + log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.", sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device)); - devfd = device_open(device, O_RDWR); - if (devfd == -1) { + devfd = device_open(ctx, device, O_RDWR); + if (devfd < 0) { if (errno == EACCES) - log_err(ctx, _("Cannot write to device %s, permission denied.\n"), + log_err(ctx, _("Cannot write to device %s, permission denied."), device_path(device)); else - log_err(ctx, _("Cannot open device %s.\n"), device_path(device)); + log_err(ctx, _("Cannot open device %s."), device_path(device)); r = -EINVAL; goto out; } - if (write_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) { + if (write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), + buffer, buffer_size, 0) < buffer_size) { r = -EIO; goto out; } - close(devfd); /* Be sure to reload new data */ r = LUKS_read_phdr(hdr, 1, 0, ctx); out: - if (devfd != -1) - close(devfd); + device_sync(ctx, device); crypt_safe_free(buffer); return r; } @@ -322,45 +369,44 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx) struct luks_phdr temp_phdr; const unsigned char *sector = (const unsigned char*)phdr; struct volume_key *vk; - uint64_t PBKDF2_per_sec = 1; int i, bad, r, need_write = 0; if (phdr->keyBytes != 16 && phdr->keyBytes != 32 && phdr->keyBytes != 64) { - log_err(ctx, _("Non standard key size, manual repair required.\n")); + log_err(ctx, _("Non standard key size, manual repair required.")); return -EINVAL; } /* cryptsetup 1.0 did not align to 4k, cannot repair this one */ - if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) { - log_err(ctx, _("Non standard keyslots alignment, manual repair required.\n")); + if (LUKS_keyslots_offset(phdr) < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) { + log_err(ctx, _("Non standard keyslots alignment, manual repair required.")); return -EINVAL; } + r = LUKS_check_cipher(ctx, phdr->keyBytes, phdr->cipherName, phdr->cipherMode); + if (r < 0) + return -EINVAL; + vk = crypt_alloc_volume_key(phdr->keyBytes, NULL); - log_verbose(ctx, _("Repairing keyslots.\n")); + log_verbose(ctx, _("Repairing keyslots.")); - log_dbg("Generating second header with the same parameters for check."); + log_dbg(ctx, "Generating second header with the same parameters for check."); /* cipherName, cipherMode, hashSpec, uuid are already null terminated */ /* payloadOffset - cannot check */ r = LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode, - phdr->hashSpec,phdr->uuid, LUKS_STRIPES, - phdr->payloadOffset, 0, - 1, &PBKDF2_per_sec, - 1, ctx); - if (r < 0) { - log_err(ctx, _("Repair failed.")); + phdr->hashSpec, phdr->uuid, + phdr->payloadOffset * SECTOR_SIZE, 0, 0, ctx); + if (r < 0) goto out; - } for(i = 0; i < LUKS_NUMKEYS; ++i) { if (phdr->keyblock[i].active == LUKS_KEY_ENABLED) { - log_dbg("Skipping repair for active keyslot %i.", i); + log_dbg(ctx, "Skipping repair for active keyslot %i.", i); continue; } bad = 0; if (phdr->keyblock[i].keyMaterialOffset != temp_phdr.keyblock[i].keyMaterialOffset) { - log_err(ctx, _("Keyslot %i: offset repaired (%u -> %u).\n"), i, + log_err(ctx, _("Keyslot %i: offset repaired (%u -> %u)."), i, (unsigned)phdr->keyblock[i].keyMaterialOffset, (unsigned)temp_phdr.keyblock[i].keyMaterialOffset); phdr->keyblock[i].keyMaterialOffset = temp_phdr.keyblock[i].keyMaterialOffset; @@ -368,7 +414,7 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx) } if (phdr->keyblock[i].stripes != temp_phdr.keyblock[i].stripes) { - log_err(ctx, _("Keyslot %i: stripes repaired (%u -> %u).\n"), i, + log_err(ctx, _("Keyslot %i: stripes repaired (%u -> %u)."), i, (unsigned)phdr->keyblock[i].stripes, (unsigned)temp_phdr.keyblock[i].stripes); phdr->keyblock[i].stripes = temp_phdr.keyblock[i].stripes; @@ -377,12 +423,12 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx) /* Known case - MSDOS partition table signature */ if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) { - log_err(ctx, _("Keyslot %i: bogus partition signature.\n"), i); + log_err(ctx, _("Keyslot %i: bogus partition signature."), i); bad = 1; } if(bad) { - log_err(ctx, _("Keyslot %i: salt wiped.\n"), i); + log_err(ctx, _("Keyslot %i: salt wiped."), i); phdr->keyblock[i].active = LUKS_KEY_DISABLED; memset(&phdr->keyblock[i].passwordSalt, 0x00, LUKS_SALTSIZE); phdr->keyblock[i].passwordIterations = 0; @@ -392,13 +438,21 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx) need_write = 1; } - if (need_write) { - log_verbose(ctx, _("Writing LUKS header to disk.\n")); + /* + * check repair result before writing because repair can't fix out of order + * keyslot offsets and would corrupt header again + */ + if (LUKS_check_keyslots(ctx, phdr)) + r = -EINVAL; + else if (need_write) { + log_verbose(ctx, _("Writing LUKS header to disk.")); r = LUKS_write_phdr(phdr, ctx); } out: + if (r) + log_err(ctx, _("Repair failed.")); crypt_free_volume_key(vk); - crypt_memzero(&temp_phdr, sizeof(temp_phdr)); + crypt_safe_memzero(&temp_phdr, sizeof(temp_phdr)); return r; } @@ -413,18 +467,18 @@ static int _check_and_convert_hdr(const char *device, char luksMagic[] = LUKS_MAGIC; if(memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */ - log_dbg("LUKS header not detected."); + log_dbg(ctx, "LUKS header not detected."); if (require_luks_device) - log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device); + log_err(ctx, _("Device %s is not a valid LUKS device."), device); return -EINVAL; } else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */ - log_err(ctx, _("Unsupported LUKS version %d.\n"), hdr->version); + log_err(ctx, _("Unsupported LUKS version %d."), hdr->version); return -EINVAL; } hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0'; if (crypt_hmac_size(hdr->hashSpec) < LUKS_DIGESTSIZE) { - log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec); + log_err(ctx, _("Requested LUKS hash %s is not supported."), hdr->hashSpec); return -EINVAL; } @@ -438,12 +492,11 @@ static int _check_and_convert_hdr(const char *device, hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations); hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset); hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes); - if (LUKS_check_keyslot_size(hdr, i)) { - log_err(ctx, _("LUKS keyslot %u is invalid.\n"), i); - r = -EINVAL; - } } + if (LUKS_check_keyslots(ctx, hdr)) + r = -EINVAL; + /* Avoid unterminated strings */ hdr->cipherName[LUKS_CIPHERNAME_L - 1] = '\0'; hdr->cipherMode[LUKS_CIPHERMODE_L - 1] = '\0'; @@ -453,7 +506,7 @@ static int _check_and_convert_hdr(const char *device, if (r == -EINVAL) r = _keyslot_repair(hdr, ctx); else - log_verbose(ctx, _("No known problems detected for LUKS header.\n")); + log_verbose(ctx, _("No known problems detected for LUKS header.")); } return r; @@ -468,7 +521,7 @@ static void _to_lower(char *str, unsigned max_len) static void LUKS_fix_header_compatible(struct luks_phdr *header) { - /* Old cryptsetup expects "sha1", gcrypt allows case insensistive names, + /* Old cryptsetup expects "sha1", gcrypt allows case insensitive names, * so always convert hash to lower case in header */ _to_lower(header->hashSpec, LUKS_HASHSPEC_L); @@ -488,16 +541,16 @@ int LUKS_read_phdr_backup(const char *backup_file, ssize_t hdr_size = sizeof(struct luks_phdr); int devfd = 0, r = 0; - log_dbg("Reading LUKS header of size %d from backup file %s", + log_dbg(ctx, "Reading LUKS header of size %d from backup file %s", (int)hdr_size, backup_file); devfd = open(backup_file, O_RDONLY); - if(-1 == devfd) { - log_err(ctx, _("Cannot open header backup file %s.\n"), backup_file); + if (devfd == -1) { + log_err(ctx, _("Cannot open header backup file %s."), backup_file); return -ENOENT; } - if (read(devfd, hdr, hdr_size) < hdr_size) + if (read_buffer(devfd, hdr, hdr_size) < hdr_size) r = -EIO; else { LUKS_fix_header_compatible(hdr); @@ -514,9 +567,9 @@ int LUKS_read_phdr(struct luks_phdr *hdr, int repair, struct crypt_device *ctx) { + int devfd, r = 0; struct device *device = crypt_metadata_device(ctx); ssize_t hdr_size = sizeof(struct luks_phdr); - int devfd = 0, r = 0; /* LUKS header starts at offset 0, first keyslot on LUKS_ALIGN_KEYSLOTS */ assert(sizeof(struct luks_phdr) <= LUKS_ALIGN_KEYSLOTS); @@ -527,25 +580,35 @@ int LUKS_read_phdr(struct luks_phdr *hdr, if (repair && !require_luks_device) return -EINVAL; - log_dbg("Reading LUKS header of size %zu from device %s", + log_dbg(ctx, "Reading LUKS header of size %zu from device %s", hdr_size, device_path(device)); - devfd = device_open(device, O_RDONLY); - if (devfd == -1) { - log_err(ctx, _("Cannot open device %s.\n"), device_path(device)); + devfd = device_open(ctx, device, O_RDONLY); + if (devfd < 0) { + log_err(ctx, _("Cannot open device %s."), device_path(device)); return -EINVAL; } - if (read_blockwise(devfd, device_block_size(device), hdr, hdr_size) < hdr_size) + if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), + hdr, hdr_size, 0) < hdr_size) r = -EIO; else r = _check_and_convert_hdr(device_path(device), hdr, require_luks_device, repair, ctx); if (!r) - r = LUKS_check_device_size(ctx, hdr->keyBytes); + r = LUKS_check_device_size(ctx, hdr, 0); + + /* + * Cryptsetup 1.0.0 did not align keyslots to 4k (very rare version). + * Disable direct-io to avoid possible IO errors if underlying device + * has bigger sector size. + */ + if (!r && hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE < LUKS_ALIGN_KEYSLOTS) { + log_dbg(ctx, "Old unaligned LUKS keyslot detected, disabling direct-io."); + device_disable_direct_io(device); + } - close(devfd); return r; } @@ -559,20 +622,20 @@ int LUKS_write_phdr(struct luks_phdr *hdr, struct luks_phdr convHdr; int r; - log_dbg("Updating LUKS header of size %zu on device %s", + log_dbg(ctx, "Updating LUKS header of size %zu on device %s", sizeof(struct luks_phdr), device_path(device)); - r = LUKS_check_device_size(ctx, hdr->keyBytes); + r = LUKS_check_device_size(ctx, hdr, 1); if (r) return r; - devfd = device_open(device, O_RDWR); - if(-1 == devfd) { + devfd = device_open(ctx, device, O_RDWR); + if (devfd < 0) { if (errno == EACCES) - log_err(ctx, _("Cannot write to device %s, permission denied.\n"), + log_err(ctx, _("Cannot write to device %s, permission denied."), device_path(device)); else - log_err(ctx, _("Cannot open device %s.\n"), device_path(device)); + log_err(ctx, _("Cannot open device %s."), device_path(device)); return -EINVAL; } @@ -591,16 +654,18 @@ int LUKS_write_phdr(struct luks_phdr *hdr, convHdr.keyblock[i].stripes = htonl(hdr->keyblock[i].stripes); } - r = write_blockwise(devfd, device_block_size(device), &convHdr, hdr_size) < hdr_size ? -EIO : 0; + r = write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), + &convHdr, hdr_size, 0) < hdr_size ? -EIO : 0; if (r) - log_err(ctx, _("Error during update of LUKS header on device %s.\n"), device_path(device)); - close(devfd); + log_err(ctx, _("Error during update of LUKS header on device %s."), device_path(device)); + + device_sync(ctx, device); /* Re-read header from disk to be sure that in-memory and on-disk data are the same. */ if (!r) { r = LUKS_read_phdr(hdr, 1, 0, ctx); if (r) - log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), + log_err(ctx, _("Error re-reading LUKS header after update on device %s."), device_path(device)); } @@ -608,139 +673,142 @@ int LUKS_write_phdr(struct luks_phdr *hdr, } /* Check that kernel supports requested cipher by decryption of one sector */ -static int LUKS_check_cipher(struct luks_phdr *hdr, struct crypt_device *ctx) +int LUKS_check_cipher(struct crypt_device *ctx, size_t keylength, const char *cipher, const char *cipher_mode) { int r; struct volume_key *empty_key; char buf[SECTOR_SIZE]; - log_dbg("Checking if cipher %s-%s is usable.", hdr->cipherName, hdr->cipherMode); + log_dbg(ctx, "Checking if cipher %s-%s is usable.", cipher, cipher_mode); - empty_key = crypt_alloc_volume_key(hdr->keyBytes, NULL); + empty_key = crypt_alloc_volume_key(keylength, NULL); if (!empty_key) return -ENOMEM; - r = LUKS_decrypt_from_storage(buf, sizeof(buf), - hdr->cipherName, hdr->cipherMode, - empty_key, 0, ctx); + /* No need to get KEY quality random but it must avoid known weak keys. */ + r = crypt_random_get(ctx, empty_key->key, empty_key->keylength, CRYPT_RND_NORMAL); + if (!r) + r = LUKS_decrypt_from_storage(buf, sizeof(buf), cipher, cipher_mode, empty_key, 0, ctx); crypt_free_volume_key(empty_key); - crypt_memzero(buf, sizeof(buf)); + crypt_safe_memzero(buf, sizeof(buf)); return r; } int LUKS_generate_phdr(struct luks_phdr *header, - const struct volume_key *vk, - const char *cipherName, const char *cipherMode, const char *hashSpec, - const char *uuid, unsigned int stripes, - unsigned int alignPayload, - unsigned int alignOffset, - uint32_t iteration_time_ms, - uint64_t *PBKDF2_per_sec, - int detached_metadata_device, - struct crypt_device *ctx) + const struct volume_key *vk, + const char *cipherName, + const char *cipherMode, + const char *hashSpec, + const char *uuid, + uint64_t data_offset, /* in bytes */ + uint64_t align_offset, /* in bytes */ + uint64_t required_alignment, /* in bytes */ + struct crypt_device *ctx) { - unsigned int i = 0, hdr_sectors = LUKS_device_sectors(vk->keylength); - size_t blocksPerStripeSet, currentSector; - int r; + int i, r; + size_t keyslot_sectors, header_sectors; uuid_t partitionUuid; + struct crypt_pbkdf_type *pbkdf; + double PBKDF2_temp; char luksMagic[] = LUKS_MAGIC; - /* For separate metadata device allow zero alignment */ - if (alignPayload == 0 && !detached_metadata_device) - alignPayload = DEFAULT_DISK_ALIGNMENT / SECTOR_SIZE; + if (data_offset % SECTOR_SIZE || align_offset % SECTOR_SIZE || + required_alignment % SECTOR_SIZE) + return -EINVAL; - if (alignPayload && detached_metadata_device && alignPayload < hdr_sectors) { - log_err(ctx, _("Data offset for detached LUKS header must be " - "either 0 or higher than header size (%d sectors).\n"), - hdr_sectors); + memset(header, 0, sizeof(struct luks_phdr)); + + keyslot_sectors = AF_split_sectors(vk->keylength, LUKS_STRIPES); + header_sectors = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE; + + for (i = 0; i < LUKS_NUMKEYS; i++) { + header->keyblock[i].active = LUKS_KEY_DISABLED; + header->keyblock[i].keyMaterialOffset = header_sectors; + header->keyblock[i].stripes = LUKS_STRIPES; + header_sectors = size_round_up(header_sectors + keyslot_sectors, + LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE); + } + /* In sector is now size of all keyslot material space */ + + /* Data offset has priority */ + if (data_offset) + header->payloadOffset = data_offset / SECTOR_SIZE; + else if (required_alignment) { + header->payloadOffset = size_round_up(header_sectors, (required_alignment / SECTOR_SIZE)); + header->payloadOffset += (align_offset / SECTOR_SIZE); + } else + header->payloadOffset = 0; + + if (header->payloadOffset && header->payloadOffset < header_sectors) { + log_err(ctx, _("Data offset for LUKS header must be " + "either 0 or higher than header size.")); return -EINVAL; } if (crypt_hmac_size(hashSpec) < LUKS_DIGESTSIZE) { - log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hashSpec); + log_err(ctx, _("Requested LUKS hash %s is not supported."), hashSpec); return -EINVAL; } if (uuid && uuid_parse(uuid, partitionUuid) == -1) { - log_err(ctx, _("Wrong LUKS UUID format provided.\n")); + log_err(ctx, _("Wrong LUKS UUID format provided.")); return -EINVAL; } if (!uuid) uuid_generate(partitionUuid); - memset(header,0,sizeof(struct luks_phdr)); - /* Set Magic */ memcpy(header->magic,luksMagic,LUKS_MAGIC_L); header->version=1; - strncpy(header->cipherName,cipherName,LUKS_CIPHERNAME_L); - strncpy(header->cipherMode,cipherMode,LUKS_CIPHERMODE_L); - strncpy(header->hashSpec,hashSpec,LUKS_HASHSPEC_L); + strncpy(header->cipherName,cipherName,LUKS_CIPHERNAME_L-1); + strncpy(header->cipherMode,cipherMode,LUKS_CIPHERMODE_L-1); + strncpy(header->hashSpec,hashSpec,LUKS_HASHSPEC_L-1); header->keyBytes=vk->keylength; LUKS_fix_header_compatible(header); - r = LUKS_check_cipher(header, ctx); - if (r < 0) - return r; - - log_dbg("Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes", + log_dbg(ctx, "Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes", header->version, header->hashSpec ,header->cipherName, header->cipherMode, header->keyBytes); r = crypt_random_get(ctx, header->mkDigestSalt, LUKS_SALTSIZE, CRYPT_RND_SALT); if(r < 0) { - log_err(ctx, _("Cannot create LUKS header: reading random salt failed.\n")); + log_err(ctx, _("Cannot create LUKS header: reading random salt failed.")); return r; } - r = crypt_benchmark_kdf(ctx, "pbkdf2", header->hashSpec, - "foo", 3, "bar", 3, PBKDF2_per_sec); - if (r < 0) { - log_err(ctx, _("Not compatible PBKDF2 options (using hash algorithm %s).\n"), - header->hashSpec); + /* Compute master key digest */ + pbkdf = crypt_get_pbkdf(ctx); + r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength); + if (r < 0) return r; - } + assert(pbkdf->iterations); - /* Compute master key digest */ - iteration_time_ms /= 8; - header->mkDigestIterations = at_least((uint32_t)(*PBKDF2_per_sec/1024) * iteration_time_ms, - LUKS_MKD_ITERATIONS_MIN); + if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK && pbkdf->time_ms == 0) + PBKDF2_temp = LUKS_MKD_ITERATIONS_MIN; + else /* iterations per ms * LUKS_MKD_ITERATIONS_MS */ + PBKDF2_temp = (double)pbkdf->iterations * LUKS_MKD_ITERATIONS_MS / pbkdf->time_ms; - r = crypt_pbkdf("pbkdf2", header->hashSpec, vk->key,vk->keylength, + if (PBKDF2_temp > (double)UINT32_MAX) + return -EINVAL; + header->mkDigestIterations = at_least((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN); + assert(header->mkDigestIterations); + + r = crypt_pbkdf(CRYPT_KDF_PBKDF2, header->hashSpec, vk->key,vk->keylength, header->mkDigestSalt, LUKS_SALTSIZE, header->mkDigest,LUKS_DIGESTSIZE, - header->mkDigestIterations); - if(r < 0) { - log_err(ctx, _("Cannot create LUKS header: header digest failed (using hash %s).\n"), + header->mkDigestIterations, 0, 0); + if (r < 0) { + log_err(ctx, _("Cannot create LUKS header: header digest failed (using hash %s)."), header->hashSpec); return r; } - currentSector = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE; - blocksPerStripeSet = AF_split_sectors(vk->keylength, stripes); - for(i = 0; i < LUKS_NUMKEYS; ++i) { - header->keyblock[i].active = LUKS_KEY_DISABLED; - header->keyblock[i].keyMaterialOffset = currentSector; - header->keyblock[i].stripes = stripes; - currentSector = size_round_up(currentSector + blocksPerStripeSet, - LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE); - } - - if (detached_metadata_device) { - /* for separate metadata device use alignPayload directly */ - header->payloadOffset = alignPayload; - } else { - /* alignOffset - offset from natural device alignment provided by topology info */ - currentSector = size_round_up(currentSector, alignPayload); - header->payloadOffset = currentSector + alignOffset; - } - uuid_unparse(partitionUuid, header->uuid); - log_dbg("Data offset %d, UUID %s, digest iterations %" PRIu32, + log_dbg(ctx, "Data offset %d, UUID %s, digest iterations %" PRIu32, header->payloadOffset, header->uuid, header->mkDigestIterations); return 0; @@ -754,7 +822,7 @@ int LUKS_hdr_uuid_set( uuid_t partitionUuid; if (uuid && uuid_parse(uuid, partitionUuid) == -1) { - log_err(ctx, _("Wrong LUKS UUID format provided.\n")); + log_err(ctx, _("Wrong LUKS UUID format provided.")); return -EINVAL; } if (!uuid) @@ -768,50 +836,40 @@ int LUKS_hdr_uuid_set( int LUKS_set_key(unsigned int keyIndex, const char *password, size_t passwordLen, struct luks_phdr *hdr, struct volume_key *vk, - uint32_t iteration_time_ms, - uint64_t *PBKDF2_per_sec, struct crypt_device *ctx) { struct volume_key *derived_key; char *AfKey = NULL; size_t AFEKSize; - uint64_t PBKDF2_temp; + struct crypt_pbkdf_type *pbkdf; int r; if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) { - log_err(ctx, _("Key slot %d active, purge first.\n"), keyIndex); + log_err(ctx, _("Key slot %d active, purge first."), keyIndex); return -EINVAL; } - /* LUKS keyslot has always at least 4000 stripes accoding to specification */ + /* LUKS keyslot has always at least 4000 stripes according to specification */ if(hdr->keyblock[keyIndex].stripes < 4000) { - log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?\n"), + log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?"), keyIndex); return -EINVAL; } - log_dbg("Calculating data for key slot %d", keyIndex); - - r = crypt_benchmark_kdf(ctx, "pbkdf2", hdr->hashSpec, - "foo", 3, "bar", 3, PBKDF2_per_sec); - if (r < 0) { - log_err(ctx, _("Not compatible PBKDF2 options (using hash algorithm %s).\n"), - hdr->hashSpec); + log_dbg(ctx, "Calculating data for key slot %d", keyIndex); + pbkdf = crypt_get_pbkdf(ctx); + r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength); + if (r < 0) return r; - } + assert(pbkdf->iterations); /* - * Avoid floating point operation * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN */ - PBKDF2_temp = (*PBKDF2_per_sec / 2) * (uint64_t)iteration_time_ms; - PBKDF2_temp /= 1024; - if (PBKDF2_temp > UINT32_MAX) - PBKDF2_temp = UINT32_MAX; - hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp, - LUKS_SLOT_ITERATIONS_MIN); - - log_dbg("Key slot %d use %" PRIu32 " password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations); + hdr->keyblock[keyIndex].passwordIterations = + at_least(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN); + log_dbg(ctx, "Key slot %d use %" PRIu32 " password iterations.", keyIndex, + hdr->keyblock[keyIndex].passwordIterations); derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL); if (!derived_key) @@ -822,10 +880,10 @@ int LUKS_set_key(unsigned int keyIndex, if (r < 0) goto out; - r = crypt_pbkdf("pbkdf2", hdr->hashSpec, password, passwordLen, + r = crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, password, passwordLen, hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE, derived_key->key, hdr->keyBytes, - hdr->keyblock[keyIndex].passwordIterations); + hdr->keyblock[keyIndex].passwordIterations, 0, 0); if (r < 0) goto out; @@ -840,13 +898,13 @@ int LUKS_set_key(unsigned int keyIndex, goto out; } - log_dbg("Using hash %s for AF in key slot %d, %d stripes", + log_dbg(ctx, "Using hash %s for AF in key slot %d, %d stripes", hdr->hashSpec, keyIndex, hdr->keyblock[keyIndex].stripes); - r = AF_split(vk->key,AfKey,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec); + r = AF_split(ctx, vk->key, AfKey, vk->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec); if (r < 0) goto out; - log_dbg("Updating key slot %d [0x%04x] area.", keyIndex, + log_dbg(ctx, "Updating key slot %d [0x%04x] area.", keyIndex, hdr->keyblock[keyIndex].keyMaterialOffset << 9); /* Encryption via dm */ r = LUKS_encrypt_to_storage(AfKey, @@ -859,7 +917,7 @@ int LUKS_set_key(unsigned int keyIndex, goto out; /* Mark the key as active in phdr */ - r = LUKS_keyslot_set(hdr, (int)keyIndex, 1); + r = LUKS_keyslot_set(hdr, (int)keyIndex, 1, ctx); if (r < 0) goto out; @@ -880,10 +938,10 @@ int LUKS_verify_volume_key(const struct luks_phdr *hdr, { char checkHashBuf[LUKS_DIGESTSIZE]; - if (crypt_pbkdf("pbkdf2", hdr->hashSpec, vk->key, vk->keylength, + if (crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, vk->key, vk->keylength, hdr->mkDigestSalt, LUKS_SALTSIZE, checkHashBuf, LUKS_DIGESTSIZE, - hdr->mkDigestIterations) < 0) + hdr->mkDigestIterations, 0, 0) < 0) return -EINVAL; if (memcmp(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE)) @@ -906,7 +964,7 @@ static int LUKS_open_key(unsigned int keyIndex, size_t AFEKSize; int r; - log_dbg("Trying to open key slot %d [%s].", keyIndex, + log_dbg(ctx, "Trying to open key slot %d [%s].", keyIndex, dbg_slot_state(ki)); if (ki < CRYPT_SLOT_ACTIVE) @@ -924,14 +982,16 @@ static int LUKS_open_key(unsigned int keyIndex, goto out; } - r = crypt_pbkdf("pbkdf2", hdr->hashSpec, password, passwordLen, + r = crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, password, passwordLen, hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE, derived_key->key, hdr->keyBytes, - hdr->keyblock[keyIndex].passwordIterations); - if (r < 0) + hdr->keyblock[keyIndex].passwordIterations, 0, 0); + if (r < 0) { + log_err(ctx, _("Cannot open keyslot (using hash %s)."), hdr->hashSpec); goto out; + } - log_dbg("Reading key slot %d area.", keyIndex); + log_dbg(ctx, "Reading key slot %d area.", keyIndex); r = LUKS_decrypt_from_storage(AfKey, AFEKSize, hdr->cipherName, hdr->cipherMode, @@ -941,13 +1001,15 @@ static int LUKS_open_key(unsigned int keyIndex, if (r < 0) goto out; - r = AF_merge(AfKey,vk->key,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec); + r = AF_merge(ctx, AfKey, vk->key, vk->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec); if (r < 0) goto out; r = LUKS_verify_volume_key(hdr, vk); - if (!r) - log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex); + + /* Allow only empty passphrase with null cipher */ + if (!r && !strcmp(hdr->cipherName, "cipher_null") && passwordLen) + r = -EPERM; out: crypt_safe_free(AfKey); crypt_free_volume_key(derived_key); @@ -961,7 +1023,7 @@ int LUKS_open_key_with_hdr(int keyIndex, struct volume_key **vk, struct crypt_device *ctx) { - unsigned int i; + unsigned int i, tried = 0; int r; *vk = crypt_alloc_volume_key(hdr->keyBytes, NULL); @@ -971,7 +1033,7 @@ int LUKS_open_key_with_hdr(int keyIndex, return (r < 0) ? r : keyIndex; } - for(i = 0; i < LUKS_NUMKEYS; i++) { + for (i = 0; i < LUKS_NUMKEYS; i++) { r = LUKS_open_key(i, password, passwordLen, hdr, *vk, ctx); if(r == 0) return i; @@ -980,10 +1042,11 @@ int LUKS_open_key_with_hdr(int keyIndex, former meaning password wrong, latter key slot inactive */ if ((r != -EPERM) && (r != -ENOENT)) return r; + if (r == -EPERM) + tried++; } /* Warning, early returns above */ - log_err(ctx, _("No key available with this passphrase.\n")); - return -EPERM; + return tried ? -EPERM : -ENOENT; } int LUKS_del_key(unsigned int keyIndex, @@ -998,9 +1061,9 @@ int LUKS_del_key(unsigned int keyIndex, if (r) return r; - r = LUKS_keyslot_set(hdr, keyIndex, 0); + r = LUKS_keyslot_set(hdr, keyIndex, 0, ctx); if (r) { - log_err(ctx, _("Key slot %d is invalid, please select keyslot between 0 and %d.\n"), + log_err(ctx, _("Key slot %d is invalid, please select keyslot between 0 and %d."), keyIndex, LUKS_NUMKEYS - 1); return r; } @@ -1009,16 +1072,16 @@ int LUKS_del_key(unsigned int keyIndex, startOffset = hdr->keyblock[keyIndex].keyMaterialOffset; endOffset = startOffset + AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes); - r = crypt_wipe(device, startOffset * SECTOR_SIZE, - (endOffset - startOffset) * SECTOR_SIZE, - CRYPT_WIPE_DISK, 0); + r = crypt_wipe_device(ctx, device, CRYPT_WIPE_SPECIAL, startOffset * SECTOR_SIZE, + (endOffset - startOffset) * SECTOR_SIZE, + (endOffset - startOffset) * SECTOR_SIZE, NULL, NULL); if (r) { if (r == -EACCES) { - log_err(ctx, _("Cannot write to device %s, permission denied.\n"), + log_err(ctx, _("Cannot write to device %s, permission denied."), device_path(device)); r = -EINVAL; } else - log_err(ctx, _("Cannot wipe device %s.\n"), + log_err(ctx, _("Cannot wipe device %s."), device_path(device)); return r; } @@ -1077,7 +1140,7 @@ int LUKS_keyslot_active_count(struct luks_phdr *hdr) return num; } -int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable) +int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable, struct crypt_device *ctx) { crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyslot); @@ -1085,7 +1148,7 @@ int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable) return -EINVAL; hdr->keyblock[keyslot].active = enable ? LUKS_KEY_ENABLED : LUKS_KEY_DISABLED; - log_dbg("Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled"); + log_dbg(ctx, "Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled"); return 0; } @@ -1095,39 +1158,87 @@ int LUKS1_activate(struct crypt_device *cd, uint32_t flags) { int r; - char *dm_cipher = NULL; - enum devcheck device_check; struct crypt_dm_active_device dmd = { - .target = DM_CRYPT, - .uuid = crypt_get_uuid(cd), - .flags = flags, - .size = 0, - .data_device = crypt_data_device(cd), - .u.crypt = { - .cipher = NULL, - .vk = vk, - .offset = crypt_get_data_offset(cd), - .iv_offset = 0, - } + .flags = flags, + .uuid = crypt_get_uuid(cd), }; - if (dmd.flags & CRYPT_ACTIVATE_SHARED) - device_check = DEV_SHARED; - else - device_check = DEV_EXCL; + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), + vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), + crypt_get_data_offset(cd), crypt_get_integrity(cd), + crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); + if (!r) + r = create_or_reload_device(cd, name, CRYPT_LUKS1, &dmd); - r = device_block_adjust(cd, dmd.data_device, device_check, - dmd.u.crypt.offset, &dmd.size, &dmd.flags); - if (r) - return r; + dm_targets_free(cd, &dmd); + + return r; +} + +int LUKS_wipe_header_areas(struct luks_phdr *hdr, + struct crypt_device *ctx) +{ + int i, r; + uint64_t offset, length; + size_t wipe_block; + + /* Wipe complete header, keyslots and padding areas with zeroes. */ + offset = 0; + length = (uint64_t)hdr->payloadOffset * SECTOR_SIZE; + wipe_block = 1024 * 1024; + + /* On detached header or bogus header, wipe at least the first 4k */ + if (length == 0 || length > (LUKS_MAX_KEYSLOT_SIZE * LUKS_NUMKEYS)) { + length = 4096; + wipe_block = 4096; + } - r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); + log_dbg(ctx, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.", + offset, length + offset); + + r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_ZERO, + offset, length, wipe_block, NULL, NULL); if (r < 0) - return -ENOMEM; + return r; + + /* Wipe keyslots areas */ + wipe_block = 1024 * 1024; + for (i = 0; i < LUKS_NUMKEYS; i++) { + r = LUKS_keyslot_area(hdr, i, &offset, &length); + if (r < 0) + return r; + + /* Ignore too big LUKS1 keyslots here */ + if (length > LUKS_MAX_KEYSLOT_SIZE || + offset > (LUKS_MAX_KEYSLOT_SIZE - length)) + continue; + + if (length == 0 || offset < 4096) + return -EINVAL; - dmd.u.crypt.cipher = dm_cipher; - r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd, 0); + log_dbg(ctx, "Wiping keyslot %i area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.", + i, offset, length + offset); + + r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_RANDOM, + offset, length, wipe_block, NULL, NULL); + if (r < 0) + return r; + } - free(dm_cipher); return r; } + +int LUKS_keyslot_pbkdf(struct luks_phdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf) +{ + if (LUKS_keyslot_info(hdr, keyslot) < CRYPT_SLOT_ACTIVE) + return -EINVAL; + + pbkdf->type = CRYPT_KDF_PBKDF2; + pbkdf->hash = hdr->hashSpec; + pbkdf->iterations = hdr->keyblock[keyslot].passwordIterations; + pbkdf->max_memory_kb = 0; + pbkdf->parallel_threads = 0; + pbkdf->time_ms = 0; + pbkdf->flags = 0; + return 0; +} diff --git a/lib/luks1/luks.h b/lib/luks1/luks.h index 7aef82f..d54276e 100644 --- a/lib/luks1/luks.h +++ b/lib/luks1/luks.h @@ -1,8 +1,8 @@ /* * LUKS - Linux Unified Key Setup * - * Copyright (C) 2004-2006, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2006 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -40,6 +40,9 @@ #define LUKS_MKD_ITERATIONS_MIN 1000 #define LUKS_SLOT_ITERATIONS_MIN 1000 +// Iteration time for digest in ms +#define LUKS_MKD_ITERATIONS_MS 125 + #define LUKS_KEY_DISABLED_OLD 0 #define LUKS_KEY_ENABLED_OLD 0xCAFE @@ -58,6 +61,9 @@ /* Offset to keyslot area [in bytes] */ #define LUKS_ALIGN_KEYSLOTS 4096 +/* Maximal LUKS header size, for wipe [in bytes] */ +#define LUKS_MAX_KEYSLOT_SIZE 0x1000000 /* 16 MB, up to 32768 bits key */ + /* Any integer values are stored in network byte order on disk and must be converted */ @@ -96,19 +102,20 @@ struct luks_phdr { int LUKS_verify_volume_key(const struct luks_phdr *hdr, const struct volume_key *vk); -int LUKS_generate_phdr( - struct luks_phdr *header, +int LUKS_check_cipher(struct crypt_device *ctx, + size_t keylength, + const char *cipher, + const char *cipher_mode); + +int LUKS_generate_phdr(struct luks_phdr *header, const struct volume_key *vk, const char *cipherName, const char *cipherMode, const char *hashSpec, const char *uuid, - unsigned int stripes, - unsigned int alignPayload, - unsigned int alignOffset, - uint32_t iteration_time_ms, - uint64_t *PBKDF2_per_sec, - int detached_metadata_device, + uint64_t data_offset, + uint64_t align_offset, + uint64_t required_alignment, struct crypt_device *ctx); int LUKS_read_phdr( @@ -147,8 +154,6 @@ int LUKS_set_key( size_t passwordLen, struct luks_phdr *hdr, struct volume_key *vk, - uint32_t iteration_time_ms, - uint64_t *PBKDF2_per_sec, struct crypt_device *ctx); int LUKS_open_key_with_hdr( @@ -164,30 +169,22 @@ int LUKS_del_key( struct luks_phdr *hdr, struct crypt_device *ctx); +int LUKS_wipe_header_areas(struct luks_phdr *hdr, + struct crypt_device *ctx); + crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot); int LUKS_keyslot_find_empty(struct luks_phdr *hdr); int LUKS_keyslot_active_count(struct luks_phdr *hdr); -int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable); -int LUKS_keyslot_area(struct luks_phdr *hdr, +int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable, + struct crypt_device *ctx); +int LUKS_keyslot_area(const struct luks_phdr *hdr, int keyslot, uint64_t *offset, uint64_t *length); - -int LUKS_encrypt_to_storage( - char *src, size_t srcLength, - const char *cipher, - const char *cipher_mode, - struct volume_key *vk, - unsigned int sector, - struct crypt_device *ctx); - -int LUKS_decrypt_from_storage( - char *dst, size_t dstLength, - const char *cipher, - const char *cipher_mode, - struct volume_key *vk, - unsigned int sector, - struct crypt_device *ctx); +size_t LUKS_device_sectors(const struct luks_phdr *hdr); +size_t LUKS_keyslots_offset(const struct luks_phdr *hdr); +int LUKS_keyslot_pbkdf(struct luks_phdr *hdr, int keyslot, + struct crypt_pbkdf_type *pbkdf); int LUKS1_activate(struct crypt_device *cd, const char *name, diff --git a/lib/luks2/luks2.h b/lib/luks2/luks2.h new file mode 100644 index 0000000..6ab753a --- /dev/null +++ b/lib/luks2/luks2.h @@ -0,0 +1,609 @@ +/* + * LUKS - Linux Unified Key Setup v2 + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_LUKS2_ONDISK_H +#define _CRYPTSETUP_LUKS2_ONDISK_H + +#include + +#include "libcryptsetup.h" + +#define LUKS2_MAGIC_1ST "LUKS\xba\xbe" +#define LUKS2_MAGIC_2ND "SKUL\xba\xbe" +#define LUKS2_MAGIC_L 6 +#define LUKS2_UUID_L 40 +#define LUKS2_LABEL_L 48 +#define LUKS2_SALT_L 64 +#define LUKS2_CHECKSUM_ALG_L 32 +#define LUKS2_CHECKSUM_L 64 + +#define LUKS2_KEYSLOTS_MAX 32 +#define LUKS2_TOKENS_MAX 32 +#define LUKS2_SEGMENT_MAX 32 + +#define LUKS2_BUILTIN_TOKEN_PREFIX "luks2-" +#define LUKS2_BUILTIN_TOKEN_PREFIX_LEN 6 + +#define LUKS2_TOKEN_KEYRING LUKS2_BUILTIN_TOKEN_PREFIX "keyring" + +#define LUKS2_DIGEST_MAX 8 + +#define CRYPT_ANY_SEGMENT -1 +#define CRYPT_DEFAULT_SEGMENT -2 +#define CRYPT_ONE_SEGMENT -3 + +#define CRYPT_ANY_DIGEST -1 + +/* 20 MiBs */ +#define LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH 0x1400000 + +/* 1 GiB */ +#define LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH 0x40000000 + +struct device; + +/* + * LUKS2 header on-disk. + * + * Binary header is followed by JSON area. + * JSON area is followed by keyslot area and data area, + * these are described in JSON metadata. + * + * Note: uuid, csum_alg are intentionally on the same offset as LUKS1 + * (checksum alg replaces hash in LUKS1) + * + * String (char) should be zero terminated. + * Padding should be wiped. + * Checksum is calculated with csum zeroed (+ full JSON area). + */ +struct luks2_hdr_disk { + char magic[LUKS2_MAGIC_L]; + uint16_t version; /* Version 2 */ + uint64_t hdr_size; /* in bytes, including JSON area */ + uint64_t seqid; /* increased on every update */ + char label[LUKS2_LABEL_L]; + char checksum_alg[LUKS2_CHECKSUM_ALG_L]; + uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */ + char uuid[LUKS2_UUID_L]; + char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */ + uint64_t hdr_offset; /* offset from device start in bytes */ + char _padding[184]; + uint8_t csum[LUKS2_CHECKSUM_L]; + char _padding4096[7*512]; + /* JSON area starts here */ +} __attribute__ ((packed)); + +/* + * LUKS2 header in-memory. + */ +typedef struct json_object json_object; +struct luks2_hdr { + size_t hdr_size; + uint64_t seqid; + unsigned int version; + char label[LUKS2_LABEL_L]; + char subsystem[LUKS2_LABEL_L]; + char checksum_alg[LUKS2_CHECKSUM_ALG_L]; + uint8_t salt1[LUKS2_SALT_L]; + uint8_t salt2[LUKS2_SALT_L]; + char uuid[LUKS2_UUID_L]; + json_object *jobj; +}; + +struct luks2_keyslot_params { + enum { LUKS2_KEYSLOT_AF_LUKS1 = 0 } af_type; + enum { LUKS2_KEYSLOT_AREA_RAW = 0 } area_type; + + union { + struct { + char hash[LUKS2_CHECKSUM_ALG_L]; // or include luks.h + unsigned int stripes; + } luks1; + } af; + + union { + struct { + char encryption[65]; // or include utils_crypt.h + size_t key_size; + } raw; + } area; +}; + +struct reenc_protection { + enum { REENC_PROTECTION_NONE = 0, /* none should be 0 always */ + REENC_PROTECTION_CHECKSUM, + REENC_PROTECTION_JOURNAL, + REENC_PROTECTION_DATASHIFT } type; + + union { + struct { + } none; + struct { + char hash[LUKS2_CHECKSUM_ALG_L]; // or include luks.h + struct crypt_hash *ch; + size_t hash_size; + /* buffer for checksums */ + void *checksums; + size_t checksums_len; + } csum; + struct { + } ds; + } p; +}; + +struct luks2_reenc_context { + /* reencryption window attributes */ + uint64_t offset; + uint64_t progress; + uint64_t length; + uint64_t data_shift; + size_t alignment; + uint64_t device_size; + bool online; + bool fixed_length; + crypt_reencrypt_direction_info direction; + crypt_reencrypt_mode_info mode; + + char *device_name; + char *hotzone_name; + char *overlay_name; + uint32_t flags; + + /* reencryption window persistence attributes */ + struct reenc_protection rp; + + int reenc_keyslot; + + /* already running reencryption */ + json_object *jobj_segs_hot; + json_object *jobj_segs_post; + + /* backup segments */ + json_object *jobj_segment_new; + int digest_new; + json_object *jobj_segment_old; + int digest_old; + json_object *jobj_segment_moved; + + struct volume_key *vks; + + void *reenc_buffer; + ssize_t read; + + struct crypt_storage_wrapper *cw1; + struct crypt_storage_wrapper *cw2; + + uint32_t wflags1; + uint32_t wflags2; + + struct crypt_lock_handle *reenc_lock; +}; + +crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr); +/* + * Supportable header sizes (hdr_disk + JSON area) + * Also used as offset for the 2nd header. + */ +#define LUKS2_HDR_16K_LEN 0x4000 + +#define LUKS2_HDR_BIN_LEN sizeof(struct luks2_hdr_disk) + +//#define LUKS2_DEFAULT_HDR_SIZE 0x400000 /* 4 MiB */ +#define LUKS2_DEFAULT_HDR_SIZE 0x1000000 /* 16 MiB */ + +#define LUKS2_MAX_KEYSLOTS_SIZE 0x8000000 /* 128 MiB */ + +#define LUKS2_HDR_OFFSET_MAX 0x400000 /* 4 MiB */ + +/* Offsets for secondary header (for scan if primary header is corrupted). */ +#define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \ + 0x40000, 0x080000, 0x100000, 0x200000, LUKS2_HDR_OFFSET_MAX } + +int LUKS2_hdr_version_unlocked(struct crypt_device *cd, + const char *backup_file); + +int LUKS2_device_write_lock(struct crypt_device *cd, + struct luks2_hdr *hdr, struct device *device); + +int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair); +int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr); +int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr); +int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr); + +int LUKS2_hdr_uuid(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *uuid); + +int LUKS2_hdr_labels(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *label, + const char *subsystem, + int commit); + +void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr); + +int LUKS2_hdr_backup(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *backup_file); +int LUKS2_hdr_restore(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *backup_file); + +uint64_t LUKS2_hdr_and_areas_size(json_object *jobj); +uint64_t LUKS2_keyslots_size(json_object *jobj); +uint64_t LUKS2_metadata_size(json_object *jobj); + +int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec); + +/* + * Generic LUKS2 keyslot + */ +int LUKS2_keyslot_open(struct crypt_device *cd, + int keyslot, + int segment, + const char *password, + size_t password_len, + struct volume_key **vk); + +int LUKS2_keyslot_open_all_segments(struct crypt_device *cd, + int keyslot_old, + int keyslot_new, + const char *password, + size_t password_len, + struct volume_key **vks); + +int LUKS2_keyslot_store(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const char *password, + size_t password_len, + const struct volume_key *vk, + const struct luks2_keyslot_params *params); + +int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const void *buffer, + size_t buffer_length); + +int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const struct crypt_params_reencrypt *params); + +int reenc_keyslot_update(struct crypt_device *cd, + const struct luks2_reenc_context *rh); + +int LUKS2_keyslot_wipe(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int wipe_area_only); + +int LUKS2_keyslot_dump(struct crypt_device *cd, + int keyslot); + +crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot); + +int LUKS2_keyslot_priority_set(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + crypt_keyslot_priority priority, + int commit); + +/* + * Generic LUKS2 token + */ +int LUKS2_token_json_get(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char **json); + +int LUKS2_token_assign(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int token, + int assign, + int commit); + +int LUKS2_token_is_assigned(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int token); + +int LUKS2_token_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *json, + int commit); + +crypt_token_info LUKS2_token_status(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char **type); + +int LUKS2_builtin_token_get(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *type, + void *params); + +int LUKS2_builtin_token_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *type, + const void *params, + int commit); + +int LUKS2_token_open_and_activate(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *name, + uint32_t flags, + void *usrptr); + +int LUKS2_token_open_and_activate_any(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *name, + uint32_t flags); + +int LUKS2_tokens_count(struct luks2_hdr *hdr); + +/* + * Generic LUKS2 segment + */ +uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise); +const char *json_segment_type(json_object *jobj_segment); +uint64_t json_segment_get_iv_offset(json_object *jobj_segment); +uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise); +const char *json_segment_get_cipher(json_object *jobj_segment); +int json_segment_get_sector_size(json_object *jobj_segment); +bool json_segment_is_backup(json_object *jobj_segment); +json_object *json_segments_get_segment(json_object *jobj_segments, int segment); +unsigned json_segments_count(json_object *jobj_segments); +void json_segment_remove_flag(json_object *jobj_segment, const char *flag); +uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise); +json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption); +json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption); +int json_segments_segment_in_reencrypt(json_object *jobj_segments); + +int LUKS2_segments_count(struct luks2_hdr *hdr); + +int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr); + +int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag); + +json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag); + +int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag); + +int LUKS2_segments_set(struct crypt_device *cd, + struct luks2_hdr *hdr, + json_object *jobj_segments, + int commit); + +uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, + int segment, + unsigned blockwise); + +uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, + int segment, + unsigned blockwise); + +int LUKS2_segment_is_type(struct luks2_hdr *hdr, + int segment, + const char *type); + +int LUKS2_segment_by_type(struct luks2_hdr *hdr, + const char *type); + +int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, + const char *type); + +int LUKS2_get_default_segment(struct luks2_hdr *hdr); + +int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr); +int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr); +int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise); + +/* + * Generic LUKS2 digest + */ +int LUKS2_digest_any_matching(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk); + +int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment); + +int LUKS2_digest_verify_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, + int digest, + const struct volume_key *vk); + +int LUKS2_digest_verify_by_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, + int segment, + const struct volume_key *vk); + +void LUKS2_digests_erase_unused(struct crypt_device *cd, + struct luks2_hdr *hdr); + +int LUKS2_digest_verify(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk, + int keyslot); + +int LUKS2_digest_dump(struct crypt_device *cd, + int digest); + +int LUKS2_digest_assign(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int digest, + int assign, + int commit); + +int LUKS2_digest_segment_assign(struct crypt_device *cd, + struct luks2_hdr *hdr, + int segment, + int digest, + int assign, + int commit); + +int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot); + +int LUKS2_digest_create(struct crypt_device *cd, + const char *type, + struct luks2_hdr *hdr, + const struct volume_key *vk); + +/* + * LUKS2 generic + */ +int LUKS2_activate(struct crypt_device *cd, + const char *name, + struct volume_key *vk, + uint32_t flags); + +int LUKS2_activate_multi(struct crypt_device *cd, + const char *name, + struct volume_key *vks, + uint64_t device_size, + uint32_t flags); + +struct crypt_dm_active_device; + +int LUKS2_deactivate(struct crypt_device *cd, + const char *name, + struct luks2_hdr *hdr, + struct crypt_dm_active_device *dmd, + uint32_t flags); + +int LUKS2_reload(struct crypt_device *cd, + const char *name, + struct volume_key *vks, + uint64_t device_size, + uint32_t flags); + +int LUKS2_generate_hdr( + struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk, + const char *cipherName, + const char *cipherMode, + const char *integrity, + const char *uuid, + unsigned int sector_size, + uint64_t data_offset, + uint64_t align_offset, + uint64_t required_alignment, + uint64_t metadata_size, + uint64_t keyslots_size); + +int LUKS2_check_metadata_area_size(uint64_t metadata_size); +int LUKS2_check_keyslots_area_size(uint64_t keyslots_size); + +int LUKS2_wipe_header_areas(struct crypt_device *cd, + struct luks2_hdr *hdr); + +uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr); +int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic); +int LUKS2_get_sector_size(struct luks2_hdr *hdr); +const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment); +const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment); +int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr, + struct luks2_keyslot_params *params); +int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment); +int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot); +const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size); +int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr); +int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment); +int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment); +int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type); +crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot); +int LUKS2_keyslot_area(struct luks2_hdr *hdr, + int keyslot, + uint64_t *offset, + uint64_t *length); +int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf); +int LUKS2_set_keyslots_size(struct crypt_device *cd, + struct luks2_hdr *hdr, + uint64_t data_offset); + +/* + * Permanent activation flags stored in header + */ +int LUKS2_config_get_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *flags); +int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t flags); + +/* + * Requirements for device activation or header modification + */ +int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs); +int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit); + +int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet); + +int LUKS2_key_description_by_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int segment); +int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int keyslot); +int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int digest); + +struct luks_phdr; +int LUKS2_luks1_to_luks2(struct crypt_device *cd, + struct luks_phdr *hdr1, + struct luks2_hdr *hdr2); +int LUKS2_luks2_to_luks1(struct crypt_device *cd, + struct luks2_hdr *hdr2, + struct luks_phdr *hdr1); + +/* + * LUKS2 reencryption + */ +int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd, + int keyslot_old, + int keyslot_new, + const char *passphrase, + size_t passphrase_size, + uint32_t flags, + struct volume_key **vks); + +void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_context *rh); + +int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct volume_key *vks, + json_object *jobj_segments, + struct crypt_dm_active_device *dmd); + +crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd, + struct crypt_params_reencrypt *params); + +int crypt_reencrypt_lock(struct crypt_device *cd, struct crypt_lock_handle **reencrypt_lock); +int crypt_reencrypt_lock_by_dm_uuid(struct crypt_device *cd, const char *dm_uuid, struct crypt_lock_handle **reencrypt_lock); +void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock); + +int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic); + +#endif diff --git a/lib/luks2/luks2_digest.c b/lib/luks2/luks2_digest.c new file mode 100644 index 0000000..94b3abf --- /dev/null +++ b/lib/luks2/luks2_digest.c @@ -0,0 +1,455 @@ +/* + * LUKS - Linux Unified Key Setup v2, digest handling + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +extern const digest_handler PBKDF2_digest; + +static const digest_handler *digest_handlers[LUKS2_DIGEST_MAX] = { + &PBKDF2_digest, + NULL +}; + +static const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type) +{ + int i; + + for (i = 0; i < LUKS2_DIGEST_MAX && digest_handlers[i]; i++) { + if (!strcmp(digest_handlers[i]->name, type)) + return digest_handlers[i]; + } + + return NULL; +} + +static const digest_handler *LUKS2_digest_handler(struct crypt_device *cd, int digest) +{ + struct luks2_hdr *hdr; + json_object *jobj1, *jobj2; + + if (digest < 0) + return NULL; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return NULL; + + if (!(jobj1 = LUKS2_get_digest_jobj(hdr, digest))) + return NULL; + + if (!json_object_object_get_ex(jobj1, "type", &jobj2)) + return NULL; + + return LUKS2_digest_handler_type(cd, json_object_get_string(jobj2)); +} + +static int LUKS2_digest_find_free(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + int digest = 0; + + while (LUKS2_get_digest_jobj(hdr, digest) && digest < LUKS2_DIGEST_MAX) + digest++; + + return digest < LUKS2_DIGEST_MAX ? digest : -1; +} + +int LUKS2_digest_create(struct crypt_device *cd, + const char *type, + struct luks2_hdr *hdr, + const struct volume_key *vk) +{ + int digest; + const digest_handler *dh; + + dh = LUKS2_digest_handler_type(cd, type); + if (!dh) + return -EINVAL; + + digest = LUKS2_digest_find_free(cd, hdr); + if (digest < 0) + return -EINVAL; + + log_dbg(cd, "Creating new digest %d (%s).", digest, type); + + return dh->store(cd, digest, vk->key, vk->keylength) ?: digest; +} + +int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot) +{ + char keyslot_name[16]; + json_object *jobj_digests, *jobj_digest_keyslots; + + if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1) + return -ENOMEM; + + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + + json_object_object_foreach(jobj_digests, key, val) { + json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots); + if (LUKS2_array_jobj(jobj_digest_keyslots, keyslot_name)) + return atoi(key); + } + + return -ENOENT; +} + +int LUKS2_digest_verify_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, + int digest, + const struct volume_key *vk) +{ + const digest_handler *h; + int r; + + h = LUKS2_digest_handler(cd, digest); + if (!h) + return -EINVAL; + + r = h->verify(cd, digest, vk->key, vk->keylength); + if (r < 0) { + log_dbg(cd, "Digest %d (%s) verify failed with %d.", digest, h->name, r); + return r; + } + + return digest; +} + +int LUKS2_digest_verify(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk, + int keyslot) +{ + int digest; + + digest = LUKS2_digest_by_keyslot(hdr, keyslot); + if (digest < 0) + return digest; + + log_dbg(cd, "Verifying key from keyslot %d, digest %d.", keyslot, digest); + + return LUKS2_digest_verify_by_digest(cd, hdr, digest, vk); +} + +int LUKS2_digest_dump(struct crypt_device *cd, int digest) +{ + const digest_handler *h; + + if (!(h = LUKS2_digest_handler(cd, digest))) + return -EINVAL; + + return h->dump(cd, digest); +} + +int LUKS2_digest_any_matching(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk) +{ + int digest; + + for (digest = 0; digest < LUKS2_DIGEST_MAX; digest++) + if (LUKS2_digest_verify_by_digest(cd, hdr, digest, vk) == digest) + return digest; + + return -ENOENT; +} + +int LUKS2_digest_verify_by_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, + int segment, + const struct volume_key *vk) +{ + return LUKS2_digest_verify_by_digest(cd, hdr, LUKS2_digest_by_segment(hdr, segment), vk); +} + +/* FIXME: segment can have more digests */ +int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment) +{ + char segment_name[16]; + json_object *jobj_digests, *jobj_digest_segments; + + if (segment == CRYPT_DEFAULT_SEGMENT) + segment = LUKS2_get_default_segment(hdr); + + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + + if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1) + return -EINVAL; + + json_object_object_foreach(jobj_digests, key, val) { + json_object_object_get_ex(val, "segments", &jobj_digest_segments); + if (!LUKS2_array_jobj(jobj_digest_segments, segment_name)) + continue; + + return atoi(key); + } + + return -ENOENT; +} + +static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int digest, int assign) +{ + json_object *jobj1, *jobj_digest, *jobj_digest_keyslots; + char num[16]; + + log_dbg(cd, "Keyslot %i %s digest %i.", keyslot, assign ? "assigned to" : "unassigned from", digest); + + jobj_digest = LUKS2_get_digest_jobj(hdr, digest); + if (!jobj_digest) + return -EINVAL; + + json_object_object_get_ex(jobj_digest, "keyslots", &jobj_digest_keyslots); + if (!jobj_digest_keyslots) + return -EINVAL; + + snprintf(num, sizeof(num), "%d", keyslot); + if (assign) { + jobj1 = LUKS2_array_jobj(jobj_digest_keyslots, num); + if (!jobj1) + json_object_array_add(jobj_digest_keyslots, json_object_new_string(num)); + } else { + jobj1 = LUKS2_array_remove(jobj_digest_keyslots, num); + if (jobj1) + json_object_object_add(jobj_digest, "keyslots", jobj1); + } + + return 0; +} + +int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int digest, int assign, int commit) +{ + json_object *jobj_digests; + int r = 0; + + if (digest == CRYPT_ANY_DIGEST) { + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + + json_object_object_foreach(jobj_digests, key, val) { + UNUSED(val); + r = assign_one_digest(cd, hdr, keyslot, atoi(key), assign); + if (r < 0) + break; + } + } else + r = assign_one_digest(cd, hdr, keyslot, digest, assign); + + if (r < 0) + return r; + + // FIXME: do not write header in nothing changed + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +static int assign_all_segments(struct crypt_device *cd, struct luks2_hdr *hdr, + int digest, int assign) +{ + json_object *jobj1, *jobj_digest, *jobj_digest_segments; + + jobj_digest = LUKS2_get_digest_jobj(hdr, digest); + if (!jobj_digest) + return -EINVAL; + + json_object_object_get_ex(jobj_digest, "segments", &jobj_digest_segments); + if (!jobj_digest_segments) + return -EINVAL; + + if (assign) { + json_object_object_foreach(LUKS2_get_segments_jobj(hdr), key, value) { + UNUSED(value); + jobj1 = LUKS2_array_jobj(jobj_digest_segments, key); + if (!jobj1) + json_object_array_add(jobj_digest_segments, json_object_new_string(key)); + } + } else { + jobj1 = json_object_new_array(); + if (!jobj1) + return -ENOMEM; + json_object_object_add(jobj_digest, "segments", jobj1); + } + + return 0; +} + +static int assign_one_segment(struct crypt_device *cd, struct luks2_hdr *hdr, + int segment, int digest, int assign) +{ + json_object *jobj1, *jobj_digest, *jobj_digest_segments; + char num[16]; + + log_dbg(cd, "Segment %i %s digest %i.", segment, assign ? "assigned to" : "unassigned from", digest); + + jobj_digest = LUKS2_get_digest_jobj(hdr, digest); + if (!jobj_digest) + return -EINVAL; + + json_object_object_get_ex(jobj_digest, "segments", &jobj_digest_segments); + if (!jobj_digest_segments) + return -EINVAL; + + snprintf(num, sizeof(num), "%d", segment); + if (assign) { + jobj1 = LUKS2_array_jobj(jobj_digest_segments, num); + if (!jobj1) + json_object_array_add(jobj_digest_segments, json_object_new_string(num)); + } else { + jobj1 = LUKS2_array_remove(jobj_digest_segments, num); + if (jobj1) + json_object_object_add(jobj_digest, "segments", jobj1); + } + + return 0; +} + +int LUKS2_digest_segment_assign(struct crypt_device *cd, struct luks2_hdr *hdr, + int segment, int digest, int assign, int commit) +{ + json_object *jobj_digests; + int r = 0; + + if (segment == CRYPT_DEFAULT_SEGMENT) + segment = LUKS2_get_default_segment(hdr); + + if (digest == CRYPT_ANY_DIGEST) { + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + + json_object_object_foreach(jobj_digests, key, val) { + UNUSED(val); + if (segment == CRYPT_ANY_SEGMENT) + r = assign_all_segments(cd, hdr, atoi(key), assign); + else + r = assign_one_segment(cd, hdr, segment, atoi(key), assign); + if (r < 0) + break; + } + } else { + if (segment == CRYPT_ANY_SEGMENT) + r = assign_all_segments(cd, hdr, digest, assign); + else + r = assign_one_segment(cd, hdr, segment, digest, assign); + } + + if (r < 0) + return r; + + // FIXME: do not write header in nothing changed + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +static int digest_unused(json_object *jobj_digest) +{ + json_object *jobj; + + json_object_object_get_ex(jobj_digest, "segments", &jobj); + if (!jobj || !json_object_is_type(jobj, json_type_array) || json_object_array_length(jobj) > 0) + return 0; + + json_object_object_get_ex(jobj_digest, "keyslots", &jobj); + if (!jobj || !json_object_is_type(jobj, json_type_array)) + return 0; + + return json_object_array_length(jobj) > 0 ? 0 : 1; +} + +void LUKS2_digests_erase_unused(struct crypt_device *cd, + struct luks2_hdr *hdr) +{ + json_object *jobj_digests; + + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + if (!jobj_digests || !json_object_is_type(jobj_digests, json_type_object)) + return; + + json_object_object_foreach(jobj_digests, key, val) { + if (digest_unused(val)) { + log_dbg(cd, "Erasing unused digest %d.", atoi(key)); + json_object_object_del(jobj_digests, key); + } + } +} + +/* Key description helpers */ +static char *get_key_description_by_digest(struct crypt_device *cd, int digest) +{ + char *desc, digest_str[3]; + int r; + size_t len; + + if (!crypt_get_uuid(cd)) + return NULL; + + r = snprintf(digest_str, sizeof(digest_str), "d%u", digest); + if (r < 0 || (size_t)r >= sizeof(digest_str)) + return NULL; + + /* "cryptsetup:-" + \0 */ + len = strlen(crypt_get_uuid(cd)) + strlen(digest_str) + 13; + + desc = malloc(len); + if (!desc) + return NULL; + + r = snprintf(desc, len, "%s:%s-%s", "cryptsetup", crypt_get_uuid(cd), digest_str); + if (r < 0 || (size_t)r >= len) { + free(desc); + return NULL; + } + + return desc; +} + +int LUKS2_key_description_by_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int segment) +{ + char *desc = get_key_description_by_digest(cd, LUKS2_digest_by_segment(hdr, segment)); + int r; + + r = crypt_volume_key_set_description(vk, desc); + free(desc); + return r; +} + +int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int keyslot) +{ + char *desc = get_key_description_by_digest(cd, LUKS2_digest_by_keyslot(hdr, keyslot)); + int r; + + r = crypt_volume_key_set_description(vk, desc); + if (!r) + r = crypt_volume_key_load_in_keyring(cd, vk); + + free(desc); + return r; +} + +int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, struct volume_key *vk, int digest) +{ + char *desc = get_key_description_by_digest(cd, digest); + int r; + + r = crypt_volume_key_set_description(vk, desc); + if (!r) + r = crypt_volume_key_load_in_keyring(cd, vk); + + free(desc); + return r; +} diff --git a/lib/luks2/luks2_digest_pbkdf2.c b/lib/luks2/luks2_digest_pbkdf2.c new file mode 100644 index 0000000..bf1e4f9 --- /dev/null +++ b/lib/luks2/luks2_digest_pbkdf2.c @@ -0,0 +1,211 @@ +/* + * LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible) + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +#define LUKS_DIGESTSIZE 20 // since SHA1 +#define LUKS_SALTSIZE 32 +#define LUKS_MKD_ITERATIONS_MS 125 + +static int PBKDF2_digest_verify(struct crypt_device *cd, + int digest, + const char *volume_key, + size_t volume_key_len) +{ + char checkHashBuf[64]; + json_object *jobj_digest, *jobj1; + const char *hashSpec; + char *mkDigest = NULL, mkDigestSalt[LUKS_SALTSIZE]; + unsigned int mkDigestIterations; + size_t len; + int r; + + /* This can be done only for internally linked digests */ + jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest); + if (!jobj_digest) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_digest, "hash", &jobj1)) + return -EINVAL; + hashSpec = json_object_get_string(jobj1); + + if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1)) + return -EINVAL; + mkDigestIterations = json_object_get_int64(jobj1); + + if (!json_object_object_get_ex(jobj_digest, "salt", &jobj1)) + return -EINVAL; + len = sizeof(mkDigestSalt); + if (!base64_decode(json_object_get_string(jobj1), + json_object_get_string_len(jobj1), mkDigestSalt, &len)) + return -EINVAL; + if (len != LUKS_SALTSIZE) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1)) + return -EINVAL; + len = 0; + if (!base64_decode_alloc(json_object_get_string(jobj1), + json_object_get_string_len(jobj1), &mkDigest, &len)) + return -EINVAL; + if (len < LUKS_DIGESTSIZE || + len > sizeof(checkHashBuf) || + (len != LUKS_DIGESTSIZE && len != (size_t)crypt_hash_size(hashSpec))) { + free(mkDigest); + return -EINVAL; + } + + r = -EPERM; + if (crypt_pbkdf(CRYPT_KDF_PBKDF2, hashSpec, volume_key, volume_key_len, + mkDigestSalt, LUKS_SALTSIZE, + checkHashBuf, len, + mkDigestIterations, 0, 0) < 0) { + r = -EINVAL; + } else { + if (memcmp(checkHashBuf, mkDigest, len) == 0) + r = 0; + } + + free(mkDigest); + return r; +} + +static int PBKDF2_digest_store(struct crypt_device *cd, + int digest, + const char *volume_key, + size_t volume_key_len) +{ + json_object *jobj_digest, *jobj_digests; + char salt[LUKS_SALTSIZE], digest_raw[128]; + int hmac_size, r; + char *base64_str; + struct luks2_hdr *hdr; + struct crypt_pbkdf_limits pbkdf_limits; + const struct crypt_pbkdf_type *pbkdf_cd; + struct crypt_pbkdf_type pbkdf = { + .type = CRYPT_KDF_PBKDF2, + .time_ms = LUKS_MKD_ITERATIONS_MS, + }; + + /* Inherit hash from PBKDF setting */ + pbkdf_cd = crypt_get_pbkdf_type(cd); + if (pbkdf_cd) + pbkdf.hash = pbkdf_cd->hash; + if (!pbkdf.hash) + pbkdf.hash = DEFAULT_LUKS1_HASH; + + log_dbg(cd, "Setting PBKDF2 type key digest %d.", digest); + + r = crypt_random_get(cd, salt, LUKS_SALTSIZE, CRYPT_RND_SALT); + if (r < 0) + return r; + + r = crypt_pbkdf_get_limits(CRYPT_KDF_PBKDF2, &pbkdf_limits); + if (r < 0) + return r; + + if (crypt_get_pbkdf(cd)->flags & CRYPT_PBKDF_NO_BENCHMARK) + pbkdf.iterations = pbkdf_limits.min_iterations; + else { + r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len); + if (r < 0) + return r; + } + + hmac_size = crypt_hmac_size(pbkdf.hash); + if (hmac_size < 0 || hmac_size > (int)sizeof(digest_raw)) + return -EINVAL; + + r = crypt_pbkdf(CRYPT_KDF_PBKDF2, pbkdf.hash, volume_key, volume_key_len, + salt, LUKS_SALTSIZE, digest_raw, hmac_size, + pbkdf.iterations, 0, 0); + if (r < 0) + return r; + + jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest); + jobj_digests = NULL; + if (!jobj_digest) { + hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + jobj_digest = json_object_new_object(); + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + } + + json_object_object_add(jobj_digest, "type", json_object_new_string("pbkdf2")); + json_object_object_add(jobj_digest, "keyslots", json_object_new_array()); + json_object_object_add(jobj_digest, "segments", json_object_new_array()); + json_object_object_add(jobj_digest, "hash", json_object_new_string(pbkdf.hash)); + json_object_object_add(jobj_digest, "iterations", json_object_new_int(pbkdf.iterations)); + + base64_encode_alloc(salt, LUKS_SALTSIZE, &base64_str); + if (!base64_str) { + json_object_put(jobj_digest); + return -ENOMEM; + } + json_object_object_add(jobj_digest, "salt", json_object_new_string(base64_str)); + free(base64_str); + + base64_encode_alloc(digest_raw, hmac_size, &base64_str); + if (!base64_str) { + json_object_put(jobj_digest); + return -ENOMEM; + } + json_object_object_add(jobj_digest, "digest", json_object_new_string(base64_str)); + free(base64_str); + + if (jobj_digests) + json_object_object_add_by_uint(jobj_digests, digest, jobj_digest); + + JSON_DBG(cd, jobj_digest, "Digest JSON:"); + return 0; +} + +static int PBKDF2_digest_dump(struct crypt_device *cd, int digest) +{ + json_object *jobj_digest, *jobj1; + + /* This can be done only for internally linked digests */ + jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest); + if (!jobj_digest) + return -EINVAL; + + json_object_object_get_ex(jobj_digest, "hash", &jobj1); + log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1)); + + json_object_object_get_ex(jobj_digest, "iterations", &jobj1); + log_std(cd, "\tIterations: %" PRIu64 "\n", json_object_get_int64(jobj1)); + + json_object_object_get_ex(jobj_digest, "salt", &jobj1); + log_std(cd, "\tSalt: "); + hexprint_base64(cd, jobj1, " ", " "); + + json_object_object_get_ex(jobj_digest, "digest", &jobj1); + log_std(cd, "\tDigest: "); + hexprint_base64(cd, jobj1, " ", " "); + + return 0; +} + +const digest_handler PBKDF2_digest = { + .name = "pbkdf2", + .verify = PBKDF2_digest_verify, + .store = PBKDF2_digest_store, + .dump = PBKDF2_digest_dump, +}; diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c new file mode 100644 index 0000000..9654cdb --- /dev/null +++ b/lib/luks2/luks2_disk_metadata.c @@ -0,0 +1,806 @@ +/* + * LUKS - Linux Unified Key Setup v2 + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "luks2_internal.h" + +/* + * Helper functions + */ +static json_object *parse_json_len(struct crypt_device *cd, const char *json_area, + uint64_t max_length, int *json_len) +{ + json_object *jobj; + struct json_tokener *jtok; + + /* INT32_MAX is internal (json-c) json_tokener_parse_ex() limit */ + if (!json_area || max_length > INT32_MAX) + return NULL; + + jtok = json_tokener_new(); + if (!jtok) { + log_dbg(cd, "ERROR: Failed to init json tokener"); + return NULL; + } + + jobj = json_tokener_parse_ex(jtok, json_area, max_length); + if (!jobj) + log_dbg(cd, "ERROR: Failed to parse json data (%d): %s", + json_tokener_get_error(jtok), + json_tokener_error_desc(json_tokener_get_error(jtok))); + else + *json_len = jtok->char_offset; + + json_tokener_free(jtok); + + return jobj; +} + +static void log_dbg_checksum(struct crypt_device *cd, + const uint8_t *csum, const char *csum_alg, const char *info) +{ + char csum_txt[2*LUKS2_CHECKSUM_L+1]; + int i; + + for (i = 0; i < crypt_hash_size(csum_alg); i++) + snprintf(&csum_txt[i*2], 3, "%02hhx", (const char)csum[i]); + csum_txt[i*2+1] = '\0'; /* Just to be safe, sprintf should write \0 there. */ + + log_dbg(cd, "Checksum:%s (%s)", &csum_txt[0], info); +} + +/* + * Calculate hash (checksum) of |LUKS2_bin|LUKS2_JSON_area| from in-memory structs. + * LUKS2 on-disk header contains uniques salt both for primary and secondary header. + * Checksum is always calculated with zeroed checksum field in binary header. + */ +static int hdr_checksum_calculate(const char *alg, struct luks2_hdr_disk *hdr_disk, + const char *json_area, size_t json_len) +{ + struct crypt_hash *hd = NULL; + int hash_size, r; + + hash_size = crypt_hash_size(alg); + if (hash_size <= 0 || crypt_hash_init(&hd, alg)) + return -EINVAL; + + /* Binary header, csum zeroed. */ + r = crypt_hash_write(hd, (char*)hdr_disk, LUKS2_HDR_BIN_LEN); + + /* JSON area (including unused space) */ + if (!r) + r = crypt_hash_write(hd, json_area, json_len); + + if (!r) + r = crypt_hash_final(hd, (char*)hdr_disk->csum, (size_t)hash_size); + + crypt_hash_destroy(hd); + return r; +} + +/* + * Compare hash (checksum) of on-disk and in-memory header. + */ +static int hdr_checksum_check(struct crypt_device *cd, + const char *alg, struct luks2_hdr_disk *hdr_disk, + const char *json_area, size_t json_len) +{ + struct luks2_hdr_disk hdr_tmp; + int hash_size, r; + + hash_size = crypt_hash_size(alg); + if (hash_size <= 0) + return -EINVAL; + + /* Copy header and zero checksum. */ + memcpy(&hdr_tmp, hdr_disk, LUKS2_HDR_BIN_LEN); + memset(&hdr_tmp.csum, 0, sizeof(hdr_tmp.csum)); + + r = hdr_checksum_calculate(alg, &hdr_tmp, json_area, json_len); + if (r < 0) + return r; + + log_dbg_checksum(cd, hdr_disk->csum, alg, "on-disk"); + log_dbg_checksum(cd, hdr_tmp.csum, alg, "in-memory"); + + if (memcmp(hdr_tmp.csum, hdr_disk->csum, (size_t)hash_size)) + return -EINVAL; + + return 0; +} + +/* + * Convert header from on-disk format to in-memory struct + */ +static void hdr_from_disk(struct luks2_hdr_disk *hdr_disk1, + struct luks2_hdr_disk *hdr_disk2, + struct luks2_hdr *hdr, + int secondary) +{ + hdr->version = be16_to_cpu(hdr_disk1->version); + hdr->hdr_size = be64_to_cpu(hdr_disk1->hdr_size); + hdr->seqid = be64_to_cpu(hdr_disk1->seqid); + + memcpy(hdr->label, hdr_disk1->label, LUKS2_LABEL_L); + hdr->label[LUKS2_LABEL_L - 1] = '\0'; + memcpy(hdr->subsystem, hdr_disk1->subsystem, LUKS2_LABEL_L); + hdr->subsystem[LUKS2_LABEL_L - 1] = '\0'; + memcpy(hdr->checksum_alg, hdr_disk1->checksum_alg, LUKS2_CHECKSUM_ALG_L); + hdr->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0'; + memcpy(hdr->uuid, hdr_disk1->uuid, LUKS2_UUID_L); + hdr->uuid[LUKS2_UUID_L - 1] = '\0'; + + if (secondary) { + memcpy(hdr->salt1, hdr_disk2->salt, LUKS2_SALT_L); + memcpy(hdr->salt2, hdr_disk1->salt, LUKS2_SALT_L); + } else { + memcpy(hdr->salt1, hdr_disk1->salt, LUKS2_SALT_L); + memcpy(hdr->salt2, hdr_disk2->salt, LUKS2_SALT_L); + } +} + +/* + * Convert header from in-memory struct to on-disk format + */ +static void hdr_to_disk(struct luks2_hdr *hdr, + struct luks2_hdr_disk *hdr_disk, + int secondary, uint64_t offset) +{ + assert(((char*)&(hdr_disk->_padding4096) - (char*)&(hdr_disk->magic)) == 512); + + memset(hdr_disk, 0, LUKS2_HDR_BIN_LEN); + + memcpy(&hdr_disk->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L); + hdr_disk->version = cpu_to_be16(hdr->version); + hdr_disk->hdr_size = cpu_to_be64(hdr->hdr_size); + hdr_disk->hdr_offset = cpu_to_be64(offset); + hdr_disk->seqid = cpu_to_be64(hdr->seqid); + + strncpy(hdr_disk->label, hdr->label, LUKS2_LABEL_L); + hdr_disk->label[LUKS2_LABEL_L - 1] = '\0'; + strncpy(hdr_disk->subsystem, hdr->subsystem, LUKS2_LABEL_L); + hdr_disk->subsystem[LUKS2_LABEL_L - 1] = '\0'; + strncpy(hdr_disk->checksum_alg, hdr->checksum_alg, LUKS2_CHECKSUM_ALG_L); + hdr_disk->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0'; + strncpy(hdr_disk->uuid, hdr->uuid, LUKS2_UUID_L); + hdr_disk->uuid[LUKS2_UUID_L - 1] = '\0'; + + memcpy(hdr_disk->salt, secondary ? hdr->salt2 : hdr->salt1, LUKS2_SALT_L); +} + +/* + * Sanity checks before checksum is validated + */ +static int hdr_disk_sanity_check_pre(struct crypt_device *cd, + struct luks2_hdr_disk *hdr, + size_t *hdr_json_size, int secondary, + uint64_t offset) +{ + if (memcmp(hdr->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L)) + return -EINVAL; + + if (be16_to_cpu(hdr->version) != 2) { + log_dbg(cd, "Unsupported LUKS2 header version %u.", be16_to_cpu(hdr->version)); + return -EINVAL; + } + + if (offset != be64_to_cpu(hdr->hdr_offset)) { + log_dbg(cd, "LUKS2 offset 0x%04x on device differs to expected offset 0x%04x.", + (unsigned)be64_to_cpu(hdr->hdr_offset), (unsigned)offset); + return -EINVAL; + } + + if (secondary && (offset != be64_to_cpu(hdr->hdr_size))) { + log_dbg(cd, "LUKS2 offset 0x%04x in secondary header does not match size 0x%04x.", + (unsigned)offset, (unsigned)be64_to_cpu(hdr->hdr_size)); + return -EINVAL; + } + + /* FIXME: sanity check checksum alg. */ + + log_dbg(cd, "LUKS2 header version %u of size %u bytes, checksum %s.", + (unsigned)be16_to_cpu(hdr->version), (unsigned)be64_to_cpu(hdr->hdr_size), + hdr->checksum_alg); + + *hdr_json_size = be64_to_cpu(hdr->hdr_size) - LUKS2_HDR_BIN_LEN; + return 0; +} + +/* + * Read LUKS2 header from disk at specific offset. + */ +static int hdr_read_disk(struct crypt_device *cd, + struct device *device, struct luks2_hdr_disk *hdr_disk, + char **json_area, uint64_t offset, int secondary) +{ + size_t hdr_json_size = 0; + int devfd, r; + + log_dbg(cd, "Trying to read %s LUKS2 header at offset 0x%" PRIx64 ".", + secondary ? "secondary" : "primary", offset); + + devfd = device_open_locked(cd, device, O_RDONLY); + if (devfd < 0) + return devfd == -1 ? -EIO : devfd; + + /* + * Read binary header and run sanity check before reading + * JSON area and validating checksum. + */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr_disk, + LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) { + return -EIO; + } + + r = hdr_disk_sanity_check_pre(cd, hdr_disk, &hdr_json_size, secondary, offset); + if (r < 0) { + return r; + } + + /* + * Allocate and read JSON area. Always the whole area must be read. + */ + *json_area = malloc(hdr_json_size); + if (!*json_area) { + return -ENOMEM; + } + + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), *json_area, hdr_json_size, + offset + LUKS2_HDR_BIN_LEN) != (ssize_t)hdr_json_size) { + free(*json_area); + *json_area = NULL; + return -EIO; + } + + /* + * Calculate and validate checksum and zero it afterwards. + */ + if (hdr_checksum_check(cd, hdr_disk->checksum_alg, hdr_disk, + *json_area, hdr_json_size)) { + log_dbg(cd, "LUKS2 header checksum error (offset %" PRIu64 ").", offset); + r = -EINVAL; + } + memset(hdr_disk->csum, 0, LUKS2_CHECKSUM_L); + + return r; +} + +/* + * Write LUKS2 header to disk at specific offset. + */ +static int hdr_write_disk(struct crypt_device *cd, + struct device *device, struct luks2_hdr *hdr, + const char *json_area, int secondary) +{ + struct luks2_hdr_disk hdr_disk; + uint64_t offset = secondary ? hdr->hdr_size : 0; + size_t hdr_json_len; + int devfd, r; + + log_dbg(cd, "Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 ".", + hdr->hdr_size, offset); + + /* FIXME: read-only device silent fail? */ + + devfd = device_open_locked(cd, device, O_RDWR); + if (devfd < 0) + return devfd == -1 ? -EINVAL : devfd; + + hdr_json_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN; + + hdr_to_disk(hdr, &hdr_disk, secondary, offset); + + /* + * Write header without checksum but with proper seqid. + */ + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), (char *)&hdr_disk, + LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN) { + return -EIO; + } + + /* + * Write json area. + */ + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), + CONST_CAST(char*)json_area, hdr_json_len, + LUKS2_HDR_BIN_LEN + offset) < (ssize_t)hdr_json_len) { + return -EIO; + } + + /* + * Calculate checksum and write header with checksum. + */ + r = hdr_checksum_calculate(hdr_disk.checksum_alg, &hdr_disk, + json_area, hdr_json_len); + if (r < 0) { + return r; + } + log_dbg_checksum(cd, hdr_disk.csum, hdr_disk.checksum_alg, "in-memory"); + + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), (char *)&hdr_disk, + LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN) + r = -EIO; + + device_sync(cd, device); + return r; +} + +static int LUKS2_check_sequence_id(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device) +{ + int devfd; + struct luks2_hdr_disk dhdr; + + if (!hdr) + return -EINVAL; + + devfd = device_open_locked(cd, device, O_RDONLY); + if (devfd < 0) + return devfd == -1 ? -EINVAL : devfd; + + /* we need only first 512 bytes, see luks2_hdr_disk structure */ + if ((read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &dhdr, 512, 0) != 512)) + return -EIO; + + /* there's nothing to check if there's no LUKS2 header */ + if ((be16_to_cpu(dhdr.version) != 2) || + memcmp(dhdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L) || + strcmp(dhdr.uuid, hdr->uuid)) + return 0; + + return hdr->seqid != be64_to_cpu(dhdr.seqid); +} + +int LUKS2_device_write_lock(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device) +{ + int r = device_write_lock(cd, device); + + if (r < 0) { + log_err(cd, _("Failed to acquire write lock on device %s."), device_path(device)); + return r; + } + + /* run sequence id check only on first write lock (r == 1) and w/o LUKS2 reencryption in-progress */ + if (r == 1 && !crypt_get_reenc_context(cd)) { + log_dbg(cd, "Checking context sequence id matches value stored on disk."); + if (LUKS2_check_sequence_id(cd, hdr, device)) { + device_write_unlock(cd, device); + log_err(cd, _("Detected attempt for concurrent LUKS2 metadata update. Aborting operation.")); + return -EINVAL; + } + } + + return 0; +} + +/* + * Convert in-memory LUKS2 header and write it to disk. + * This will increase sequence id, write both header copies and calculate checksum. + */ +int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device, bool seqid_check) +{ + char *json_area; + const char *json_text; + size_t json_area_len; + int r; + + if (hdr->version != 2) { + log_dbg(cd, "Unsupported LUKS2 header version (%u).", hdr->version); + return -EINVAL; + } + + r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj), 1); + if (r) + return r; + + /* + * Allocate and zero JSON area (of proper header size). + */ + json_area_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN; + json_area = crypt_zalloc(json_area_len); + if (!json_area) + return -ENOMEM; + + /* + * Generate text space-efficient JSON representation to json area. + */ + json_text = json_object_to_json_string_ext(hdr->jobj, + JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE); + if (!json_text || !*json_text) { + log_dbg(cd, "Cannot parse JSON object to text representation."); + free(json_area); + return -ENOMEM; + } + if (strlen(json_text) > (json_area_len - 1)) { + log_dbg(cd, "JSON is too large (%zu > %zu).", strlen(json_text), json_area_len); + free(json_area); + return -EINVAL; + } + strncpy(json_area, json_text, json_area_len); + + if (seqid_check) + r = LUKS2_device_write_lock(cd, hdr, device); + else + r = device_write_lock(cd, device); + if (r < 0) { + free(json_area); + return r; + } + + /* Increase sequence id before writing it to disk. */ + hdr->seqid++; + + /* Write primary and secondary header */ + r = hdr_write_disk(cd, device, hdr, json_area, 0); + if (!r) + r = hdr_write_disk(cd, device, hdr, json_area, 1); + + if (r) + log_dbg(cd, "LUKS2 header write failed (%d).", r); + + device_write_unlock(cd, device); + + free(json_area); + return r; +} +static int validate_json_area(struct crypt_device *cd, const char *json_area, + uint64_t json_len, uint64_t max_length) +{ + char c; + + /* Enforce there are no needless opening bytes */ + if (*json_area != '{') { + log_dbg(cd, "ERROR: Opening character must be left curly bracket: '{'."); + return -EINVAL; + } + + if (json_len >= max_length) { + log_dbg(cd, "ERROR: Missing trailing null byte beyond parsed json data string."); + return -EINVAL; + } + + /* + * TODO: + * validate there are legal json format characters between + * 'json_area' and 'json_area + json_len' + */ + + do { + c = *(json_area + json_len); + if (c != '\0') { + log_dbg(cd, "ERROR: Forbidden ascii code 0x%02hhx found beyond json data string at offset %" PRIu64, + c, json_len); + return -EINVAL; + } + } while (++json_len < max_length); + + return 0; +} + +static int validate_luks2_json_object(struct crypt_device *cd, json_object *jobj_hdr, uint64_t length) +{ + int r; + + /* we require top level object to be of json_type_object */ + r = !json_object_is_type(jobj_hdr, json_type_object); + if (r) { + log_dbg(cd, "ERROR: Resulting object is not a json object type"); + return r; + } + + r = LUKS2_hdr_validate(cd, jobj_hdr, length); + if (r) { + log_dbg(cd, "Repairing JSON metadata."); + /* try to correct known glitches */ + LUKS2_hdr_repair(cd, jobj_hdr); + + /* run validation again */ + r = LUKS2_hdr_validate(cd, jobj_hdr, length); + } + + if (r) + log_dbg(cd, "ERROR: LUKS2 validation failed"); + + return r; +} + +static json_object *parse_and_validate_json(struct crypt_device *cd, + const char *json_area, uint64_t max_length) +{ + int json_len, r; + json_object *jobj = parse_json_len(cd, json_area, max_length, &json_len); + + if (!jobj) + return NULL; + + /* successful parse_json_len must not return offset <= 0 */ + assert(json_len > 0); + + r = validate_json_area(cd, json_area, json_len, max_length); + if (!r) + r = validate_luks2_json_object(cd, jobj, max_length); + + if (r) { + json_object_put(jobj); + jobj = NULL; + } + + return jobj; +} + +static int detect_device_signatures(struct crypt_device *cd, const char *path) +{ + blk_probe_status prb_state; + int r; + struct blkid_handle *h; + + if (!blk_supported()) { + log_dbg(cd, "Blkid probing of device signatures disabled."); + return 0; + } + + if ((r = blk_init_by_path(&h, path))) { + log_dbg(cd, "Failed to initialize blkid_handle by path."); + return -EINVAL; + } + + /* We don't care about details. Be fast. */ + blk_set_chains_for_fast_detection(h); + + /* Filter out crypto_LUKS. we don't care now */ + blk_superblocks_filter_luks(h); + + prb_state = blk_safeprobe(h); + + switch (prb_state) { + case PRB_AMBIGUOUS: + log_dbg(cd, "Blkid probe couldn't decide device type unambiguously."); + /* fall through */ + case PRB_FAIL: + log_dbg(cd, "Blkid probe failed."); + r = -EINVAL; + break; + case PRB_OK: /* crypto_LUKS type is filtered out */ + r = -EINVAL; + + if (blk_is_partition(h)) + log_dbg(cd, "Blkid probe detected partition type '%s'", blk_get_partition_type(h)); + else if (blk_is_superblock(h)) + log_dbg(cd, "blkid probe detected superblock type '%s'", blk_get_superblock_type(h)); + break; + case PRB_EMPTY: + log_dbg(cd, "Blkid probe detected no foreign device signature."); + } + blk_free(h); + return r; +} + +/* + * Read and convert on-disk LUKS2 header to in-memory representation.. + * Try to do recovery if on-disk state is not consistent. + */ +int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, + struct device *device, int do_recovery, int do_blkprobe) +{ + enum { HDR_OK, HDR_OBSOLETE, HDR_FAIL, HDR_FAIL_IO } state_hdr1, state_hdr2; + struct luks2_hdr_disk hdr_disk1, hdr_disk2; + char *json_area1 = NULL, *json_area2 = NULL; + json_object *jobj_hdr1 = NULL, *jobj_hdr2 = NULL; + unsigned int i; + int r; + uint64_t hdr_size; + uint64_t hdr2_offsets[] = LUKS2_HDR2_OFFSETS; + + /* Skip auto-recovery if locks are disabled and we're not doing LUKS2 explicit repair */ + if (do_recovery && do_blkprobe && !crypt_metadata_locking_enabled()) { + do_recovery = 0; + log_dbg(cd, "Disabling header auto-recovery due to locking being disabled."); + } + + /* + * Read primary LUKS2 header (offset 0). + */ + state_hdr1 = HDR_FAIL; + r = hdr_read_disk(cd, device, &hdr_disk1, &json_area1, 0, 0); + if (r == 0) { + jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size) - LUKS2_HDR_BIN_LEN); + state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE; + } else if (r == -EIO) + state_hdr1 = HDR_FAIL_IO; + + /* + * Read secondary LUKS2 header (follows primary). + */ + state_hdr2 = HDR_FAIL; + if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO) { + r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, be64_to_cpu(hdr_disk1.hdr_size), 1); + if (r == 0) { + jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN); + state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE; + } else if (r == -EIO) + state_hdr2 = HDR_FAIL_IO; + } else { + /* + * No header size, check all known offsets. + */ + for (r = -EINVAL,i = 0; r < 0 && i < ARRAY_SIZE(hdr2_offsets); i++) + r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, hdr2_offsets[i], 1); + + if (r == 0) { + jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN); + state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE; + } else if (r == -EIO) + state_hdr2 = HDR_FAIL_IO; + } + + /* + * Check sequence id if both headers are read correctly. + */ + if (state_hdr1 == HDR_OK && state_hdr2 == HDR_OK) { + if (be64_to_cpu(hdr_disk1.seqid) > be64_to_cpu(hdr_disk2.seqid)) + state_hdr2 = HDR_OBSOLETE; + else if (be64_to_cpu(hdr_disk1.seqid) < be64_to_cpu(hdr_disk2.seqid)) + state_hdr1 = HDR_OBSOLETE; + } + + /* check header with keyslots to fit the device */ + if (state_hdr1 == HDR_OK) + hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr1); + else if (state_hdr2 == HDR_OK) + hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr2); + else { + r = (state_hdr1 == HDR_FAIL_IO && state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL; + goto err; + } + + r = device_check_size(cd, device, hdr_size, 0); + if (r) + goto err; + + /* + * Try to rewrite (recover) bad header. Always regenerate salt for bad header. + */ + if (state_hdr1 == HDR_OK && state_hdr2 != HDR_OK) { + log_dbg(cd, "Secondary LUKS2 header requires recovery."); + + if (do_blkprobe && (r = detect_device_signatures(cd, device_path(device)))) { + log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n" + "Please run \"cryptsetup repair\" for recovery.")); + goto err; + } + + if (do_recovery) { + memcpy(&hdr_disk2, &hdr_disk1, LUKS2_HDR_BIN_LEN); + r = crypt_random_get(cd, (char*)hdr_disk2.salt, sizeof(hdr_disk2.salt), CRYPT_RND_SALT); + if (r) + log_dbg(cd, "Cannot generate master salt."); + else { + hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0); + r = hdr_write_disk(cd, device, hdr, json_area1, 1); + } + if (r) + log_dbg(cd, "Secondary LUKS2 header recovery failed."); + } + } else if (state_hdr1 != HDR_OK && state_hdr2 == HDR_OK) { + log_dbg(cd, "Primary LUKS2 header requires recovery."); + + if (do_blkprobe && (r = detect_device_signatures(cd, device_path(device)))) { + log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n" + "Please run \"cryptsetup repair\" for recovery.")); + goto err; + } + + if (do_recovery) { + memcpy(&hdr_disk1, &hdr_disk2, LUKS2_HDR_BIN_LEN); + r = crypt_random_get(cd, (char*)hdr_disk1.salt, sizeof(hdr_disk1.salt), CRYPT_RND_SALT); + if (r) + log_dbg(cd, "Cannot generate master salt."); + else { + hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1); + r = hdr_write_disk(cd, device, hdr, json_area2, 0); + } + if (r) + log_dbg(cd, "Primary LUKS2 header recovery failed."); + } + } + + free(json_area1); + json_area1 = NULL; + free(json_area2); + json_area2 = NULL; + + /* wrong lock for write mode during recovery attempt */ + if (r == -EAGAIN) + goto err; + + /* + * Even if status is failed, the second header includes salt. + */ + if (state_hdr1 == HDR_OK) { + hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0); + hdr->jobj = jobj_hdr1; + json_object_put(jobj_hdr2); + } else if (state_hdr2 == HDR_OK) { + hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1); + hdr->jobj = jobj_hdr2; + json_object_put(jobj_hdr1); + } + + /* + * FIXME: should this fail? At least one header was read correctly. + * r = (state_hdr1 == HDR_FAIL_IO || state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL; + */ + return 0; +err: + log_dbg(cd, "LUKS2 header read failed (%d).", r); + + free(json_area1); + free(json_area2); + json_object_put(jobj_hdr1); + json_object_put(jobj_hdr2); + hdr->jobj = NULL; + return r; +} + +int LUKS2_hdr_version_unlocked(struct crypt_device *cd, const char *backup_file) +{ + struct { + char magic[LUKS2_MAGIC_L]; + uint16_t version; + } __attribute__ ((packed)) hdr; + struct device *device = NULL; + int r = 0, devfd = -1, flags; + + if (!backup_file) + device = crypt_metadata_device(cd); + else if (device_alloc(cd, &device, backup_file) < 0) + return 0; + + if (!device) + return 0; + + flags = O_RDONLY; + if (device_direct_io(device)) + flags |= O_DIRECT; + + devfd = open(device_path(device), flags); + if (devfd < 0) + goto err; + + if ((read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &hdr, sizeof(hdr), 0) == sizeof(hdr)) && + !memcmp(hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L)) + r = (int)be16_to_cpu(hdr.version); +err: + if (devfd != -1) + close(devfd); + + if (backup_file) + device_free(cd, device); + + return r; +} diff --git a/lib/luks2/luks2_internal.h b/lib/luks2/luks2_internal.h new file mode 100644 index 0000000..a5bcb1f --- /dev/null +++ b/lib/luks2/luks2_internal.h @@ -0,0 +1,203 @@ +/* + * LUKS - Linux Unified Key Setup v2 + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_LUKS2_INTERNAL_H +#define _CRYPTSETUP_LUKS2_INTERNAL_H + +#include +#include +#include + +#include "internal.h" +#include "base64.h" +#include "luks2.h" + +#define UNUSED(x) (void)(x) + +/* override useless forward slash escape when supported by json-c */ +#ifndef JSON_C_TO_STRING_NOSLASHESCAPE +#define JSON_C_TO_STRING_NOSLASHESCAPE 0 +#endif + +/* + * On-disk access function prototypes + */ +int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, + struct device *device, int do_recovery, int do_blkprobe); +int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, + struct device *device, bool seqid_check); + +/* + * JSON struct access helpers + */ +json_object *LUKS2_get_keyslot_jobj(struct luks2_hdr *hdr, int keyslot); +json_object *LUKS2_get_token_jobj(struct luks2_hdr *hdr, int token); +json_object *LUKS2_get_digest_jobj(struct luks2_hdr *hdr, int digest); +json_object *LUKS2_get_segment_jobj(struct luks2_hdr *hdr, int segment); +json_object *LUKS2_get_tokens_jobj(struct luks2_hdr *hdr); +json_object *LUKS2_get_segments_jobj(struct luks2_hdr *hdr); + +void hexprint_base64(struct crypt_device *cd, json_object *jobj, + const char *sep, const char *line_sep); + +uint64_t crypt_jobj_get_uint64(json_object *jobj); +uint32_t crypt_jobj_get_uint32(json_object *jobj); +json_object *crypt_jobj_new_uint64(uint64_t value); + +int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val); +void json_object_object_del_by_uint(json_object *jobj, unsigned key); +int json_object_copy(json_object *jobj_src, json_object **jobj_dst); + +void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc); + +/* + * LUKS2 JSON validation + */ + +/* validation helper */ +json_bool validate_json_uint32(json_object *jobj); +json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name, + const char *section, const char *key, json_type type); + +int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size); +int LUKS2_check_json_size(struct crypt_device *cd, const struct luks2_hdr *hdr); +int LUKS2_token_validate(struct crypt_device *cd, json_object *hdr_jobj, + json_object *jobj_token, const char *key); +void LUKS2_token_dump(struct crypt_device *cd, int token); + +/* + * LUKS2 JSON repair for known glitches + */ +void LUKS2_hdr_repair(struct crypt_device *cd, json_object *jobj_hdr); +void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_hdr); + +/* + * JSON array helpers + */ +struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num); +struct json_object *LUKS2_array_remove(struct json_object *array, const char *num); + +/* + * Plugins API + */ + +/** + * LUKS2 keyslots handlers (EXPERIMENTAL) + */ +typedef int (*keyslot_alloc_func)(struct crypt_device *cd, int keyslot, + size_t volume_key_len, + const struct luks2_keyslot_params *params); +typedef int (*keyslot_update_func)(struct crypt_device *cd, int keyslot, + const struct luks2_keyslot_params *params); +typedef int (*keyslot_open_func) (struct crypt_device *cd, int keyslot, + const char *password, size_t password_len, + char *volume_key, size_t volume_key_len); +typedef int (*keyslot_store_func)(struct crypt_device *cd, int keyslot, + const char *password, size_t password_len, + const char *volume_key, size_t volume_key_len); +typedef int (*keyslot_wipe_func) (struct crypt_device *cd, int keyslot); +typedef int (*keyslot_dump_func) (struct crypt_device *cd, int keyslot); +typedef int (*keyslot_validate_func) (struct crypt_device *cd, json_object *jobj_keyslot); +typedef void(*keyslot_repair_func) (struct crypt_device *cd, json_object *jobj_keyslot); + +/* see LUKS2_luks2_to_luks1 */ +int placeholder_keyslot_alloc(struct crypt_device *cd, + int keyslot, + uint64_t area_offset, + uint64_t area_length, + size_t volume_key_len); + +/* validate all keyslot implementations in hdr json */ +int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj); + +typedef struct { + const char *name; + keyslot_alloc_func alloc; + keyslot_update_func update; + keyslot_open_func open; + keyslot_store_func store; + keyslot_wipe_func wipe; + keyslot_dump_func dump; + keyslot_validate_func validate; + keyslot_repair_func repair; +} keyslot_handler; + +/* can not fit prototype alloc function */ +int reenc_keyslot_alloc(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const struct crypt_params_reencrypt *params); + +/** + * LUKS2 digest handlers (EXPERIMENTAL) + */ +typedef int (*digest_verify_func)(struct crypt_device *cd, int digest, + const char *volume_key, size_t volume_key_len); +typedef int (*digest_store_func) (struct crypt_device *cd, int digest, + const char *volume_key, size_t volume_key_len); +typedef int (*digest_dump_func) (struct crypt_device *cd, int digest); + +typedef struct { + const char *name; + digest_verify_func verify; + digest_store_func store; + digest_dump_func dump; +} digest_handler; + +/** + * LUKS2 token handlers (internal use only) + */ +typedef int (*builtin_token_get_func) (json_object *jobj_token, void *params); +typedef int (*builtin_token_set_func) (json_object **jobj_token, const void *params); + +typedef struct { + /* internal only section used by builtin tokens */ + builtin_token_get_func get; + builtin_token_set_func set; + /* public token handler */ + const crypt_token_handler *h; +} token_handler; + +int token_keyring_set(json_object **, const void *); +int token_keyring_get(json_object *, void *); + +int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr, + size_t keylength, uint64_t *area_offset, uint64_t *area_length); +int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr, + uint64_t *area_offset, uint64_t *area_length); + +int LUKS2_check_cipher(struct crypt_device *cd, + size_t keylength, + const char *cipher, + const char *cipher_mode); + +static inline const char *crypt_reencrypt_mode_to_str(crypt_reencrypt_mode_info mi) +{ + if (mi == CRYPT_REENCRYPT_REENCRYPT) + return "reencrypt"; + if (mi == CRYPT_REENCRYPT_ENCRYPT) + return "encrypt"; + if (mi == CRYPT_REENCRYPT_DECRYPT) + return "decrypt"; + return ""; +} + +#endif diff --git a/lib/luks2/luks2_json_format.c b/lib/luks2/luks2_json_format.c new file mode 100644 index 0000000..1416766 --- /dev/null +++ b/lib/luks2/luks2_json_format.c @@ -0,0 +1,405 @@ +/* + * LUKS - Linux Unified Key Setup v2, LUKS2 header format code + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" +#include +#include + +struct area { + uint64_t offset; + uint64_t length; +}; + +static size_t get_area_size(size_t keylength) +{ + //FIXME: calculate this properly, for now it is AF_split_sectors + return size_round_up(keylength * 4000, 4096); +} + +static size_t get_min_offset(struct luks2_hdr *hdr) +{ + return 2 * hdr->hdr_size; +} + +static size_t get_max_offset(struct luks2_hdr *hdr) +{ + return LUKS2_hdr_and_areas_size(hdr->jobj); +} + +int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr, + uint64_t *area_offset, uint64_t *area_length) +{ + struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX+1] = {}; + int i, j, k, area_i; + size_t valid_offset, offset, length; + + /* fill area offset + length table */ + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length)) + continue; + areas[i].length = 0; + areas[i].offset = 0; + } + + /* sort table */ + k = 0; /* index in sorted table */ + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + offset = get_max_offset(hdr) ?: UINT64_MAX; + area_i = -1; + /* search for the smallest offset in table */ + for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++) + if (areas[j].offset && areas[j].offset <= offset) { + area_i = j; + offset = areas[j].offset; + } + + if (area_i >= 0) { + sorted_areas[k].length = areas[area_i].length; + sorted_areas[k].offset = areas[area_i].offset; + areas[area_i].length = 0; + areas[area_i].offset = 0; + k++; + } + } + + sorted_areas[LUKS2_KEYSLOTS_MAX].offset = get_max_offset(hdr); + sorted_areas[LUKS2_KEYSLOTS_MAX].length = 1; + + /* search for the gap we can use */ + length = valid_offset = 0; + offset = get_min_offset(hdr); + for (i = 0; i < LUKS2_KEYSLOTS_MAX+1; i++) { + /* skip empty */ + if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0) + continue; + + /* found bigger gap than the last one */ + if ((offset < sorted_areas[i].offset) && (sorted_areas[i].offset - offset) > length) { + length = sorted_areas[i].offset - offset; + valid_offset = offset; + } + + /* move beyond allocated area */ + offset = sorted_areas[i].offset + sorted_areas[i].length; + } + + /* this search 'algorithm' does not work with unaligned areas */ + assert(length == size_round_up(length, 4096)); + assert(valid_offset == size_round_up(valid_offset, 4096)); + + if (!length) { + log_dbg(cd, "Not enough space in header keyslot area."); + return -EINVAL; + } + + log_dbg(cd, "Found largest free area %zu -> %zu", valid_offset, length + valid_offset); + + *area_offset = valid_offset; + *area_length = length; + + return 0; +} + +int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr, + size_t keylength, uint64_t *area_offset, uint64_t *area_length) +{ + struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX] = {}; + int i, j, k, area_i; + size_t offset, length; + + /* fill area offset + length table */ + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length)) + continue; + areas[i].length = 0; + areas[i].offset = 0; + } + + /* sort table */ + k = 0; /* index in sorted table */ + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + offset = get_max_offset(hdr) ?: UINT64_MAX; + area_i = -1; + /* search for the smallest offset in table */ + for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++) + if (areas[j].offset && areas[j].offset <= offset) { + area_i = j; + offset = areas[j].offset; + } + + if (area_i >= 0) { + sorted_areas[k].length = areas[area_i].length; + sorted_areas[k].offset = areas[area_i].offset; + areas[area_i].length = 0; + areas[area_i].offset = 0; + k++; + } + } + + /* search for the gap we can use */ + offset = get_min_offset(hdr); + length = get_area_size(keylength); + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + /* skip empty */ + if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0) + continue; + + /* enough space before the used area */ + if ((offset < sorted_areas[i].offset) && ((offset + length) <= sorted_areas[i].offset)) + break; + + /* both offset and length are already aligned to 4096 bytes */ + offset = sorted_areas[i].offset + sorted_areas[i].length; + } + + if ((offset + length) > get_max_offset(hdr)) { + log_dbg(cd, "Not enough space in header keyslot area."); + return -EINVAL; + } + + log_dbg(cd, "Found area %zu -> %zu", offset, length + offset); + + *area_offset = offset; + *area_length = length; + return 0; +} + +int LUKS2_check_metadata_area_size(uint64_t metadata_size) +{ + /* see LUKS2_HDR2_OFFSETS */ + return (metadata_size != 0x004000 && + metadata_size != 0x008000 && metadata_size != 0x010000 && + metadata_size != 0x020000 && metadata_size != 0x040000 && + metadata_size != 0x080000 && metadata_size != 0x100000 && + metadata_size != 0x200000 && metadata_size != 0x400000); +} + +int LUKS2_check_keyslots_area_size(uint64_t keyslots_size) +{ + return (MISALIGNED_4K(keyslots_size) || + keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE); +} + +int LUKS2_generate_hdr( + struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct volume_key *vk, + const char *cipherName, + const char *cipherMode, + const char *integrity, + const char *uuid, + unsigned int sector_size, /* in bytes */ + uint64_t data_offset, /* in bytes */ + uint64_t align_offset, /* in bytes */ + uint64_t required_alignment, + uint64_t metadata_size, + uint64_t keyslots_size) +{ + struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config; + char cipher[128]; + uuid_t partitionUuid; + int digest; + uint64_t mdev_size; + + if (!metadata_size) + metadata_size = LUKS2_HDR_16K_LEN; + hdr->hdr_size = metadata_size; + + if (data_offset && data_offset < get_min_offset(hdr)) { + log_err(cd, _("Requested data offset is too small.")); + return -EINVAL; + } + + /* Increase keyslot size according to data offset */ + if (!keyslots_size && data_offset) + keyslots_size = data_offset - get_min_offset(hdr); + + /* keyslots size has to be 4 KiB aligned */ + keyslots_size -= (keyslots_size % 4096); + + if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE) + keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE; + + if (!keyslots_size) { + assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX); + keyslots_size = LUKS2_DEFAULT_HDR_SIZE - get_min_offset(hdr); + /* Decrease keyslots_size due to metadata device being too small */ + if (!device_size(crypt_metadata_device(cd), &mdev_size) && + ((keyslots_size + get_min_offset(hdr)) > mdev_size) && + device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr))) + keyslots_size = mdev_size - get_min_offset(hdr); + } + + /* Decrease keyslots_size if we have smaller data_offset */ + if (data_offset && (keyslots_size + get_min_offset(hdr)) > data_offset) { + keyslots_size = data_offset - get_min_offset(hdr); + log_dbg(cd, "Decreasing keyslot area size to %" PRIu64 + " bytes due to the requested data offset %" + PRIu64 " bytes.", keyslots_size, data_offset); + } + + /* Data offset has priority */ + if (!data_offset && required_alignment) { + data_offset = size_round_up(get_min_offset(hdr) + keyslots_size, + (size_t)required_alignment); + data_offset += align_offset; + } + + log_dbg(cd, "Formatting LUKS2 with JSON metadata area %" PRIu64 + " bytes and keyslots area %" PRIu64 " bytes.", + metadata_size - LUKS2_HDR_BIN_LEN, keyslots_size); + + if (keyslots_size < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN)) + log_std(cd, _("WARNING: keyslots area (%" PRIu64 " bytes) is very small," + " available LUKS2 keyslot count is very limited.\n"), + keyslots_size); + + hdr->seqid = 1; + hdr->version = 2; + memset(hdr->label, 0, LUKS2_LABEL_L); + strcpy(hdr->checksum_alg, "sha256"); + crypt_random_get(cd, (char*)hdr->salt1, LUKS2_SALT_L, CRYPT_RND_SALT); + crypt_random_get(cd, (char*)hdr->salt2, LUKS2_SALT_L, CRYPT_RND_SALT); + + if (uuid && uuid_parse(uuid, partitionUuid) == -1) { + log_err(cd, _("Wrong LUKS UUID format provided.")); + return -EINVAL; + } + if (!uuid) + uuid_generate(partitionUuid); + + uuid_unparse(partitionUuid, hdr->uuid); + + if (*cipherMode != '\0') + snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode); + else + snprintf(cipher, sizeof(cipher), "%s", cipherName); + + hdr->jobj = json_object_new_object(); + + jobj_keyslots = json_object_new_object(); + json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots); + json_object_object_add(hdr->jobj, "tokens", json_object_new_object()); + jobj_segments = json_object_new_object(); + json_object_object_add(hdr->jobj, "segments", jobj_segments); + json_object_object_add(hdr->jobj, "digests", json_object_new_object()); + jobj_config = json_object_new_object(); + json_object_object_add(hdr->jobj, "config", jobj_config); + + digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk); + if (digest < 0) + goto err; + + if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0) + goto err; + + jobj_segment = json_segment_create_crypt(data_offset, 0, NULL, cipher, sector_size, 0); + if (!jobj_segment) + goto err; + + if (integrity) { + jobj_integrity = json_object_new_object(); + json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity)); + json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none")); + json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none")); + json_object_object_add(jobj_segment, "integrity", jobj_integrity); + } + + json_object_object_add_by_uint(jobj_segments, 0, jobj_segment); + + json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN)); + json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size)); + + JSON_DBG(cd, hdr->jobj, "Header JSON:"); + return 0; +err: + json_object_put(hdr->jobj); + hdr->jobj = NULL; + return -EINVAL; +} + +int LUKS2_wipe_header_areas(struct crypt_device *cd, + struct luks2_hdr *hdr) +{ + int r; + uint64_t offset, length; + size_t wipe_block; + + /* Wipe complete header, keyslots and padding areas with zeroes. */ + offset = 0; + length = LUKS2_get_data_offset(hdr) * SECTOR_SIZE; + wipe_block = 1024 * 1024; + + if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN)) + return -EINVAL; + + /* On detached header wipe at least the first 4k */ + if (length == 0) { + length = 4096; + wipe_block = 4096; + } + + log_dbg(cd, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.", + offset, length + offset); + + r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, + offset, length, wipe_block, NULL, NULL); + if (r < 0) + return r; + + /* Wipe keyslot area */ + wipe_block = 1024 * 1024; + offset = get_min_offset(hdr); + length = LUKS2_keyslots_size(hdr->jobj); + + log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.", + offset, length + offset); + + return crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_RANDOM, + offset, length, wipe_block, NULL, NULL); +} + +/* FIXME: what if user wanted to keep original keyslots size? */ +int LUKS2_set_keyslots_size(struct crypt_device *cd, + struct luks2_hdr *hdr, + uint64_t data_offset) +{ + json_object *jobj_config; + uint64_t keyslots_size; + + if (data_offset < get_min_offset(hdr)) + return 1; + + keyslots_size = data_offset - get_min_offset(hdr); + + /* keep keyslots_size reasonable for custom data alignments */ + if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE) + keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE; + + /* keyslots size has to be 4 KiB aligned */ + keyslots_size -= (keyslots_size % 4096); + + if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) + return 1; + + json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size)); + return 0; +} diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c new file mode 100644 index 0000000..e346067 --- /dev/null +++ b/lib/luks2/luks2_json_metadata.c @@ -0,0 +1,2414 @@ +/* + * LUKS - Linux Unified Key Setup v2 + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * Copyright (C) 2015-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" +#include "../integrity/integrity.h" +#include +#include +#include + +#define LUKS_STRIPES 4000 + +struct interval { + uint64_t offset; + uint64_t length; +}; + +void hexprint_base64(struct crypt_device *cd, json_object *jobj, + const char *sep, const char *line_sep) +{ + char *buf = NULL; + size_t buf_len; + unsigned int i; + + if (!base64_decode_alloc(json_object_get_string(jobj), + json_object_get_string_len(jobj), + &buf, &buf_len)) + return; + + for (i = 0; i < buf_len; i++) { + if (i && !(i % 16)) + log_std(cd, "\n\t%s", line_sep); + log_std(cd, "%02hhx%s", buf[i], sep); + } + log_std(cd, "\n"); + free(buf); +} + +void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc) +{ + if (desc) + crypt_log(cd, CRYPT_LOG_DEBUG_JSON, desc); + crypt_log(cd, CRYPT_LOG_DEBUG_JSON, json_object_to_json_string_ext(jobj, + JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE)); +} + +/* + * JSON array helpers + */ +struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num) +{ + struct json_object *jobj1; + int i; + + for (i = 0; i < (int) json_object_array_length(array); i++) { + jobj1 = json_object_array_get_idx(array, i); + if (!strcmp(num, json_object_get_string(jobj1))) + return jobj1; + } + + return NULL; +} + +struct json_object *LUKS2_array_remove(struct json_object *array, const char *num) +{ + struct json_object *jobj1, *jobj_removing = NULL, *array_new; + int i; + + jobj_removing = LUKS2_array_jobj(array, num); + if (!jobj_removing) + return NULL; + + /* Create new array without jobj_removing. */ + array_new = json_object_new_array(); + for (i = 0; i < (int) json_object_array_length(array); i++) { + jobj1 = json_object_array_get_idx(array, i); + if (jobj1 != jobj_removing) + json_object_array_add(array_new, json_object_get(jobj1)); + } + + return array_new; +} + +/* + * JSON struct access helpers + */ +json_object *LUKS2_get_keyslot_jobj(struct luks2_hdr *hdr, int keyslot) +{ + json_object *jobj1, *jobj2; + char keyslot_name[16]; + + if (!hdr || keyslot < 0) + return NULL; + + if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1) + return NULL; + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj1)) + return NULL; + + if (!json_object_object_get_ex(jobj1, keyslot_name, &jobj2)) + return NULL; + + return jobj2; +} + +json_object *LUKS2_get_tokens_jobj(struct luks2_hdr *hdr) +{ + json_object *jobj_tokens; + + if (!hdr || !json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens)) + return NULL; + + return jobj_tokens; +} + +json_object *LUKS2_get_token_jobj(struct luks2_hdr *hdr, int token) +{ + json_object *jobj1, *jobj2; + char token_name[16]; + + if (!hdr || token < 0) + return NULL; + + jobj1 = LUKS2_get_tokens_jobj(hdr); + if (!jobj1) + return NULL; + + if (snprintf(token_name, sizeof(token_name), "%u", token) < 1) + return NULL; + + json_object_object_get_ex(jobj1, token_name, &jobj2); + return jobj2; +} + +json_object *LUKS2_get_digest_jobj(struct luks2_hdr *hdr, int digest) +{ + json_object *jobj1, *jobj2; + char digest_name[16]; + + if (!hdr || digest < 0) + return NULL; + + if (snprintf(digest_name, sizeof(digest_name), "%u", digest) < 1) + return NULL; + + if (!json_object_object_get_ex(hdr->jobj, "digests", &jobj1)) + return NULL; + + json_object_object_get_ex(jobj1, digest_name, &jobj2); + return jobj2; +} + +static json_object *json_get_segments_jobj(json_object *hdr_jobj) +{ + json_object *jobj_segments; + + if (!hdr_jobj || !json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) + return NULL; + + return jobj_segments; +} + +json_object *LUKS2_get_segment_jobj(struct luks2_hdr *hdr, int segment) +{ + if (!hdr) + return NULL; + + if (segment == CRYPT_DEFAULT_SEGMENT) + segment = LUKS2_get_default_segment(hdr); + + return json_segments_get_segment(json_get_segments_jobj(hdr->jobj), segment); +} + +json_object *LUKS2_get_segments_jobj(struct luks2_hdr *hdr) +{ + return hdr ? json_get_segments_jobj(hdr->jobj) : NULL; +} + +int LUKS2_segments_count(struct luks2_hdr *hdr) +{ + if (!hdr) + return -EINVAL; + + return json_segments_count(LUKS2_get_segments_jobj(hdr)); +} + +int LUKS2_get_default_segment(struct luks2_hdr *hdr) +{ + int s = LUKS2_get_segment_id_by_flag(hdr, "backup-final"); + if (s >= 0) + return s; + + if (LUKS2_segments_count(hdr) == 1) + return 0; + + return -EINVAL; +} + +/* + * json_type_int needs to be validated first. + * See validate_json_uint32() + */ +uint32_t crypt_jobj_get_uint32(json_object *jobj) +{ + return json_object_get_int64(jobj); +} + +/* jobj has to be json_type_string and numbered */ +static json_bool json_str_to_uint64(json_object *jobj, uint64_t *value) +{ + char *endptr; + unsigned long long tmp; + + errno = 0; + tmp = strtoull(json_object_get_string(jobj), &endptr, 10); + if (*endptr || errno) { + *value = 0; + return 0; + } + + *value = tmp; + return 1; +} + +uint64_t crypt_jobj_get_uint64(json_object *jobj) +{ + uint64_t r; + json_str_to_uint64(jobj, &r); + return r; +} + +json_object *crypt_jobj_new_uint64(uint64_t value) +{ + /* 18446744073709551615 */ + char num[21]; + int r; + json_object *jobj; + + r = snprintf(num, sizeof(num), "%" PRIu64, value); + if (r < 0 || (size_t)r >= sizeof(num)) + return NULL; + + jobj = json_object_new_string(num); + return jobj; +} + +/* + * Validate helpers + */ +static json_bool numbered(struct crypt_device *cd, const char *name, const char *key) +{ + int i; + + for (i = 0; key[i]; i++) + if (!isdigit(key[i])) { + log_dbg(cd, "%s \"%s\" is not in numbered form.", name, key); + return 0; + } + return 1; +} + +json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name, + const char *section, const char *key, json_type type) +{ + json_object *sobj; + + if (!json_object_object_get_ex(jobj, key, &sobj) || + !json_object_is_type(sobj, type)) { + log_dbg(cd, "%s \"%s\" is missing \"%s\" (%s) specification.", + section, name, key, json_type_to_name(type)); + return NULL; + } + + return sobj; +} + +json_bool validate_json_uint32(json_object *jobj) +{ + int64_t tmp; + + errno = 0; + tmp = json_object_get_int64(jobj); + + return (errno || tmp < 0 || tmp > UINT32_MAX) ? 0 : 1; +} + +static json_bool validate_keyslots_array(struct crypt_device *cd, + json_object *jarr, json_object *jobj_keys) +{ + json_object *jobj; + int i = 0, length = (int) json_object_array_length(jarr); + + while (i < length) { + jobj = json_object_array_get_idx(jarr, i); + if (!json_object_is_type(jobj, json_type_string)) { + log_dbg(cd, "Illegal value type in keyslots array at index %d.", i); + return 0; + } + + if (!json_contains(cd, jobj_keys, "", "Keyslots section", + json_object_get_string(jobj), json_type_object)) + return 0; + + i++; + } + + return 1; +} + +static json_bool validate_segments_array(struct crypt_device *cd, + json_object *jarr, json_object *jobj_segments) +{ + json_object *jobj; + int i = 0, length = (int) json_object_array_length(jarr); + + while (i < length) { + jobj = json_object_array_get_idx(jarr, i); + if (!json_object_is_type(jobj, json_type_string)) { + log_dbg(cd, "Illegal value type in segments array at index %d.", i); + return 0; + } + + if (!json_contains(cd, jobj_segments, "", "Segments section", + json_object_get_string(jobj), json_type_object)) + return 0; + + i++; + } + + return 1; +} + +static json_bool segment_has_digest(const char *segment_name, json_object *jobj_digests) +{ + json_object *jobj_segments; + + json_object_object_foreach(jobj_digests, key, val) { + UNUSED(key); + json_object_object_get_ex(val, "segments", &jobj_segments); + if (LUKS2_array_jobj(jobj_segments, segment_name)) + return 1; + } + + return 0; +} + +static json_bool validate_intervals(struct crypt_device *cd, + int length, const struct interval *ix, + uint64_t metadata_size, uint64_t keyslots_area_end) +{ + int j, i = 0; + + while (i < length) { + if (ix[i].offset < 2 * metadata_size) { + log_dbg(cd, "Illegal area offset: %" PRIu64 ".", ix[i].offset); + return 0; + } + + if (!ix[i].length) { + log_dbg(cd, "Area length must be greater than zero."); + return 0; + } + + if ((ix[i].offset + ix[i].length) > keyslots_area_end) { + log_dbg(cd, "Area [%" PRIu64 ", %" PRIu64 "] overflows binary keyslots area (ends at offset: %" PRIu64 ").", + ix[i].offset, ix[i].offset + ix[i].length, keyslots_area_end); + return 0; + } + + for (j = 0; j < length; j++) { + if (i == j) + continue; + if ((ix[i].offset >= ix[j].offset) && (ix[i].offset < (ix[j].offset + ix[j].length))) { + log_dbg(cd, "Overlapping areas [%" PRIu64 ",%" PRIu64 "] and [%" PRIu64 ",%" PRIu64 "].", + ix[i].offset, ix[i].offset + ix[i].length, + ix[j].offset, ix[j].offset + ix[j].length); + return 0; + } + } + + i++; + } + + return 1; +} + +static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj, json_object *hdr_keyslot, const char *key) +{ + json_object *jobj_key_size; + + if (!json_contains(cd, hdr_keyslot, key, "Keyslot", "type", json_type_string)) + return 1; + if (!(jobj_key_size = json_contains(cd, hdr_keyslot, key, "Keyslot", "key_size", json_type_int))) + return 1; + + /* enforce uint32_t type */ + if (!validate_json_uint32(jobj_key_size)) { + log_dbg(cd, "Illegal field \"key_size\":%s.", + json_object_get_string(jobj_key_size)); + return 1; + } + + return 0; +} + +int LUKS2_token_validate(struct crypt_device *cd, + json_object *hdr_jobj, json_object *jobj_token, const char *key) +{ + json_object *jarr, *jobj_keyslots; + + /* keyslots are not yet validated, but we need to know token doesn't reference missing keyslot */ + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) + return 1; + + if (!json_contains(cd, jobj_token, key, "Token", "type", json_type_string)) + return 1; + + jarr = json_contains(cd, jobj_token, key, "Token", "keyslots", json_type_array); + if (!jarr) + return 1; + + if (!validate_keyslots_array(cd, jarr, jobj_keyslots)) + return 1; + + return 0; +} + +static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj, uint64_t hdr_json_size) +{ + json_object *jobj, *jobj1; + const char *json; + uint64_t json_area_size, json_size; + + json_object_object_get_ex(hdr_jobj, "config", &jobj); + json_object_object_get_ex(jobj, "json_size", &jobj1); + + json = json_object_to_json_string_ext(hdr_jobj, + JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE); + json_area_size = crypt_jobj_get_uint64(jobj1); + json_size = (uint64_t)strlen(json); + + if (hdr_json_size != json_area_size) { + log_dbg(cd, "JSON area size does not match value in binary header."); + return 1; + } + + if (json_size > json_area_size) { + log_dbg(cd, "JSON does not fit in the designated area."); + return 1; + } + + return 0; +} + +int LUKS2_check_json_size(struct crypt_device *cd, const struct luks2_hdr *hdr) +{ + return hdr_validate_json_size(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN); +} + +static int hdr_validate_keyslots(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jobj; + + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj)) { + log_dbg(cd, "Missing keyslots section."); + return 1; + } + + json_object_object_foreach(jobj, key, val) { + if (!numbered(cd, "Keyslot", key)) + return 1; + if (LUKS2_keyslot_validate(cd, hdr_jobj, val, key)) + return 1; + } + + return 0; +} + +static int hdr_validate_tokens(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jobj; + + if (!json_object_object_get_ex(hdr_jobj, "tokens", &jobj)) { + log_dbg(cd, "Missing tokens section."); + return 1; + } + + json_object_object_foreach(jobj, key, val) { + if (!numbered(cd, "Token", key)) + return 1; + if (LUKS2_token_validate(cd, hdr_jobj, val, key)) + return 1; + } + + return 0; +} + +static int hdr_validate_crypt_segment(struct crypt_device *cd, + json_object *jobj, const char *key, json_object *jobj_digests, + uint64_t offset, uint64_t size) +{ + json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity; + uint32_t sector_size; + uint64_t ivoffset; + + if (!(jobj_ivoffset = json_contains(cd, jobj, key, "Segment", "iv_tweak", json_type_string)) || + !json_contains(cd, jobj, key, "Segment", "encryption", json_type_string) || + !(jobj_sector_size = json_contains(cd, jobj, key, "Segment", "sector_size", json_type_int))) + return 1; + + /* integrity */ + if (json_object_object_get_ex(jobj, "integrity", &jobj_integrity)) { + if (!json_contains(cd, jobj, key, "Segment", "integrity", json_type_object) || + !json_contains(cd, jobj_integrity, key, "Segment integrity", "type", json_type_string) || + !json_contains(cd, jobj_integrity, key, "Segment integrity", "journal_encryption", json_type_string) || + !json_contains(cd, jobj_integrity, key, "Segment integrity", "journal_integrity", json_type_string)) + return 1; + } + + /* enforce uint32_t type */ + if (!validate_json_uint32(jobj_sector_size)) { + log_dbg(cd, "Illegal field \"sector_size\":%s.", + json_object_get_string(jobj_sector_size)); + return 1; + } + + sector_size = crypt_jobj_get_uint32(jobj_sector_size); + if (!sector_size || MISALIGNED_512(sector_size)) { + log_dbg(cd, "Illegal sector size: %" PRIu32, sector_size); + return 1; + } + + if (!numbered(cd, "iv_tweak", json_object_get_string(jobj_ivoffset)) || + !json_str_to_uint64(jobj_ivoffset, &ivoffset)) { + log_dbg(cd, "Illegal iv_tweak value."); + return 1; + } + + if (size % sector_size) { + log_dbg(cd, "Size field has to be aligned to sector size: %" PRIu32, sector_size); + return 1; + } + + return !segment_has_digest(key, jobj_digests); +} + +static bool validate_segment_intervals(struct crypt_device *cd, + int length, const struct interval *ix) +{ + int j, i = 0; + + while (i < length) { + if (ix[i].length == UINT64_MAX && (i != (length - 1))) { + log_dbg(cd, "Only last regular segment is allowed to have 'dynamic' size."); + return false; + } + + for (j = 0; j < length; j++) { + if (i == j) + continue; + if ((ix[i].offset >= ix[j].offset) && (ix[j].length == UINT64_MAX || (ix[i].offset < (ix[j].offset + ix[j].length)))) { + log_dbg(cd, "Overlapping segments [%" PRIu64 ",%" PRIu64 "]%s and [%" PRIu64 ",%" PRIu64 "]%s.", + ix[i].offset, ix[i].offset + ix[i].length, ix[i].length == UINT64_MAX ? "(dynamic)" : "", + ix[j].offset, ix[j].offset + ix[j].length, ix[j].length == UINT64_MAX ? "(dynamic)" : ""); + return false; + } + } + + i++; + } + + return true; +} + +static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj; + struct interval *intervals; + uint64_t offset, size; + int i, r, count, first_backup = -1; + + if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) { + log_dbg(cd, "Missing segments section."); + return 1; + } + + count = json_object_object_length(jobj_segments); + if (count < 1) { + log_dbg(cd, "Empty segments section."); + return 1; + } + + /* digests should already be validated */ + if (!json_object_object_get_ex(hdr_jobj, "digests", &jobj_digests)) + return 1; + + json_object_object_foreach(jobj_segments, key, val) { + if (!numbered(cd, "Segment", key)) + return 1; + + /* those fields are mandatory for all segment types */ + if (!(jobj_type = json_contains(cd, val, key, "Segment", "type", json_type_string)) || + !(jobj_offset = json_contains(cd, val, key, "Segment", "offset", json_type_string)) || + !(jobj_size = json_contains(cd, val, key, "Segment", "size", json_type_string))) + return 1; + + if (!numbered(cd, "offset", json_object_get_string(jobj_offset)) || + !json_str_to_uint64(jobj_offset, &offset)) + return 1; + + /* size "dynamic" means whole device starting at 'offset' */ + if (strcmp(json_object_get_string(jobj_size), "dynamic")) { + if (!numbered(cd, "size", json_object_get_string(jobj_size)) || + !json_str_to_uint64(jobj_size, &size) || !size) + return 1; + } else + size = 0; + + /* all device-mapper devices are aligned to 512 sector size */ + if (MISALIGNED_512(offset)) { + log_dbg(cd, "Offset field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE); + return 1; + } + if (MISALIGNED_512(size)) { + log_dbg(cd, "Size field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE); + return 1; + } + + /* flags array is optional and must contain strings */ + if (json_object_object_get_ex(val, "flags", NULL)) { + if (!(jobj_flags = json_contains(cd, val, key, "Segment", "flags", json_type_array))) + return 1; + for (i = 0; i < (int) json_object_array_length(jobj_flags); i++) + if (!json_object_is_type(json_object_array_get_idx(jobj_flags, i), json_type_string)) + return 1; + } + + i = atoi(key); + if (json_segment_is_backup(val)) { + if (first_backup < 0 || i < first_backup) + first_backup = i; + } else { + if ((first_backup >= 0) && i >= first_backup) { + log_dbg(cd, "Regular segment at %d is behind backup segment at %d", i, first_backup); + return 1; + } + } + + /* crypt */ + if (!strcmp(json_object_get_string(jobj_type), "crypt") && + hdr_validate_crypt_segment(cd, val, key, jobj_digests, offset, size)) + return 1; + } + + if (first_backup == 0) { + log_dbg(cd, "No regular segment."); + return 1; + } + + if (first_backup < 0) + first_backup = count; + + intervals = malloc(first_backup * sizeof(*intervals)); + if (!intervals) { + log_dbg(cd, "Not enough memory."); + return 1; + } + + for (i = 0; i < first_backup; i++) { + jobj = json_segments_get_segment(jobj_segments, i); + if (!jobj) { + log_dbg(cd, "Gap at key %d in segments object.", i); + free(intervals); + return 1; + } + intervals[i].offset = json_segment_get_offset(jobj, 0); + intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX; + } + + r = !validate_segment_intervals(cd, first_backup, intervals); + free(intervals); + + if (r) + return 1; + + for (; i < count; i++) { + if (!json_segments_get_segment(jobj_segments, i)) { + log_dbg(cd, "Gap at key %d in segments object.", i); + return 1; + } + } + + return 0; +} + +uint64_t LUKS2_metadata_size(json_object *jobj) +{ + json_object *jobj1, *jobj2; + uint64_t json_size; + + json_object_object_get_ex(jobj, "config", &jobj1); + json_object_object_get_ex(jobj1, "json_size", &jobj2); + json_str_to_uint64(jobj2, &json_size); + + return json_size + LUKS2_HDR_BIN_LEN; +} + +static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj) +{ + struct interval *intervals; + json_object *jobj_keyslots, *jobj_offset, *jobj_length, *jobj_segments, *jobj_area; + int length, ret, i = 0; + uint64_t metadata_size; + + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) + return 1; + + /* segments are already validated */ + if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) + return 1; + + /* config is already validated */ + metadata_size = LUKS2_metadata_size(hdr_jobj); + + length = json_object_object_length(jobj_keyslots); + + /* Empty section */ + if (length == 0) + return 0; + + if (length < 0) { + log_dbg(cd, "Invalid keyslot areas specification."); + return 1; + } + + intervals = malloc(length * sizeof(*intervals)); + if (!intervals) { + log_dbg(cd, "Not enough memory."); + return -ENOMEM; + } + + json_object_object_foreach(jobj_keyslots, key, val) { + + if (!(jobj_area = json_contains(cd, val, key, "Keyslot", "area", json_type_object)) || + !json_contains(cd, jobj_area, key, "Keyslot area", "type", json_type_string) || + !(jobj_offset = json_contains(cd, jobj_area, key, "Keyslot", "offset", json_type_string)) || + !(jobj_length = json_contains(cd, jobj_area, key, "Keyslot", "size", json_type_string)) || + !numbered(cd, "offset", json_object_get_string(jobj_offset)) || + !numbered(cd, "size", json_object_get_string(jobj_length))) { + free(intervals); + return 1; + } + + /* rule out values > UINT64_MAX */ + if (!json_str_to_uint64(jobj_offset, &intervals[i].offset) || + !json_str_to_uint64(jobj_length, &intervals[i].length)) { + free(intervals); + return 1; + } + + i++; + } + + if (length != i) { + free(intervals); + return 1; + } + + ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size(hdr_jobj)) ? 0 : 1; + + free(intervals); + + return ret; +} + +static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jarr_keys, *jarr_segs, *jobj, *jobj_keyslots, *jobj_segments; + + if (!json_object_object_get_ex(hdr_jobj, "digests", &jobj)) { + log_dbg(cd, "Missing digests section."); + return 1; + } + + /* keyslots are not yet validated, but we need to know digest doesn't reference missing keyslot */ + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) + return 1; + + /* segments are not yet validated, but we need to know digest doesn't reference missing segment */ + if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) + return 1; + + json_object_object_foreach(jobj, key, val) { + if (!numbered(cd, "Digest", key)) + return 1; + + if (!json_contains(cd, val, key, "Digest", "type", json_type_string) || + !(jarr_keys = json_contains(cd, val, key, "Digest", "keyslots", json_type_array)) || + !(jarr_segs = json_contains(cd, val, key, "Digest", "segments", json_type_array))) + return 1; + + if (!validate_keyslots_array(cd, jarr_keys, jobj_keyslots)) + return 1; + if (!validate_segments_array(cd, jarr_segs, jobj_segments)) + return 1; + } + + return 0; +} + +static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jobj_config, *jobj, *jobj1; + int i; + uint64_t keyslots_size, metadata_size, segment_offset; + + if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) { + log_dbg(cd, "Missing config section."); + return 1; + } + + if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "json_size", json_type_string)) || + !json_str_to_uint64(jobj, &metadata_size)) + return 1; + + /* single metadata instance is assembled from json area size plus + * binary header size */ + metadata_size += LUKS2_HDR_BIN_LEN; + + if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "keyslots_size", json_type_string)) || + !json_str_to_uint64(jobj, &keyslots_size)) + return 1; + + if (LUKS2_check_metadata_area_size(metadata_size)) { + log_dbg(cd, "Unsupported LUKS2 header size (%" PRIu64 ").", metadata_size); + return 1; + } + + if (LUKS2_check_keyslots_area_size(keyslots_size)) { + log_dbg(cd, "Unsupported LUKS2 keyslots size (%" PRIu64 ").", keyslots_size); + return 1; + } + + /* + * validate keyslots_size fits in between (2 * metadata_size) and first + * segment_offset (except detached header) + */ + segment_offset = json_segments_get_minimal_offset(json_get_segments_jobj(hdr_jobj), 0); + if (segment_offset && + (segment_offset < keyslots_size || + (segment_offset - keyslots_size) < (2 * metadata_size))) { + log_dbg(cd, "keyslots_size is too large %" PRIu64 " (bytes). Data offset: %" PRIu64 + ", keyslots offset: %" PRIu64, keyslots_size, segment_offset, 2 * metadata_size); + return 1; + } + + /* Flags array is optional */ + if (json_object_object_get_ex(jobj_config, "flags", &jobj)) { + if (!json_contains(cd, jobj_config, "section", "Config", "flags", json_type_array)) + return 1; + + /* All array members must be strings */ + for (i = 0; i < (int) json_object_array_length(jobj); i++) + if (!json_object_is_type(json_object_array_get_idx(jobj, i), json_type_string)) + return 1; + } + + /* Requirements object is optional */ + if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) { + if (!json_contains(cd, jobj_config, "section", "Config", "requirements", json_type_object)) + return 1; + + /* Mandatory array is optional */ + if (json_object_object_get_ex(jobj, "mandatory", &jobj1)) { + if (!json_contains(cd, jobj, "section", "Requirements", "mandatory", json_type_array)) + return 1; + + /* All array members must be strings */ + for (i = 0; i < (int) json_object_array_length(jobj1); i++) + if (!json_object_is_type(json_object_array_get_idx(jobj1, i), json_type_string)) + return 1; + } + } + + return 0; +} + +int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size) +{ + struct { + int (*validate)(struct crypt_device *, json_object *); + } checks[] = { + { hdr_validate_tokens }, + { hdr_validate_digests }, + { hdr_validate_segments }, + { hdr_validate_keyslots }, + { hdr_validate_config }, + { hdr_validate_areas }, + { NULL } + }; + int i; + + if (!hdr_jobj) + return 1; + + for (i = 0; checks[i].validate; i++) + if (checks[i].validate && checks[i].validate(cd, hdr_jobj)) + return 1; + + if (hdr_validate_json_size(cd, hdr_jobj, json_size)) + return 1; + + /* validate keyslot implementations */ + if (LUKS2_keyslots_validate(cd, hdr_jobj)) + return 1; + + return 0; +} + +/* FIXME: should we expose do_recovery parameter explicitly? */ +int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair) +{ + int r; + + r = device_read_lock(cd, crypt_metadata_device(cd)); + if (r) { + log_err(cd, _("Failed to acquire read lock on device %s."), + device_path(crypt_metadata_device(cd))); + return r; + } + + r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, !repair); + if (r == -EAGAIN) { + /* unlikely: auto-recovery is required and failed due to read lock being held */ + device_read_unlock(cd, crypt_metadata_device(cd)); + + /* Do not use LUKS2_device_write lock. Recovery. */ + r = device_write_lock(cd, crypt_metadata_device(cd)); + if (r < 0) { + log_err(cd, _("Failed to acquire write lock on device %s."), + device_path(crypt_metadata_device(cd))); + return r; + } + + r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, !repair); + + device_write_unlock(cd, crypt_metadata_device(cd)); + } else + device_read_unlock(cd, crypt_metadata_device(cd)); + + return r; +} + +static int hdr_cleanup_and_validate(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + LUKS2_digests_erase_unused(cd, hdr); + + return LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN); +} + +int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + if (hdr_cleanup_and_validate(cd, hdr)) + return -EINVAL; + + return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), false); +} + +int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + if (hdr_cleanup_and_validate(cd, hdr)) + return -EINVAL; + + return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), true); +} + +int LUKS2_hdr_uuid(struct crypt_device *cd, struct luks2_hdr *hdr, const char *uuid) +{ + uuid_t partitionUuid; + + if (uuid && uuid_parse(uuid, partitionUuid) == -1) { + log_err(cd, _("Wrong LUKS UUID format provided.")); + return -EINVAL; + } + if (!uuid) + uuid_generate(partitionUuid); + + uuid_unparse(partitionUuid, hdr->uuid); + + return LUKS2_hdr_write(cd, hdr); +} + +int LUKS2_hdr_labels(struct crypt_device *cd, struct luks2_hdr *hdr, + const char *label, const char *subsystem, int commit) +{ + //FIXME: check if the labels are the same and skip this. + + memset(hdr->label, 0, LUKS2_LABEL_L); + if (label) + strncpy(hdr->label, label, LUKS2_LABEL_L-1); + + memset(hdr->subsystem, 0, LUKS2_LABEL_L); + if (subsystem) + strncpy(hdr->subsystem, subsystem, LUKS2_LABEL_L-1); + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + if (json_object_put(hdr->jobj)) + hdr->jobj = NULL; + else if (hdr->jobj) + log_dbg(cd, "LUKS2 header still in use"); +} + +uint64_t LUKS2_keyslots_size(json_object *jobj) +{ + json_object *jobj1, *jobj2; + uint64_t keyslots_size; + + json_object_object_get_ex(jobj, "config", &jobj1); + json_object_object_get_ex(jobj1, "keyslots_size", &jobj2); + json_str_to_uint64(jobj2, &keyslots_size); + + return keyslots_size; +} + +uint64_t LUKS2_hdr_and_areas_size(json_object *jobj) +{ + return 2 * LUKS2_metadata_size(jobj) + LUKS2_keyslots_size(jobj); +} + +int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr, + const char *backup_file) +{ + struct device *device = crypt_metadata_device(cd); + int fd, devfd, r = 0; + ssize_t hdr_size; + ssize_t ret, buffer_size; + char *buffer = NULL; + + hdr_size = LUKS2_hdr_and_areas_size(hdr->jobj); + buffer_size = size_round_up(hdr_size, crypt_getpagesize()); + + buffer = crypt_safe_alloc(buffer_size); + if (!buffer) + return -ENOMEM; + + log_dbg(cd, "Storing backup of header (%zu bytes).", hdr_size); + log_dbg(cd, "Output backup file size: %zu bytes.", buffer_size); + + r = device_read_lock(cd, device); + if (r) { + log_err(cd, _("Failed to acquire read lock on device %s."), + device_path(crypt_metadata_device(cd))); + crypt_safe_free(buffer); + return r; + } + + devfd = device_open_locked(cd, device, O_RDONLY); + if (devfd < 0) { + device_read_unlock(cd, device); + log_err(cd, _("Device %s is not a valid LUKS device."), device_path(device)); + crypt_safe_free(buffer); + return devfd == -1 ? -EINVAL : devfd; + } + + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), buffer, hdr_size, 0) < hdr_size) { + device_read_unlock(cd, device); + crypt_safe_free(buffer); + return -EIO; + } + + device_read_unlock(cd, device); + + fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); + if (fd == -1) { + if (errno == EEXIST) + log_err(cd, _("Requested header backup file %s already exists."), backup_file); + else + log_err(cd, _("Cannot create header backup file %s."), backup_file); + crypt_safe_free(buffer); + return -EINVAL; + } + ret = write_buffer(fd, buffer, buffer_size); + close(fd); + if (ret < buffer_size) { + log_err(cd, _("Cannot write header backup file %s."), backup_file); + r = -EIO; + } else + r = 0; + + crypt_safe_free(buffer); + return r; +} + +static int reqs_unknown(uint32_t reqs) +{ + return reqs & CRYPT_REQUIREMENT_UNKNOWN; +} + +static int reqs_reencrypt(uint32_t reqs) +{ + return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT; +} + +static int reqs_reencrypt_online(uint32_t reqs) +{ + return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT; +} + +int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr, + const char *backup_file) +{ + struct device *backup_device, *device = crypt_metadata_device(cd); + int r, fd, devfd = -1, diff_uuid = 0; + ssize_t ret, buffer_size = 0; + char *buffer = NULL, msg[1024]; + struct luks2_hdr hdr_file; + struct luks2_hdr tmp_hdr = {}; + uint32_t reqs = 0; + + r = device_alloc(cd, &backup_device, backup_file); + if (r < 0) + return r; + + r = device_read_lock(cd, backup_device); + if (r) { + log_err(cd, _("Failed to acquire read lock on device %s."), + device_path(backup_device)); + device_free(cd, backup_device); + return r; + } + + r = LUKS2_disk_hdr_read(cd, &hdr_file, backup_device, 0, 0); + device_read_unlock(cd, backup_device); + device_free(cd, backup_device); + + if (r < 0) { + log_err(cd, _("Backup file does not contain valid LUKS header.")); + goto out; + } + + /* do not allow header restore from backup with unmet requirements */ + if (LUKS2_unmet_requirements(cd, &hdr_file, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1)) { + log_err(cd, _("Forbidden LUKS2 requirements detected in backup %s."), + backup_file); + r = -ETXTBSY; + goto out; + } + + buffer_size = LUKS2_hdr_and_areas_size(hdr_file.jobj); + buffer = crypt_safe_alloc(buffer_size); + if (!buffer) { + r = -ENOMEM; + goto out; + } + + fd = open(backup_file, O_RDONLY); + if (fd == -1) { + log_err(cd, _("Cannot open header backup file %s."), backup_file); + r = -EINVAL; + goto out; + } + + ret = read_buffer(fd, buffer, buffer_size); + close(fd); + if (ret < buffer_size) { + log_err(cd, _("Cannot read header backup file %s."), backup_file); + r = -EIO; + goto out; + } + + r = LUKS2_hdr_read(cd, &tmp_hdr, 0); + if (r == 0) { + log_dbg(cd, "Device %s already contains LUKS2 header, checking UUID and requirements.", device_path(device)); + r = LUKS2_config_get_requirements(cd, &tmp_hdr, &reqs); + if (r) + goto out; + + if (memcmp(tmp_hdr.uuid, hdr_file.uuid, LUKS2_UUID_L)) + diff_uuid = 1; + + if (!reqs_reencrypt(reqs)) { + log_dbg(cd, "Checking LUKS2 header size and offsets."); + if (LUKS2_get_data_offset(&tmp_hdr) != LUKS2_get_data_offset(&hdr_file)) { + log_err(cd, _("Data offset differ on device and backup, restore failed.")); + r = -EINVAL; + goto out; + } + /* FIXME: what could go wrong? Erase if we're fine with consequences */ + if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(tmp_hdr.jobj)) { + log_err(cd, _("Binary header with keyslot areas size differ on device and backup, restore failed.")); + r = -EINVAL; + goto out; + } + } + } + + r = snprintf(msg, sizeof(msg), _("Device %s %s%s%s%s"), device_path(device), + r ? _("does not contain LUKS2 header. Replacing header can destroy data on that device.") : + _("already contains LUKS2 header. Replacing header will destroy existing keyslots."), + diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "", + reqs_unknown(reqs) ? _("\nWARNING: unknown LUKS2 requirements detected in real device header!" + "\nReplacing header with backup may corrupt the data on that device!") : "", + reqs_reencrypt(reqs) ? _("\nWARNING: Unfinished offline reencryption detected on the device!" + "\nReplacing header with backup may corrupt data.") : ""); + if (r < 0 || (size_t) r >= sizeof(msg)) { + r = -ENOMEM; + goto out; + } + + if (!crypt_confirm(cd, msg)) { + r = -EINVAL; + goto out; + } + + log_dbg(cd, "Storing backup of header (%zu bytes) to device %s.", buffer_size, device_path(device)); + + /* Do not use LUKS2_device_write lock for checking sequence id on restore */ + r = device_write_lock(cd, device); + if (r < 0) { + log_err(cd, _("Failed to acquire write lock on device %s."), + device_path(device)); + goto out; + } + + devfd = device_open_locked(cd, device, O_RDWR); + if (devfd < 0) { + if (errno == EACCES) + log_err(cd, _("Cannot write to device %s, permission denied."), + device_path(device)); + else + log_err(cd, _("Cannot open device %s."), device_path(device)); + device_write_unlock(cd, device); + r = -EINVAL; + goto out; + } + + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), buffer, buffer_size, 0) < buffer_size) + r = -EIO; + else + r = 0; + + device_write_unlock(cd, device); +out: + LUKS2_hdr_free(cd, hdr); + LUKS2_hdr_free(cd, &hdr_file); + LUKS2_hdr_free(cd, &tmp_hdr); + crypt_safe_memzero(&hdr_file, sizeof(hdr_file)); + crypt_safe_memzero(&tmp_hdr, sizeof(tmp_hdr)); + crypt_safe_free(buffer); + + device_sync(cd, device); + + return r; +} + +/* + * Persistent config flags + */ +static const struct { + uint32_t flag; + const char *description; +} persistent_flags[] = { + { CRYPT_ACTIVATE_ALLOW_DISCARDS, "allow-discards" }, + { CRYPT_ACTIVATE_SAME_CPU_CRYPT, "same-cpu-crypt" }, + { CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS, "submit-from-crypt-cpus" }, + { CRYPT_ACTIVATE_NO_JOURNAL, "no-journal" }, + { 0, NULL } +}; + +int LUKS2_config_get_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *flags) +{ + json_object *jobj1, *jobj_config, *jobj_flags; + int i, j, found; + + if (!hdr || !flags) + return -EINVAL; + + *flags = 0; + + if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) + return 0; + + if (!json_object_object_get_ex(jobj_config, "flags", &jobj_flags)) + return 0; + + for (i = 0; i < (int) json_object_array_length(jobj_flags); i++) { + jobj1 = json_object_array_get_idx(jobj_flags, i); + found = 0; + for (j = 0; persistent_flags[j].description && !found; j++) + if (!strcmp(persistent_flags[j].description, + json_object_get_string(jobj1))) { + *flags |= persistent_flags[j].flag; + log_dbg(cd, "Using persistent flag %s.", + json_object_get_string(jobj1)); + found = 1; + } + if (!found) + log_verbose(cd, _("Ignored unknown flag %s."), + json_object_get_string(jobj1)); + } + + return 0; +} + +int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t flags) +{ + json_object *jobj_config, *jobj_flags; + int i; + + if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) + return 0; + + jobj_flags = json_object_new_array(); + + for (i = 0; persistent_flags[i].description; i++) { + if (flags & persistent_flags[i].flag) { + log_dbg(cd, "Setting persistent flag: %s.", persistent_flags[i].description); + json_object_array_add(jobj_flags, + json_object_new_string(persistent_flags[i].description)); + } + } + + /* Replace or add new flags array */ + json_object_object_add(jobj_config, "flags", jobj_flags); + + return LUKS2_hdr_write(cd, hdr); +} + +/* + * json format example (mandatory array must not be ignored, + * all other future fields may be added later) + * + * "requirements": { + * mandatory : [], + * optional0 : [], + * optional1 : "lala" + * } + */ + +/* LUKS2 library requirements */ +static const struct { + uint32_t flag; + const char *description; +} requirements_flags[] = { + { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" }, + { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" }, + { 0, NULL } +}; + +static uint32_t get_requirement_by_name(const char *requirement) +{ + int i; + + for (i = 0; requirements_flags[i].description; i++) + if (!strcmp(requirement, requirements_flags[i].description)) + return requirements_flags[i].flag; + + return CRYPT_REQUIREMENT_UNKNOWN; +} + +/* + * returns count of requirements (past cryptsetup 2.0 release) + */ +int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs) +{ + json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj; + int i, len; + uint32_t req; + + assert(hdr); + if (!hdr || !reqs) + return -EINVAL; + + *reqs = 0; + + if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) + return 0; + + if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements)) + return 0; + + if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory)) + return 0; + + len = (int) json_object_array_length(jobj_mandatory); + if (len <= 0) + return 0; + + log_dbg(cd, "LUKS2 requirements detected:"); + + for (i = 0; i < len; i++) { + jobj = json_object_array_get_idx(jobj_mandatory, i); + req = get_requirement_by_name(json_object_get_string(jobj)); + log_dbg(cd, "%s - %sknown", json_object_get_string(jobj), + reqs_unknown(req) ? "un" : ""); + *reqs |= req; + } + + return 0; +} + +int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit) +{ + json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj; + int i, r = -EINVAL; + + if (!hdr) + return -EINVAL; + + jobj_mandatory = json_object_new_array(); + if (!jobj_mandatory) + return -ENOMEM; + + for (i = 0; requirements_flags[i].description; i++) { + if (reqs & requirements_flags[i].flag) { + jobj = json_object_new_string(requirements_flags[i].description); + if (!jobj) { + r = -ENOMEM; + goto err; + } + json_object_array_add(jobj_mandatory, jobj); + /* erase processed flag from input set */ + reqs &= ~(requirements_flags[i].flag); + } + } + + /* any remaining bit in requirements is unknown therefore illegal */ + if (reqs) { + log_dbg(cd, "Illegal requirement flag(s) requested"); + goto err; + } + + if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) + goto err; + + if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements)) { + jobj_requirements = json_object_new_object(); + if (!jobj_requirements) { + r = -ENOMEM; + goto err; + } + json_object_object_add(jobj_config, "requirements", jobj_requirements); + } + + if (json_object_array_length(jobj_mandatory) > 0) { + /* replace mandatory field with new values */ + json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory); + } else { + /* new mandatory field was empty, delete old one */ + json_object_object_del(jobj_requirements, "mandatory"); + json_object_put(jobj_mandatory); + } + + /* remove empty requirements object */ + if (!json_object_object_length(jobj_requirements)) + json_object_object_del(jobj_config, "requirements"); + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +err: + json_object_put(jobj_mandatory); + return r; +} + +/* + * Header dump + */ +static void hdr_dump_config(struct crypt_device *cd, json_object *hdr_jobj) +{ + + json_object *jobj1, *jobj_config, *jobj_flags, *jobj_requirements, *jobj_mandatory; + int i = 0, flags = 0, reqs = 0; + + log_std(cd, "Flags: \t"); + + if (json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) { + if (json_object_object_get_ex(jobj_config, "flags", &jobj_flags)) + flags = (int) json_object_array_length(jobj_flags); + if (json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements) && + json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory)) + reqs = (int) json_object_array_length(jobj_mandatory); + } + + for (i = 0; i < flags; i++) { + jobj1 = json_object_array_get_idx(jobj_flags, i); + log_std(cd, "%s ", json_object_get_string(jobj1)); + } + + log_std(cd, "%s\n%s", flags > 0 ? "" : "(no flags)", reqs > 0 ? "" : "\n"); + + if (reqs > 0) { + log_std(cd, "Requirements:\t"); + for (i = 0; i < reqs; i++) { + jobj1 = json_object_array_get_idx(jobj_mandatory, i); + log_std(cd, "%s ", json_object_get_string(jobj1)); + } + log_std(cd, "\n\n"); + } +} + +static const char *get_priority_desc(json_object *jobj) +{ + crypt_keyslot_priority priority; + json_object *jobj_priority; + const char *text; + + if (json_object_object_get_ex(jobj, "priority", &jobj_priority)) + priority = (crypt_keyslot_priority)(int)json_object_get_int(jobj_priority); + else + priority = CRYPT_SLOT_PRIORITY_NORMAL; + + switch (priority) { + case CRYPT_SLOT_PRIORITY_IGNORE: text = "ignored"; break; + case CRYPT_SLOT_PRIORITY_PREFER: text = "preferred"; break; + case CRYPT_SLOT_PRIORITY_NORMAL: text = "normal"; break; + default: text = "invalid"; + } + + return text; +} + +static void hdr_dump_keyslots(struct crypt_device *cd, json_object *hdr_jobj) +{ + char slot[16]; + json_object *keyslots_jobj, *digests_jobj, *jobj2, *jobj3, *val; + const char *tmps; + int i, j, r; + + log_std(cd, "Keyslots:\n"); + json_object_object_get_ex(hdr_jobj, "keyslots", &keyslots_jobj); + + for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++) { + (void) snprintf(slot, sizeof(slot), "%i", j); + json_object_object_get_ex(keyslots_jobj, slot, &val); + if (!val) + continue; + + json_object_object_get_ex(val, "type", &jobj2); + tmps = json_object_get_string(jobj2); + + r = LUKS2_keyslot_for_segment(crypt_get_hdr(cd, CRYPT_LUKS2), j, CRYPT_ONE_SEGMENT); + log_std(cd, " %s: %s%s\n", slot, tmps, r == -ENOENT ? " (unbound)" : ""); + + if (json_object_object_get_ex(val, "key_size", &jobj2)) + log_std(cd, "\tKey: %u bits\n", crypt_jobj_get_uint32(jobj2) * 8); + + log_std(cd, "\tPriority: %s\n", get_priority_desc(val)); + + LUKS2_keyslot_dump(cd, j); + + json_object_object_get_ex(hdr_jobj, "digests", &digests_jobj); + json_object_object_foreach(digests_jobj, key2, val2) { + json_object_object_get_ex(val2, "keyslots", &jobj2); + for (i = 0; i < (int) json_object_array_length(jobj2); i++) { + jobj3 = json_object_array_get_idx(jobj2, i); + if (!strcmp(slot, json_object_get_string(jobj3))) { + log_std(cd, "\tDigest ID: %s\n", key2); + } + } + } + } +} + +static void hdr_dump_tokens(struct crypt_device *cd, json_object *hdr_jobj) +{ + char token[16]; + json_object *tokens_jobj, *jobj2, *jobj3, *val; + const char *tmps; + int i, j; + + log_std(cd, "Tokens:\n"); + json_object_object_get_ex(hdr_jobj, "tokens", &tokens_jobj); + + for (j = 0; j < LUKS2_TOKENS_MAX; j++) { + (void) snprintf(token, sizeof(token), "%i", j); + json_object_object_get_ex(tokens_jobj, token, &val); + if (!val) + continue; + + json_object_object_get_ex(val, "type", &jobj2); + tmps = json_object_get_string(jobj2); + log_std(cd, " %s: %s\n", token, tmps); + + LUKS2_token_dump(cd, j); + + json_object_object_get_ex(val, "keyslots", &jobj2); + for (i = 0; i < (int) json_object_array_length(jobj2); i++) { + jobj3 = json_object_array_get_idx(jobj2, i); + log_std(cd, "\tKeyslot: %s\n", json_object_get_string(jobj3)); + } + } +} + +static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj) +{ + char segment[16]; + json_object *jobj_segments, *jobj_segment, *jobj1, *jobj2; + int i, j, flags; + uint64_t value; + + log_std(cd, "Data segments:\n"); + json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments); + + for (i = 0; i < LUKS2_SEGMENT_MAX; i++) { + (void) snprintf(segment, sizeof(segment), "%i", i); + if (!json_object_object_get_ex(jobj_segments, segment, &jobj_segment)) + continue; + + json_object_object_get_ex(jobj_segment, "type", &jobj1); + log_std(cd, " %s: %s\n", segment, json_object_get_string(jobj1)); + + json_object_object_get_ex(jobj_segment, "offset", &jobj1); + json_str_to_uint64(jobj1, &value); + log_std(cd, "\toffset: %" PRIu64 " [bytes]\n", value); + + json_object_object_get_ex(jobj_segment, "size", &jobj1); + if (!(strcmp(json_object_get_string(jobj1), "dynamic"))) + log_std(cd, "\tlength: (whole device)\n"); + else { + json_str_to_uint64(jobj1, &value); + log_std(cd, "\tlength: %" PRIu64 " [bytes]\n", value); + } + + if (json_object_object_get_ex(jobj_segment, "encryption", &jobj1)) + log_std(cd, "\tcipher: %s\n", json_object_get_string(jobj1)); + + if (json_object_object_get_ex(jobj_segment, "sector_size", &jobj1)) + log_std(cd, "\tsector: %" PRIu32 " [bytes]\n", crypt_jobj_get_uint32(jobj1)); + + if (json_object_object_get_ex(jobj_segment, "integrity", &jobj1) && + json_object_object_get_ex(jobj1, "type", &jobj2)) + log_std(cd, "\tintegrity: %s\n", json_object_get_string(jobj2)); + + if (json_object_object_get_ex(jobj_segment, "flags", &jobj1) && + (flags = (int)json_object_array_length(jobj1)) > 0) { + jobj2 = json_object_array_get_idx(jobj1, 0); + log_std(cd, "\tflags : %s", json_object_get_string(jobj2)); + for (j = 1; j < flags; j++) { + jobj2 = json_object_array_get_idx(jobj1, j); + log_std(cd, ", %s", json_object_get_string(jobj2)); + } + log_std(cd, "\n"); + } + + log_std(cd, "\n"); + } +} + +static void hdr_dump_digests(struct crypt_device *cd, json_object *hdr_jobj) +{ + char key[16]; + json_object *jobj1, *jobj2, *val; + const char *tmps; + int i; + + log_std(cd, "Digests:\n"); + json_object_object_get_ex(hdr_jobj, "digests", &jobj1); + + for (i = 0; i < LUKS2_DIGEST_MAX; i++) { + (void) snprintf(key, sizeof(key), "%i", i); + json_object_object_get_ex(jobj1, key, &val); + if (!val) + continue; + + json_object_object_get_ex(val, "type", &jobj2); + tmps = json_object_get_string(jobj2); + log_std(cd, " %s: %s\n", key, tmps); + + LUKS2_digest_dump(cd, i); + } +} + +int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr) +{ + if (!hdr->jobj) + return -EINVAL; + + JSON_DBG(cd, hdr->jobj, NULL); + + log_std(cd, "LUKS header information\n"); + log_std(cd, "Version: \t%u\n", hdr->version); + log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid); + log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr->jobj)); + log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr->jobj)); + log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)"); + log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no label)"); + log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : "(no subsystem)"); + + hdr_dump_config(cd, hdr->jobj); + hdr_dump_segments(cd, hdr->jobj); + hdr_dump_keyslots(cd, hdr->jobj); + hdr_dump_tokens(cd, hdr->jobj); + hdr_dump_digests(cd, hdr->jobj); + + return 0; +} + +int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic) +{ + int sector_size; + json_object *jobj_segments, *jobj_size; + uint64_t tmp = 0; + + if (!size || !json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) + return -EINVAL; + + json_object_object_foreach(jobj_segments, key, val) { + UNUSED(key); + if (json_segment_is_backup(val)) + continue; + + json_object_object_get_ex(val, "size", &jobj_size); + if (!strcmp(json_object_get_string(jobj_size), "dynamic")) { + sector_size = json_segment_get_sector_size(val); + /* last dynamic segment must have at least one sector in size */ + if (tmp) + *size = tmp + (sector_size > 0 ? sector_size : SECTOR_SIZE); + else + *size = 0; + if (dynamic) + *dynamic = true; + return 0; + } + + tmp += crypt_jobj_get_uint64(jobj_size); + } + + /* impossible, real device size must not be zero */ + if (!tmp) + return -EINVAL; + + *size = tmp; + if (dynamic) + *dynamic = false; + return 0; +} + +uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr) +{ + crypt_reencrypt_info ri; + json_object *jobj; + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) { + jobj = LUKS2_get_segment_by_flag(hdr, "backup-final"); + if (jobj) + return json_segment_get_offset(jobj, 1); + } + + return json_segments_get_minimal_offset(LUKS2_get_segments_jobj(hdr), 1); +} + +const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment) +{ + json_object *jobj_segment; + + if (!hdr) + return NULL; + + if (segment == CRYPT_DEFAULT_SEGMENT) + segment = LUKS2_get_default_segment(hdr); + + jobj_segment = json_segments_get_segment(json_get_segments_jobj(hdr->jobj), segment); + if (!jobj_segment) + return NULL; + + /* FIXME: default encryption (for other segment types) must be string here. */ + return json_segment_get_cipher(jobj_segment) ?: "null"; +} + +crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr) +{ + uint32_t reqs; + + /* + * Any unknown requirement or offline reencryption should abort + * anything related to online-reencryption handling + */ + if (LUKS2_config_get_requirements(NULL, hdr, &reqs)) + return CRYPT_REENCRYPT_INVALID; + + if (!reqs_reencrypt_online(reqs)) + return CRYPT_REENCRYPT_NONE; + + if (json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr)) < 0) + return CRYPT_REENCRYPT_CLEAN; + + return CRYPT_REENCRYPT_CRASH; +} + +const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size) +{ + json_object *jobj_keyslot, *jobj_area, *jobj1; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return NULL; + + if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return NULL; + + /* currently we only support raw length preserving area encryption */ + json_object_object_get_ex(jobj_area, "type", &jobj1); + if (strcmp(json_object_get_string(jobj1), "raw")) + return NULL; + + if (!json_object_object_get_ex(jobj_area, "key_size", &jobj1)) + return NULL; + *key_size = json_object_get_int(jobj1); + + if (!json_object_object_get_ex(jobj_area, "encryption", &jobj1)) + return NULL; + + return json_object_get_string(jobj1); +} + +const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment) +{ + json_object *jobj1, *jobj2, *jobj3; + + jobj1 = LUKS2_get_segment_jobj(hdr, segment); + if (!jobj1) + return NULL; + + if (!json_object_object_get_ex(jobj1, "integrity", &jobj2)) + return NULL; + + if (!json_object_object_get_ex(jobj2, "type", &jobj3)) + return NULL; + + return json_object_get_string(jobj3); +} + +/* FIXME: this only ensures that once we have journal encryption, it is not ignored. */ +/* implement segment count and type restrictions (crypt and only single crypt) */ +static int LUKS2_integrity_compatible(struct luks2_hdr *hdr) +{ + json_object *jobj1, *jobj2, *jobj3, *jobj4; + const char *str; + + if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj1)) + return 0; + + if (!(jobj2 = LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT))) + return 0; + + if (!json_object_object_get_ex(jobj2, "integrity", &jobj3)) + return 0; + + if (!json_object_object_get_ex(jobj3, "journal_encryption", &jobj4) || + !(str = json_object_get_string(jobj4)) || + strcmp(str, "none")) + return 0; + + if (!json_object_object_get_ex(jobj3, "journal_integrity", &jobj4) || + !(str = json_object_get_string(jobj4)) || + strcmp(str, "none")) + return 0; + + return 1; +} + +static int LUKS2_keyslot_get_volume_key_size(struct luks2_hdr *hdr, const char *keyslot) +{ + json_object *jobj1, *jobj2, *jobj3; + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj1)) + return -1; + + if (!json_object_object_get_ex(jobj1, keyslot, &jobj2)) + return -1; + + if (!json_object_object_get_ex(jobj2, "key_size", &jobj3)) + return -1; + + return json_object_get_int(jobj3); +} + +/* Key size used for encryption of keyslot */ +int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot) +{ + char keyslot_name[16]; + + if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1) + return -1; + + return LUKS2_keyslot_get_volume_key_size(hdr, keyslot_name); +} + +int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment) +{ + json_object *jobj_digests, *jobj_digest_segments, *jobj_digest_keyslots, *jobj1; + char buf[16]; + + if (segment == CRYPT_DEFAULT_SEGMENT) + segment = LUKS2_get_default_segment(hdr); + + if (snprintf(buf, sizeof(buf), "%u", segment) < 1) + return -1; + + json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests); + + json_object_object_foreach(jobj_digests, key, val) { + UNUSED(key); + json_object_object_get_ex(val, "segments", &jobj_digest_segments); + json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots); + + if (!LUKS2_array_jobj(jobj_digest_segments, buf)) + continue; + if (json_object_array_length(jobj_digest_keyslots) <= 0) + continue; + + jobj1 = json_object_array_get_idx(jobj_digest_keyslots, 0); + + return LUKS2_keyslot_get_volume_key_size(hdr, json_object_get_string(jobj1)); + } + + return -1; +} + +int LUKS2_get_sector_size(struct luks2_hdr *hdr) +{ + json_object *jobj_segment; + + jobj_segment = LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT); + if (!jobj_segment) + return SECTOR_SIZE; + + return json_segment_get_sector_size(jobj_segment) ?: SECTOR_SIZE; +} + +int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct volume_key *vks, + json_object *jobj_segments, + struct crypt_dm_active_device *dmd) +{ + struct volume_key *vk; + json_object *jobj; + enum devcheck device_check; + int r; + unsigned s = 0; + uint64_t data_offset, segment_size, segment_offset, segment_start = 0; + struct dm_target *t = &dmd->segment; + + if (dmd->flags & CRYPT_ACTIVATE_SHARED) + device_check = DEV_OK; + else + device_check = DEV_EXCL; + + data_offset = LUKS2_reencrypt_data_offset(hdr, true); + + r = device_block_adjust(cd, crypt_data_device(cd), device_check, + data_offset, &dmd->size, &dmd->flags); + if (r) + return r; + + r = dm_targets_allocate(&dmd->segment, json_segments_count(jobj_segments)); + if (r) + goto err; + + r = -EINVAL; + + while (t) { + jobj = json_segments_get_segment(jobj_segments, s); + if (!jobj) { + log_dbg(cd, "Internal error. Segment %u is null.", s); + r = -EINVAL; + goto err; + } + + segment_offset = json_segment_get_offset(jobj, 1); + segment_size = json_segment_get_size(jobj, 1); + /* 'dynamic' length allowed in last segment only */ + if (!segment_size && !t->next) + segment_size = dmd->size - segment_start; + if (!segment_size) { + log_dbg(cd, "Internal error. Wrong segment size %u", s); + r = -EINVAL; + goto err; + } + + if (!strcmp(json_segment_type(jobj), "crypt")) { + vk = crypt_volume_key_by_id(vks, LUKS2_digest_by_segment(hdr, s)); + if (!vk) { + log_err(cd, _("Missing key for dm-crypt segment %u"), s); + r = -EINVAL; + goto err; + } + + r = dm_crypt_target_set(t, segment_start, segment_size, + crypt_data_device(cd), vk, + json_segment_get_cipher(jobj), + json_segment_get_iv_offset(jobj), + segment_offset, "none", 0, + json_segment_get_sector_size(jobj)); + if (r) { + log_err(cd, _("Failed to set dm-crypt segment.")); + goto err; + } + } else if (!strcmp(json_segment_type(jobj), "linear")) { + r = dm_linear_target_set(t, segment_start, segment_size, crypt_data_device(cd), segment_offset); + if (r) { + log_err(cd, _("Failed to set dm-linear segment.")); + goto err; + } + } else { + r = -EINVAL; + goto err; + } + + segment_start += segment_size; + t = t->next; + s++; + } + + return r; +err: + dm_targets_free(cd, dmd); + return r; +} + +/* FIXME: This shares almost all code with activate_multi_custom */ +static int _reload_custom_multi(struct crypt_device *cd, + const char *name, + struct volume_key *vks, + json_object *jobj_segments, + uint64_t device_size, + uint32_t flags) +{ + int r; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + struct crypt_dm_active_device dmd = { + .uuid = crypt_get_uuid(cd), + .size = device_size >> SECTOR_SHIFT + }; + + /* do not allow activation when particular requirements detected */ + if ((r = LUKS2_unmet_requirements(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0))) + return r; + + /* Add persistent activation flags */ + if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT)) + LUKS2_config_get_flags(cd, hdr, &dmd.flags); + + dmd.flags |= (flags | CRYPT_ACTIVATE_SHARED); + + r = LUKS2_assembly_multisegment_dmd(cd, hdr, vks, jobj_segments, &dmd); + if (!r) + r = dm_reload_device(cd, name, &dmd, 0, 0); + + dm_targets_free(cd, &dmd); + return r; +} + +int LUKS2_reload(struct crypt_device *cd, + const char *name, + struct volume_key *vks, + uint64_t device_size, + uint32_t flags) +{ + if (crypt_get_integrity_tag_size(cd)) + return -ENOTSUP; + + return _reload_custom_multi(cd, name, vks, + LUKS2_get_segments_jobj(crypt_get_hdr(cd, CRYPT_LUKS2)), device_size, flags); +} + +int LUKS2_activate_multi(struct crypt_device *cd, + const char *name, + struct volume_key *vks, + uint64_t device_size, + uint32_t flags) +{ + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + json_object *jobj_segments = LUKS2_get_segments_jobj(hdr); + int r; + struct crypt_dm_active_device dmd = { + .size = device_size, + .uuid = crypt_get_uuid(cd) + }; + + /* do not allow activation when particular requirements detected */ + if ((r = LUKS2_unmet_requirements(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0))) + return r; + + /* Add persistent activation flags */ + if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT)) + LUKS2_config_get_flags(cd, hdr, &dmd.flags); + + dmd.flags |= flags; + + r = LUKS2_assembly_multisegment_dmd(cd, hdr, vks, jobj_segments, &dmd); + if (!r) + r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd); + + dm_targets_free(cd, &dmd); + return r; +} + +int LUKS2_activate(struct crypt_device *cd, + const char *name, + struct volume_key *vk, + uint32_t flags) +{ + int r; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + struct crypt_dm_active_device dmdi = {}, dmd = { + .uuid = crypt_get_uuid(cd) + }; + + /* do not allow activation when particular requirements detected */ + if ((r = LUKS2_unmet_requirements(cd, hdr, 0, 0))) + return r; + + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), + vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), + crypt_get_data_offset(cd), crypt_get_integrity(cd) ?: "none", + crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); + if (r < 0) + return r; + + /* Add persistent activation flags */ + if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT)) + LUKS2_config_get_flags(cd, hdr, &dmd.flags); + + dmd.flags |= flags; + + if (crypt_get_integrity_tag_size(cd)) { + if (!LUKS2_integrity_compatible(hdr)) { + log_err(cd, _("Unsupported device integrity configuration.")); + return -EINVAL; + } + + if (dmd.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) { + log_err(cd, _("Discard/TRIM is not supported.")); + return -EINVAL; + } + + r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags, 0); + if (r) + return r; + + dmdi.flags |= CRYPT_ACTIVATE_PRIVATE; + dmdi.uuid = dmd.uuid; + dmd.segment.u.crypt.offset = 0; + dmd.segment.size = dmdi.segment.size; + + r = create_or_reload_device_with_integrity(cd, name, CRYPT_LUKS2, &dmd, &dmdi); + } else + r = create_or_reload_device(cd, name, CRYPT_LUKS2, &dmd); + + dm_targets_free(cd, &dmd); + dm_targets_free(cd, &dmdi); + + return r; +} + +static bool is_reencryption_helper(const char *name) +{ + size_t len; + + if (!name) + return false; + + len = strlen(name); + return (len >= 9 && (!strncmp(name + len - 8, "-hotzone-", 9) || + !strcmp(name + len - 8, "-overlay"))); + +} + +static bool contains_reencryption_helper(char **names) +{ + while (*names) { + if (is_reencryption_helper(*names++)) + return true; + } + + return false; +} + +int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr *hdr, struct crypt_dm_active_device *dmd, uint32_t flags) +{ + int r, ret; + struct dm_target *tgt; + crypt_status_info ci; + struct crypt_dm_active_device dmdc; + char **dep, deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 }; + const char *namei = NULL; + struct crypt_lock_handle *reencrypt_lock = NULL; + + if (!dmd || !dmd->uuid || strncmp(CRYPT_LUKS2, dmd->uuid, sizeof(CRYPT_LUKS2)-1)) + return -EINVAL; + + /* uuid mismatch with metadata (if available) */ + if (hdr && crypt_uuid_cmp(dmd->uuid, hdr->uuid)) + return -EINVAL; + + r = snprintf(deps_uuid_prefix, sizeof(deps_uuid_prefix), CRYPT_SUBDEV "-%.32s", dmd->uuid + 6); + if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1)) + return -EINVAL; + + tgt = &dmd->segment; + + /* TODO: We have LUKS2 dependencies now */ + if (hdr && single_segment(dmd) && tgt->type == DM_CRYPT && crypt_get_integrity_tag_size(cd)) + namei = device_dm_name(tgt->data_device); + + r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps)); + if (r < 0) + goto out; + + if (contains_reencryption_helper(deps)) { + r = crypt_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_lock); + if (r) { + if (r == -EBUSY) + log_err(cd, _("Reencryption in-progress. Cannot deactivate device.")); + else + log_err(cd, _("Failed to get reencryption lock.")); + goto out; + } + } + + dep = deps; + while (*dep) { + if (is_reencryption_helper(*dep) && (dm_status_suspended(cd, *dep) > 0)) { + if (dm_error_device(cd, *dep)) + log_err(cd, _("Failed to replace suspended device %s with dm-error target."), *dep); + } + dep++; + } + + r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmdc); + if (r < 0) { + memset(&dmdc, 0, sizeof(dmdc)); + dmdc.segment.type = DM_UNKNOWN; + } + + /* Remove top level device first */ + r = dm_remove_device(cd, name, flags); + if (!r) { + tgt = &dmdc.segment; + while (tgt) { + if (tgt->type == DM_CRYPT) + crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY); + tgt = tgt->next; + } + } + dm_targets_free(cd, &dmdc); + + /* TODO: We have LUKS2 dependencies now */ + if (r >= 0 && namei) { + log_dbg(cd, "Deactivating integrity device %s.", namei); + r = dm_remove_device(cd, namei, 0); + } + + if (!r) { + ret = 0; + dep = deps; + while (*dep) { + log_dbg(cd, "Deactivating LUKS2 dependent device %s.", *dep); + r = dm_query_device(cd, *dep, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmdc); + if (r < 0) { + memset(&dmdc, 0, sizeof(dmdc)); + dmdc.segment.type = DM_UNKNOWN; + } + + r = dm_remove_device(cd, *dep, flags); + if (r < 0) { + ci = crypt_status(cd, *dep); + if (ci == CRYPT_BUSY) + log_err(cd, _("Device %s is still in use."), *dep); + if (ci == CRYPT_INACTIVE) + r = 0; + } + if (!r) { + tgt = &dmdc.segment; + while (tgt) { + if (tgt->type == DM_CRYPT) + crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY); + tgt = tgt->next; + } + } + dm_targets_free(cd, &dmdc); + if (r && !ret) + ret = r; + dep++; + } + r = ret; + } + +out: + crypt_reencrypt_unlock(cd, reencrypt_lock); + dep = deps; + while (*dep) + free(*dep++); + + return r; +} + +int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet) +{ + uint32_t reqs; + int r = LUKS2_config_get_requirements(cd, hdr, &reqs); + + if (r) { + if (!quiet) + log_err(cd, _("Failed to read LUKS2 requirements.")); + return r; + } + + /* do not mask unknown requirements check */ + if (reqs_unknown(reqs)) { + if (!quiet) + log_err(cd, _("Unmet LUKS2 requirements detected.")); + return -ETXTBSY; + } + + /* mask out permitted requirements */ + reqs &= ~reqs_mask; + + if (reqs_reencrypt(reqs) && !quiet) + log_err(cd, _("Operation incompatible with device marked for legacy reencryption. Aborting.")); + if (reqs_reencrypt_online(reqs) && !quiet) + log_err(cd, _("Operation incompatible with device marked for LUKS2 reencryption. Aborting.")); + + /* any remaining unmasked requirement fails the check */ + return reqs ? -EINVAL : 0; +} + +/* + * NOTE: this routine is called on json object that failed validation. + * Proceed with caution :) + * + * known glitches so far: + * + * any version < 2.0.3: + * - luks2 keyslot pbkdf params change via crypt_keyslot_change_by_passphrase() + * could leave previous type parameters behind. Correct this by purging + * all params not needed by current type. + */ +void LUKS2_hdr_repair(struct crypt_device *cd, json_object *hdr_jobj) +{ + json_object *jobj_keyslots; + + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) + return; + if (!json_object_is_type(jobj_keyslots, json_type_object)) + return; + + LUKS2_keyslots_repair(cd, jobj_keyslots); +} + +void json_object_object_del_by_uint(json_object *jobj, unsigned key) +{ + char key_name[16]; + + if (snprintf(key_name, sizeof(key_name), "%u", key) < 1) + return; + json_object_object_del(jobj, key_name); +} + +int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val) +{ + char key_name[16]; + + if (snprintf(key_name, sizeof(key_name), "%u", key) < 1) + return -EINVAL; + +#if HAVE_DECL_JSON_OBJECT_OBJECT_ADD_EX + return json_object_object_add_ex(jobj, key_name, jobj_val, 0) ? -ENOMEM : 0; +#else + json_object_object_add(jobj, key_name, jobj_val); + return 0; +#endif +} + +/* jobj_dst must contain pointer initialized to NULL (see json-c json_object_deep_copy API) */ +int json_object_copy(json_object *jobj_src, json_object **jobj_dst) +{ + if (!jobj_src || !jobj_dst || *jobj_dst) + return -1; + +#if HAVE_DECL_JSON_OBJECT_DEEP_COPY + return json_object_deep_copy(jobj_src, jobj_dst, NULL); +#else + *jobj_dst = json_tokener_parse(json_object_get_string(jobj_src)); + return *jobj_dst ? 0 : -1; +#endif +} diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c new file mode 100644 index 0000000..3b8c889 --- /dev/null +++ b/lib/luks2/luks2_keyslot.c @@ -0,0 +1,937 @@ +/* + * LUKS - Linux Unified Key Setup v2, keyslot handling + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +/* Internal implementations */ +extern const keyslot_handler luks2_keyslot; +extern const keyslot_handler reenc_keyslot; + +static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = { + &luks2_keyslot, + &reenc_keyslot, + NULL +}; + +static const keyslot_handler +*LUKS2_keyslot_handler_type(struct crypt_device *cd, const char *type) +{ + int i; + + for (i = 0; i < LUKS2_KEYSLOTS_MAX && keyslot_handlers[i]; i++) { + if (!strcmp(keyslot_handlers[i]->name, type)) + return keyslot_handlers[i]; + } + + return NULL; +} + +static const keyslot_handler +*LUKS2_keyslot_handler(struct crypt_device *cd, int keyslot) +{ + struct luks2_hdr *hdr; + json_object *jobj1, *jobj2; + + if (keyslot < 0) + return NULL; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return NULL; + + if (!(jobj1 = LUKS2_get_keyslot_jobj(hdr, keyslot))) + return NULL; + + if (!json_object_object_get_ex(jobj1, "type", &jobj2)) + return NULL; + + return LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj2)); +} + +int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr) +{ + int i; + + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) + if (!LUKS2_get_keyslot_jobj(hdr, i)) + return i; + + return -EINVAL; +} + +/* Check if a keyslot is assigned to specific segment */ +static int _keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment) +{ + int keyslot_digest, count = 0; + unsigned s; + + keyslot_digest = LUKS2_digest_by_keyslot(hdr, keyslot); + if (keyslot_digest < 0) + return keyslot_digest; + + if (segment >= 0) + return keyslot_digest == LUKS2_digest_by_segment(hdr, segment); + + for (s = 0; s < json_segments_count(LUKS2_get_segments_jobj(hdr)); s++) { + if (keyslot_digest == LUKS2_digest_by_segment(hdr, s)) + count++; + } + + return count; +} + +static int _keyslot_for_digest(struct luks2_hdr *hdr, int keyslot, int digest) +{ + int r = -EINVAL; + + r = LUKS2_digest_by_keyslot(hdr, keyslot); + if (r < 0) + return r; + return r == digest ? 0 : -ENOENT; +} + +int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment) +{ + int r = -EINVAL; + + /* no need to check anything */ + if (segment == CRYPT_ANY_SEGMENT) + return 0; /* ok */ + if (segment == CRYPT_DEFAULT_SEGMENT) { + segment = LUKS2_get_default_segment(hdr); + if (segment < 0) + return segment; + } + + r = _keyslot_for_segment(hdr, keyslot, segment); + if (r < 0) + return r; + + return r >= 1 ? 0 : -ENOENT; +} + +/* Number of keyslots assigned to a segment or all keyslots for CRYPT_ANY_SEGMENT */ +int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment) +{ + int num = 0; + json_object *jobj_keyslots; + + json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); + + json_object_object_foreach(jobj_keyslots, slot, val) { + UNUSED(val); + if (!LUKS2_keyslot_for_segment(hdr, atoi(slot), segment)) + num++; + } + + return num; +} + +int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec) +{ + char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN]; + + if (!cipher_spec || !strcmp(cipher_spec, "null") || !strcmp(cipher_spec, "cipher_null")) + return 1; + + if (crypt_parse_name_and_mode(cipher_spec, cipher, NULL, cipher_mode) < 0) + return 1; + + /* Keyslot is already authenticated; we cannot use integrity tags here */ + if (crypt_get_integrity_tag_size(cd)) + return 1; + + /* Wrapped key schemes cannot be used for keyslot encryption */ + if (crypt_cipher_wrapped_key(cipher, cipher_mode)) + return 1; + + /* Check if crypto backend can use the cipher */ + if (crypt_cipher_ivsize(cipher, cipher_mode) < 0) + return 1; + + return 0; +} + +int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr, + struct luks2_keyslot_params *params) +{ + const struct crypt_pbkdf_type *pbkdf = crypt_get_pbkdf_type(cd); + const char *cipher_spec; + size_t key_size; + int r; + + if (!hdr || !pbkdf || !params) + return -EINVAL; + + /* + * set keyslot area encryption parameters + */ + params->area_type = LUKS2_KEYSLOT_AREA_RAW; + cipher_spec = crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size); + if (!cipher_spec || !key_size) + return -EINVAL; + + params->area.raw.key_size = key_size; + r = snprintf(params->area.raw.encryption, sizeof(params->area.raw.encryption), "%s", cipher_spec); + if (r < 0 || (size_t)r >= sizeof(params->area.raw.encryption)) + return -EINVAL; + + /* + * set keyslot AF parameters + */ + params->af_type = LUKS2_KEYSLOT_AF_LUKS1; + /* currently we use hash for AF from pbkdf settings */ + r = snprintf(params->af.luks1.hash, sizeof(params->af.luks1.hash), "%s", pbkdf->hash ?: DEFAULT_LUKS1_HASH); + if (r < 0 || (size_t)r >= sizeof(params->af.luks1.hash)) + return -EINVAL; + params->af.luks1.stripes = 4000; + + return 0; +} + +int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf) +{ + json_object *jobj_keyslot, *jobj_kdf, *jobj; + + if (!hdr || !pbkdf) + return -EINVAL; + + if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -ENOENT; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf)) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_kdf, "type", &jobj)) + return -EINVAL; + + memset(pbkdf, 0, sizeof(*pbkdf)); + + pbkdf->type = json_object_get_string(jobj); + if (json_object_object_get_ex(jobj_kdf, "hash", &jobj)) + pbkdf->hash = json_object_get_string(jobj); + if (json_object_object_get_ex(jobj_kdf, "iterations", &jobj)) + pbkdf->iterations = json_object_get_int(jobj); + if (json_object_object_get_ex(jobj_kdf, "time", &jobj)) + pbkdf->iterations = json_object_get_int(jobj); + if (json_object_object_get_ex(jobj_kdf, "memory", &jobj)) + pbkdf->max_memory_kb = json_object_get_int(jobj); + if (json_object_object_get_ex(jobj_kdf, "cpus", &jobj)) + pbkdf->parallel_threads = json_object_get_int(jobj); + + return 0; +} + +static int LUKS2_keyslot_unbound(struct luks2_hdr *hdr, int keyslot) +{ + json_object *jobj_digest, *jobj_segments; + int digest = LUKS2_digest_by_keyslot(hdr, keyslot); + + if (digest < 0) + return 0; + + if (!(jobj_digest = LUKS2_get_digest_jobj(hdr, digest))) + return 0; + + json_object_object_get_ex(jobj_digest, "segments", &jobj_segments); + if (!jobj_segments || !json_object_is_type(jobj_segments, json_type_array) || + json_object_array_length(jobj_segments) == 0) + return 1; + + return 0; +} + +crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot) +{ + if(keyslot >= LUKS2_KEYSLOTS_MAX || keyslot < 0) + return CRYPT_SLOT_INVALID; + + if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) + return CRYPT_SLOT_INACTIVE; + + if (LUKS2_digest_by_keyslot(hdr, keyslot) < 0 || + LUKS2_keyslot_unbound(hdr, keyslot)) + return CRYPT_SLOT_UNBOUND; + + if (LUKS2_keyslot_active_count(hdr, CRYPT_DEFAULT_SEGMENT) == 1 && + !LUKS2_keyslot_for_segment(hdr, keyslot, CRYPT_DEFAULT_SEGMENT)) + return CRYPT_SLOT_ACTIVE_LAST; + + return CRYPT_SLOT_ACTIVE; +} + +int LUKS2_keyslot_area(struct luks2_hdr *hdr, + int keyslot, + uint64_t *offset, + uint64_t *length) +{ + json_object *jobj_keyslot, *jobj_area, *jobj; + + if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -ENOENT; + + if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_area, "offset", &jobj)) + return -EINVAL; + *offset = crypt_jobj_get_uint64(jobj); + + if (!json_object_object_get_ex(jobj_area, "size", &jobj)) + return -EINVAL; + *length = crypt_jobj_get_uint64(jobj); + + return 0; +} + +static int _open_and_verify(struct crypt_device *cd, + struct luks2_hdr *hdr, + const keyslot_handler *h, + int keyslot, + const char *password, + size_t password_len, + struct volume_key **vk) +{ + int r, key_size = LUKS2_get_keyslot_stored_key_size(hdr, keyslot); + + if (key_size < 0) + return -EINVAL; + + *vk = crypt_alloc_volume_key(key_size, NULL); + if (!*vk) + return -ENOMEM; + + r = h->open(cd, keyslot, password, password_len, (*vk)->key, (*vk)->keylength); + if (r < 0) + log_dbg(cd, "Keyslot %d (%s) open failed with %d.", keyslot, h->name, r); + else + r = LUKS2_digest_verify(cd, hdr, *vk, keyslot); + + if (r < 0) { + crypt_free_volume_key(*vk); + *vk = NULL; + } + + crypt_volume_key_set_id(*vk, r); + + return r < 0 ? r : keyslot; +} + +static int LUKS2_open_and_verify_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int digest, + const char *password, + size_t password_len, + struct volume_key **vk) +{ + const keyslot_handler *h; + int r; + + if (!(h = LUKS2_keyslot_handler(cd, keyslot))) + return -ENOENT; + + r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot)); + if (r) { + log_dbg(cd, "Keyslot %d validation failed.", keyslot); + return r; + } + + r = _keyslot_for_digest(hdr, keyslot, digest); + if (r) { + if (r == -ENOENT) + log_dbg(cd, "Keyslot %d unusable for digest %d.", keyslot, digest); + return r; + } + + return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk); +} + +static int LUKS2_open_and_verify(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int segment, + const char *password, + size_t password_len, + struct volume_key **vk) +{ + const keyslot_handler *h; + int r; + + if (!(h = LUKS2_keyslot_handler(cd, keyslot))) + return -ENOENT; + + r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot)); + if (r) { + log_dbg(cd, "Keyslot %d validation failed.", keyslot); + return r; + } + + r = LUKS2_keyslot_for_segment(hdr, keyslot, segment); + if (r) { + if (r == -ENOENT) + log_dbg(cd, "Keyslot %d unusable for segment %d.", keyslot, segment); + return r; + } + + return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk); +} + +static int LUKS2_keyslot_open_priority_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, + crypt_keyslot_priority priority, + const char *password, + size_t password_len, + int digest, + struct volume_key **vk) +{ + json_object *jobj_keyslots, *jobj; + crypt_keyslot_priority slot_priority; + int keyslot, r = -ENOENT; + + json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); + + json_object_object_foreach(jobj_keyslots, slot, val) { + if (!json_object_object_get_ex(val, "priority", &jobj)) + slot_priority = CRYPT_SLOT_PRIORITY_NORMAL; + else + slot_priority = json_object_get_int(jobj); + + keyslot = atoi(slot); + if (slot_priority != priority) { + log_dbg(cd, "Keyslot %d priority %d != %d (required), skipped.", + keyslot, slot_priority, priority); + continue; + } + + r = LUKS2_open_and_verify_by_digest(cd, hdr, keyslot, digest, password, password_len, vk); + + /* Do not retry for errors that are no -EPERM or -ENOENT, + former meaning password wrong, latter key slot unusable for segment */ + if ((r != -EPERM) && (r != -ENOENT)) + break; + } + + return r; +} + +static int LUKS2_keyslot_open_priority(struct crypt_device *cd, + struct luks2_hdr *hdr, + crypt_keyslot_priority priority, + const char *password, + size_t password_len, + int segment, + struct volume_key **vk) +{ + json_object *jobj_keyslots, *jobj; + crypt_keyslot_priority slot_priority; + int keyslot, r = -ENOENT; + + json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); + + json_object_object_foreach(jobj_keyslots, slot, val) { + if (!json_object_object_get_ex(val, "priority", &jobj)) + slot_priority = CRYPT_SLOT_PRIORITY_NORMAL; + else + slot_priority = json_object_get_int(jobj); + + keyslot = atoi(slot); + if (slot_priority != priority) { + log_dbg(cd, "Keyslot %d priority %d != %d (required), skipped.", + keyslot, slot_priority, priority); + continue; + } + + r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk); + + /* Do not retry for errors that are no -EPERM or -ENOENT, + former meaning password wrong, latter key slot unusable for segment */ + if ((r != -EPERM) && (r != -ENOENT)) + break; + } + + return r; +} + +static int LUKS2_keyslot_open_by_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int digest, + const char *password, + size_t password_len, + struct volume_key **vk) +{ + int r_prio, r = -EINVAL; + + if (digest < 0) + return r; + + if (keyslot == CRYPT_ANY_SLOT) { + r_prio = LUKS2_keyslot_open_priority_digest(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER, + password, password_len, digest, vk); + if (r_prio >= 0) + r = r_prio; + else if (r_prio != -EPERM && r_prio != -ENOENT) + r = r_prio; + else + r = LUKS2_keyslot_open_priority_digest(cd, hdr, CRYPT_SLOT_PRIORITY_NORMAL, + password, password_len, digest, vk); + /* Prefer password wrong to no entry from priority slot */ + if (r_prio == -EPERM && r == -ENOENT) + r = r_prio; + } else + r = LUKS2_open_and_verify_by_digest(cd, hdr, keyslot, digest, password, password_len, vk); + + return r; +} + +int LUKS2_keyslot_open_all_segments(struct crypt_device *cd, + int keyslot_old, + int keyslot_new, + const char *password, + size_t password_len, + struct volume_key **vks) +{ + struct volume_key *vk = NULL; + int digest_old, digest_new, r = -EINVAL; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + digest_old = LUKS2_reencrypt_digest_old(hdr); + if (digest_old >= 0) { + log_dbg(cd, "Trying to unlock volume key (digest: %d) using keyslot %d.", digest_old, keyslot_old); + r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_old, digest_old, password, password_len, &vk); + if (r < 0) + goto out; + crypt_volume_key_add_next(vks, vk); + } + + digest_new = LUKS2_reencrypt_digest_new(hdr); + if (digest_new >= 0 && digest_old != digest_new) { + log_dbg(cd, "Trying to unlock volume key (digest: %d) using keyslot %d.", digest_new, keyslot_new); + r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_new, digest_new, password, password_len, &vk); + if (r < 0) + goto out; + crypt_volume_key_add_next(vks, vk); + } +out: + if (r < 0) { + crypt_free_volume_key(*vks); + *vks = NULL; + + if (r == -ENOMEM) + log_err(cd, _("Not enough available memory to open a keyslot.")); + else if (r != -EPERM) + log_err(cd, _("Keyslot open failed.")); + } + return r; +} + +int LUKS2_keyslot_open(struct crypt_device *cd, + int keyslot, + int segment, + const char *password, + size_t password_len, + struct volume_key **vk) +{ + struct luks2_hdr *hdr; + int r_prio, r = -EINVAL; + + hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + if (keyslot == CRYPT_ANY_SLOT) { + r_prio = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER, + password, password_len, segment, vk); + if (r_prio >= 0) + r = r_prio; + else if (r_prio != -EPERM && r_prio != -ENOENT) + r = r_prio; + else + r = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_NORMAL, + password, password_len, segment, vk); + /* Prefer password wrong to no entry from priority slot */ + if (r_prio == -EPERM && r == -ENOENT) + r = r_prio; + } else + r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk); + + if (r < 0) { + if (r == -ENOMEM) + log_err(cd, _("Not enough available memory to open a keyslot.")); + else if (r != -EPERM) + log_err(cd, _("Keyslot open failed.")); + } + + return r; +} + +int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const struct crypt_params_reencrypt *params) +{ + const keyslot_handler *h; + int r; + + if (keyslot == CRYPT_ANY_SLOT) + return -EINVAL; + + /* FIXME: find keyslot by type */ + h = LUKS2_keyslot_handler_type(cd, "reencrypt"); + if (!h) + return -EINVAL; + + r = reenc_keyslot_alloc(cd, hdr, keyslot, params); + if (r < 0) + return r; + + r = LUKS2_keyslot_priority_set(cd, hdr, keyslot, CRYPT_SLOT_PRIORITY_IGNORE, 0); + if (r < 0) + return r; + + r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot)); + if (r) { + log_dbg(cd, "Keyslot validation failed."); + return r; + } + + if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN)) + return -EINVAL; + + return 0; +} + +int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const void *buffer, + size_t buffer_length) +{ + const keyslot_handler *h; + int r; + + if (!(h = LUKS2_keyslot_handler(cd, keyslot)) || strcmp(h->name, "reencrypt")) + return -EINVAL; + + r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot)); + if (r) { + log_dbg(cd, "Keyslot validation failed."); + return r; + } + + return h->store(cd, keyslot, NULL, 0, + buffer, buffer_length); +} + +int LUKS2_keyslot_store(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const char *password, + size_t password_len, + const struct volume_key *vk, + const struct luks2_keyslot_params *params) +{ + const keyslot_handler *h; + int r; + + if (keyslot == CRYPT_ANY_SLOT) + return -EINVAL; + + if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) { + /* Try to allocate default and empty keyslot type */ + h = LUKS2_keyslot_handler_type(cd, "luks2"); + if (!h) + return -EINVAL; + + r = h->alloc(cd, keyslot, vk->keylength, params); + if (r) + return r; + } else { + if (!(h = LUKS2_keyslot_handler(cd, keyslot))) + return -EINVAL; + + r = h->update(cd, keyslot, params); + if (r) { + log_dbg(cd, "Failed to update keyslot %d json.", keyslot); + return r; + } + } + + r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot)); + if (r) { + log_dbg(cd, "Keyslot validation failed."); + return r; + } + + if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN)) + return -EINVAL; + + return h->store(cd, keyslot, password, password_len, + vk->key, vk->keylength); +} + +int LUKS2_keyslot_wipe(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + int wipe_area_only) +{ + struct device *device = crypt_metadata_device(cd); + uint64_t area_offset, area_length; + int r; + json_object *jobj_keyslot, *jobj_keyslots; + const keyslot_handler *h; + + h = LUKS2_keyslot_handler(cd, keyslot); + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots)) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -ENOENT; + + if (wipe_area_only) + log_dbg(cd, "Wiping keyslot %d area only.", keyslot); + + r = LUKS2_device_write_lock(cd, hdr, device); + if (r) + return r; + + /* secure deletion of possible key material in keyslot area */ + r = crypt_keyslot_area(cd, keyslot, &area_offset, &area_length); + if (r && r != -ENOENT) + goto out; + + if (!r) { + r = crypt_wipe_device(cd, device, CRYPT_WIPE_SPECIAL, area_offset, + area_length, area_length, NULL, NULL); + if (r) { + if (r == -EACCES) { + log_err(cd, _("Cannot write to device %s, permission denied."), + device_path(device)); + r = -EINVAL; + } else + log_err(cd, _("Cannot wipe device %s."), device_path(device)); + goto out; + } + } + + if (wipe_area_only) + goto out; + + /* Slot specific wipe */ + if (h) { + r = h->wipe(cd, keyslot); + if (r < 0) + goto out; + } else + log_dbg(cd, "Wiping keyslot %d without specific-slot handler loaded.", keyslot); + + json_object_object_del_by_uint(jobj_keyslots, keyslot); + + r = LUKS2_hdr_write(cd, hdr); +out: + device_write_unlock(cd, crypt_metadata_device(cd)); + return r; +} + +int LUKS2_keyslot_dump(struct crypt_device *cd, int keyslot) +{ + const keyslot_handler *h; + + if (!(h = LUKS2_keyslot_handler(cd, keyslot))) + return -EINVAL; + + return h->dump(cd, keyslot); +} + +crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd, + struct luks2_hdr *hdr, int keyslot) +{ + json_object *jobj_keyslot, *jobj_priority; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return CRYPT_SLOT_PRIORITY_INVALID; + + if (!json_object_object_get_ex(jobj_keyslot, "priority", &jobj_priority)) + return CRYPT_SLOT_PRIORITY_NORMAL; + + return json_object_get_int(jobj_priority); +} + +int LUKS2_keyslot_priority_set(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, crypt_keyslot_priority priority, int commit) +{ + json_object *jobj_keyslot; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -EINVAL; + + if (priority == CRYPT_SLOT_PRIORITY_NORMAL) + json_object_object_del(jobj_keyslot, "priority"); + else + json_object_object_add(jobj_keyslot, "priority", json_object_new_int(priority)); + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +int placeholder_keyslot_alloc(struct crypt_device *cd, + int keyslot, + uint64_t area_offset, + uint64_t area_length, + size_t volume_key_len) +{ + struct luks2_hdr *hdr; + json_object *jobj_keyslots, *jobj_keyslot, *jobj_area; + + log_dbg(cd, "Allocating placeholder keyslot %d for LUKS1 down conversion.", keyslot); + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX) + return -EINVAL; + + if (LUKS2_get_keyslot_jobj(hdr, keyslot)) + return -EINVAL; + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots)) + return -EINVAL; + + jobj_keyslot = json_object_new_object(); + json_object_object_add(jobj_keyslot, "type", json_object_new_string("placeholder")); + /* + * key_size = -1 makes placeholder keyslot impossible to pass validation. + * It's a safeguard against accidentally storing temporary conversion + * LUKS2 header. + */ + json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(-1)); + + /* Area object */ + jobj_area = json_object_new_object(); + json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset)); + json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length)); + json_object_object_add(jobj_keyslot, "area", jobj_area); + + json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot); + + return 0; +} + +static unsigned LUKS2_get_keyslot_digests_count(json_object *hdr_jobj, int keyslot) +{ + char num[16]; + json_object *jobj_digests, *jobj_keyslots; + unsigned count = 0; + + if (!json_object_object_get_ex(hdr_jobj, "digests", &jobj_digests)) + return 0; + + if (snprintf(num, sizeof(num), "%u", keyslot) < 0) + return 0; + + json_object_object_foreach(jobj_digests, key, val) { + UNUSED(key); + json_object_object_get_ex(val, "keyslots", &jobj_keyslots); + if (LUKS2_array_jobj(jobj_keyslots, num)) + count++; + } + + return count; +} + +/* run only on header that passed basic format validation */ +int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj) +{ + const keyslot_handler *h; + int keyslot; + json_object *jobj_keyslots, *jobj_type; + + if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) + return -EINVAL; + + json_object_object_foreach(jobj_keyslots, slot, val) { + keyslot = atoi(slot); + json_object_object_get_ex(val, "type", &jobj_type); + h = LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj_type)); + if (!h) + continue; + if (h->validate && h->validate(cd, val)) { + log_dbg(cd, "Keyslot type %s validation failed on keyslot %d.", h->name, keyslot); + return -EINVAL; + } + + if (!strcmp(h->name, "luks2") && LUKS2_get_keyslot_digests_count(hdr_jobj, keyslot) != 1) { + log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot); + return -EINVAL; + } + } + + return 0; +} + +void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_keyslots) +{ + const keyslot_handler *h; + json_object *jobj_type; + + json_object_object_foreach(jobj_keyslots, slot, val) { + UNUSED(slot); + if (!json_object_is_type(val, json_type_object) || + !json_object_object_get_ex(val, "type", &jobj_type) || + !json_object_is_type(jobj_type, json_type_string)) + continue; + + h = LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj_type)); + if (h && h->repair) + h->repair(cd, val); + } +} + +/* assumes valid header */ +int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type) +{ + int i; + json_object *jobj_keyslot, *jobj_type; + + if (!type) + return -EINVAL; + + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, i); + if (!jobj_keyslot) + continue; + + json_object_object_get_ex(jobj_keyslot, "type", &jobj_type); + if (!strcmp(json_object_get_string(jobj_type), type)) + return i; + } + + return -ENOENT; +} diff --git a/lib/luks2/luks2_keyslot_luks2.c b/lib/luks2/luks2_keyslot_luks2.c new file mode 100644 index 0000000..156f0c1 --- /dev/null +++ b/lib/luks2/luks2_keyslot_luks2.c @@ -0,0 +1,785 @@ +/* + * LUKS - Linux Unified Key Setup v2, LUKS2 type keyslot handler + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +/* FIXME: move keyslot encryption to crypto backend */ +#include "../luks1/af.h" + +#define LUKS_SALTSIZE 32 +#define LUKS_SLOT_ITERATIONS_MIN 1000 +#define LUKS_STRIPES 4000 + +/* Serialize memory-hard keyslot access: optional workaround for parallel processing */ +#define MIN_MEMORY_FOR_SERIALIZE_LOCK_KB 32*1024 /* 32MB */ + +static int luks2_encrypt_to_storage(char *src, size_t srcLength, + const char *cipher, const char *cipher_mode, + struct volume_key *vk, unsigned int sector, + struct crypt_device *cd) +{ +#ifndef ENABLE_AF_ALG /* Support for old kernel without Crypto API */ + return LUKS_encrypt_to_storage(src, srcLength, cipher, cipher_mode, vk, sector, cd); +#else + struct crypt_storage *s; + int devfd, r; + struct device *device = crypt_metadata_device(cd); + + /* Only whole sector writes supported */ + if (MISALIGNED_512(srcLength)) + return -EINVAL; + + /* Encrypt buffer */ + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); + if (r) { + log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode); + return r; + } + + r = crypt_storage_encrypt(s, 0, srcLength, src); + crypt_storage_destroy(s); + if (r) { + log_err(cd, _("IO error while encrypting keyslot.")); + return r; + } + + devfd = device_open_locked(cd, device, O_RDWR); + if (devfd >= 0) { + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), src, + srcLength, sector * SECTOR_SIZE) < 0) + r = -EIO; + else + r = 0; + + device_sync(cd, device); + } else + r = -EIO; + + if (r) + log_err(cd, _("IO error while encrypting keyslot.")); + + return r; +#endif +} + +static int luks2_decrypt_from_storage(char *dst, size_t dstLength, + const char *cipher, const char *cipher_mode, struct volume_key *vk, + unsigned int sector, struct crypt_device *cd) +{ + struct device *device = crypt_metadata_device(cd); +#ifndef ENABLE_AF_ALG /* Support for old kernel without Crypto API */ + int r = device_read_lock(cd, device); + if (r) { + log_err(cd, _("Failed to acquire read lock on device %s."), device_path(device)); + return r; + } + r = LUKS_decrypt_from_storage(dst, dstLength, cipher, cipher_mode, vk, sector, cd); + device_read_unlock(cd, crypt_metadata_device(cd)); + return r; +#else + struct crypt_storage *s; + int devfd, r; + + /* Only whole sector writes supported */ + if (MISALIGNED_512(dstLength)) + return -EINVAL; + + r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength); + if (r) { + log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode); + return r; + } + + r = device_read_lock(cd, device); + if (r) { + log_err(cd, _("Failed to acquire read lock on device %s."), + device_path(device)); + crypt_storage_destroy(s); + return r; + } + + devfd = device_open_locked(cd, device, O_RDONLY); + if (devfd >= 0) { + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), dst, + dstLength, sector * SECTOR_SIZE) < 0) + r = -EIO; + else + r = 0; + } else + r = -EIO; + + device_read_unlock(cd, device); + + /* Decrypt buffer */ + if (!r) + r = crypt_storage_decrypt(s, 0, dstLength, dst); + else + log_err(cd, _("IO error while decrypting keyslot.")); + + crypt_storage_destroy(s); + return r; +#endif +} + +static int luks2_keyslot_get_pbkdf_params(json_object *jobj_keyslot, + struct crypt_pbkdf_type *pbkdf, char *salt) +{ + json_object *jobj_kdf, *jobj1, *jobj2; + size_t salt_len; + + if (!jobj_keyslot || !pbkdf) + return -EINVAL; + + memset(pbkdf, 0, sizeof(*pbkdf)); + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf)) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_kdf, "type", &jobj1)) + return -EINVAL; + pbkdf->type = json_object_get_string(jobj1); + if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) { + if (!json_object_object_get_ex(jobj_kdf, "hash", &jobj2)) + return -EINVAL; + pbkdf->hash = json_object_get_string(jobj2); + if (!json_object_object_get_ex(jobj_kdf, "iterations", &jobj2)) + return -EINVAL; + pbkdf->iterations = json_object_get_int(jobj2); + pbkdf->max_memory_kb = 0; + pbkdf->parallel_threads = 0; + } else { + if (!json_object_object_get_ex(jobj_kdf, "time", &jobj2)) + return -EINVAL; + pbkdf->iterations = json_object_get_int(jobj2); + if (!json_object_object_get_ex(jobj_kdf, "memory", &jobj2)) + return -EINVAL; + pbkdf->max_memory_kb = json_object_get_int(jobj2); + if (!json_object_object_get_ex(jobj_kdf, "cpus", &jobj2)) + return -EINVAL; + pbkdf->parallel_threads = json_object_get_int(jobj2); + } + + if (!json_object_object_get_ex(jobj_kdf, "salt", &jobj2)) + return -EINVAL; + salt_len = LUKS_SALTSIZE; + if (!base64_decode(json_object_get_string(jobj2), + json_object_get_string_len(jobj2), + salt, &salt_len)) + return -EINVAL; + if (salt_len != LUKS_SALTSIZE) + return -EINVAL; + + return 0; +} + +static int luks2_keyslot_set_key(struct crypt_device *cd, + json_object *jobj_keyslot, + const char *password, size_t passwordLen, + const char *volume_key, size_t volume_key_len) +{ + struct volume_key *derived_key; + char salt[LUKS_SALTSIZE], cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN]; + char *AfKey = NULL; + const char *af_hash = NULL; + size_t AFEKSize, keyslot_key_len; + json_object *jobj2, *jobj_kdf, *jobj_af, *jobj_area; + uint64_t area_offset; + struct crypt_pbkdf_type pbkdf; + int r; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) || + !json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + /* prevent accidental volume key size change after allocation */ + if (!json_object_object_get_ex(jobj_keyslot, "key_size", &jobj2)) + return -EINVAL; + if (json_object_get_int(jobj2) != (int)volume_key_len) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_area, "offset", &jobj2)) + return -EINVAL; + area_offset = crypt_jobj_get_uint64(jobj2); + + if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2)) + return -EINVAL; + r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode); + if (r < 0) + return r; + + if (!json_object_object_get_ex(jobj_area, "key_size", &jobj2)) + return -EINVAL; + keyslot_key_len = json_object_get_int(jobj2); + + if (!json_object_object_get_ex(jobj_af, "hash", &jobj2)) + return -EINVAL; + af_hash = json_object_get_string(jobj2); + + if (luks2_keyslot_get_pbkdf_params(jobj_keyslot, &pbkdf, salt)) + return -EINVAL; + + /* + * Allocate derived key storage. + */ + derived_key = crypt_alloc_volume_key(keyslot_key_len, NULL); + if (!derived_key) + return -ENOMEM; + /* + * Calculate keyslot content, split and store it to keyslot area. + */ + r = crypt_pbkdf(pbkdf.type, pbkdf.hash, password, passwordLen, + salt, LUKS_SALTSIZE, + derived_key->key, derived_key->keylength, + pbkdf.iterations, pbkdf.max_memory_kb, + pbkdf.parallel_threads); + if (r < 0) { + crypt_free_volume_key(derived_key); + return r; + } + + // FIXME: verity key_size to AFEKSize + AFEKSize = AF_split_sectors(volume_key_len, LUKS_STRIPES) * SECTOR_SIZE; + AfKey = crypt_safe_alloc(AFEKSize); + if (!AfKey) { + crypt_free_volume_key(derived_key); + return -ENOMEM; + } + + r = AF_split(cd, volume_key, AfKey, volume_key_len, LUKS_STRIPES, af_hash); + + if (r == 0) { + log_dbg(cd, "Updating keyslot area [0x%04x].", (unsigned)area_offset); + /* FIXME: sector_offset should be size_t, fix LUKS_encrypt... accordingly */ + r = luks2_encrypt_to_storage(AfKey, AFEKSize, cipher, cipher_mode, + derived_key, (unsigned)(area_offset / SECTOR_SIZE), cd); + } + + crypt_safe_free(AfKey); + crypt_free_volume_key(derived_key); + if (r < 0) + return r; + + return 0; +} + +static int luks2_keyslot_get_key(struct crypt_device *cd, + json_object *jobj_keyslot, + const char *password, size_t passwordLen, + char *volume_key, size_t volume_key_len) +{ + struct volume_key *derived_key; + struct crypt_pbkdf_type pbkdf; + char *AfKey; + size_t AFEKSize; + const char *af_hash = NULL; + char salt[LUKS_SALTSIZE], cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN]; + json_object *jobj2, *jobj_af, *jobj_area; + uint64_t area_offset; + size_t keyslot_key_len; + bool try_serialize_lock = false; + int r; + + if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + if (luks2_keyslot_get_pbkdf_params(jobj_keyslot, &pbkdf, salt)) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_af, "hash", &jobj2)) + return -EINVAL; + af_hash = json_object_get_string(jobj2); + + if (!json_object_object_get_ex(jobj_area, "offset", &jobj2)) + return -EINVAL; + area_offset = crypt_jobj_get_uint64(jobj2); + + if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2)) + return -EINVAL; + r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode); + if (r < 0) + return r; + + if (!json_object_object_get_ex(jobj_area, "key_size", &jobj2)) + return -EINVAL; + keyslot_key_len = json_object_get_int(jobj2); + + /* + * If requested, serialize unlocking for memory-hard KDF. Usually NOOP. + */ + if (pbkdf.max_memory_kb > MIN_MEMORY_FOR_SERIALIZE_LOCK_KB) + try_serialize_lock = true; + if (try_serialize_lock && crypt_serialize_lock(cd)) + return -EINVAL; + /* + * Allocate derived key storage space. + */ + derived_key = crypt_alloc_volume_key(keyslot_key_len, NULL); + if (!derived_key) + return -ENOMEM; + + AFEKSize = AF_split_sectors(volume_key_len, LUKS_STRIPES) * SECTOR_SIZE; + AfKey = crypt_safe_alloc(AFEKSize); + if (!AfKey) { + crypt_free_volume_key(derived_key); + return -ENOMEM; + } + /* + * Calculate derived key, decrypt keyslot content and merge it. + */ + r = crypt_pbkdf(pbkdf.type, pbkdf.hash, password, passwordLen, + salt, LUKS_SALTSIZE, + derived_key->key, derived_key->keylength, + pbkdf.iterations, pbkdf.max_memory_kb, + pbkdf.parallel_threads); + + if (try_serialize_lock) + crypt_serialize_unlock(cd); + + if (r == 0) { + log_dbg(cd, "Reading keyslot area [0x%04x].", (unsigned)area_offset); + /* FIXME: sector_offset should be size_t, fix LUKS_decrypt... accordingly */ + r = luks2_decrypt_from_storage(AfKey, AFEKSize, cipher, cipher_mode, + derived_key, (unsigned)(area_offset / SECTOR_SIZE), cd); + } + + if (r == 0) + r = AF_merge(cd, AfKey, volume_key, volume_key_len, LUKS_STRIPES, af_hash); + + crypt_free_volume_key(derived_key); + crypt_safe_free(AfKey); + + return r; +} + +/* + * currently we support update of only: + * + * - af hash function + * - kdf params + */ +static int luks2_keyslot_update_json(struct crypt_device *cd, + json_object *jobj_keyslot, + const struct luks2_keyslot_params *params) +{ + const struct crypt_pbkdf_type *pbkdf; + json_object *jobj_af, *jobj_area, *jobj_kdf; + char salt[LUKS_SALTSIZE], *salt_base64 = NULL; + int r; + + /* jobj_keyslot is not yet validated */ + + if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + /* update area encryption parameters */ + json_object_object_add(jobj_area, "encryption", json_object_new_string(params->area.raw.encryption)); + json_object_object_add(jobj_area, "key_size", json_object_new_int(params->area.raw.key_size)); + + pbkdf = crypt_get_pbkdf_type(cd); + if (!pbkdf) + return -EINVAL; + + r = crypt_benchmark_pbkdf_internal(cd, CONST_CAST(struct crypt_pbkdf_type *)pbkdf, params->area.raw.key_size); + if (r < 0) + return r; + + /* refresh whole 'kdf' object */ + jobj_kdf = json_object_new_object(); + if (!jobj_kdf) + return -ENOMEM; + json_object_object_add(jobj_kdf, "type", json_object_new_string(pbkdf->type)); + if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) { + json_object_object_add(jobj_kdf, "hash", json_object_new_string(pbkdf->hash)); + json_object_object_add(jobj_kdf, "iterations", json_object_new_int(pbkdf->iterations)); + } else { + json_object_object_add(jobj_kdf, "time", json_object_new_int(pbkdf->iterations)); + json_object_object_add(jobj_kdf, "memory", json_object_new_int(pbkdf->max_memory_kb)); + json_object_object_add(jobj_kdf, "cpus", json_object_new_int(pbkdf->parallel_threads)); + } + json_object_object_add(jobj_keyslot, "kdf", jobj_kdf); + + /* + * Regenerate salt and add it in 'kdf' object + */ + r = crypt_random_get(cd, salt, LUKS_SALTSIZE, CRYPT_RND_SALT); + if (r < 0) + return r; + base64_encode_alloc(salt, LUKS_SALTSIZE, &salt_base64); + if (!salt_base64) + return -ENOMEM; + json_object_object_add(jobj_kdf, "salt", json_object_new_string(salt_base64)); + free(salt_base64); + + /* update 'af' hash */ + json_object_object_add(jobj_af, "hash", json_object_new_string(params->af.luks1.hash)); + + JSON_DBG(cd, jobj_keyslot, "Keyslot JSON:"); + return 0; +} + +static int luks2_keyslot_alloc(struct crypt_device *cd, + int keyslot, + size_t volume_key_len, + const struct luks2_keyslot_params *params) +{ + struct luks2_hdr *hdr; + uint64_t area_offset, area_length; + json_object *jobj_keyslots, *jobj_keyslot, *jobj_af, *jobj_area; + int r; + + log_dbg(cd, "Trying to allocate LUKS2 keyslot %d.", keyslot); + + if (!params || params->area_type != LUKS2_KEYSLOT_AREA_RAW || + params->af_type != LUKS2_KEYSLOT_AF_LUKS1) { + log_dbg(cd, "Invalid LUKS2 keyslot parameters."); + return -EINVAL; + } + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + if (keyslot == CRYPT_ANY_SLOT) + keyslot = LUKS2_keyslot_find_empty(hdr); + + if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX) + return -ENOMEM; + + if (LUKS2_get_keyslot_jobj(hdr, keyslot)) { + log_dbg(cd, "Cannot modify already active keyslot %d.", keyslot); + return -EINVAL; + } + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots)) + return -EINVAL; + + r = LUKS2_find_area_gap(cd, hdr, volume_key_len, &area_offset, &area_length); + if (r < 0) { + log_err(cd, _("No space for new keyslot.")); + return r; + } + + jobj_keyslot = json_object_new_object(); + json_object_object_add(jobj_keyslot, "type", json_object_new_string("luks2")); + json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(volume_key_len)); + + /* AF object */ + jobj_af = json_object_new_object(); + json_object_object_add(jobj_af, "type", json_object_new_string("luks1")); + json_object_object_add(jobj_af, "stripes", json_object_new_int(params->af.luks1.stripes)); + json_object_object_add(jobj_keyslot, "af", jobj_af); + + /* Area object */ + jobj_area = json_object_new_object(); + json_object_object_add(jobj_area, "type", json_object_new_string("raw")); + json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset)); + json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length)); + json_object_object_add(jobj_keyslot, "area", jobj_area); + + json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot); + + r = luks2_keyslot_update_json(cd, jobj_keyslot, params); + + if (!r && LUKS2_check_json_size(cd, hdr)) { + log_dbg(cd, "Not enough space in header json area for new keyslot."); + r = -ENOSPC; + } + + if (r) + json_object_object_del_by_uint(jobj_keyslots, keyslot); + + return r; +} + +static int luks2_keyslot_open(struct crypt_device *cd, + int keyslot, + const char *password, + size_t password_len, + char *volume_key, + size_t volume_key_len) +{ + struct luks2_hdr *hdr; + json_object *jobj_keyslot; + + log_dbg(cd, "Trying to open LUKS2 keyslot %d.", keyslot); + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -EINVAL; + + return luks2_keyslot_get_key(cd, jobj_keyslot, + password, password_len, + volume_key, volume_key_len); +} + +/* + * This function must not modify json. + * It's called after luks2 keyslot validation. + */ +static int luks2_keyslot_store(struct crypt_device *cd, + int keyslot, + const char *password, + size_t password_len, + const char *volume_key, + size_t volume_key_len) +{ + struct luks2_hdr *hdr; + json_object *jobj_keyslot; + int r; + + log_dbg(cd, "Calculating attributes for LUKS2 keyslot %d.", keyslot); + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -EINVAL; + + r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd)); + if(r) + return r; + + r = luks2_keyslot_set_key(cd, jobj_keyslot, + password, password_len, + volume_key, volume_key_len); + if (!r) + r = LUKS2_hdr_write(cd, hdr); + + device_write_unlock(cd, crypt_metadata_device(cd)); + + return r < 0 ? r : keyslot; +} + +static int luks2_keyslot_wipe(struct crypt_device *cd, int keyslot) +{ + struct luks2_hdr *hdr; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + /* Remove any reference of deleted keyslot from digests and tokens */ + LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0); + LUKS2_token_assign(cd, hdr, keyslot, CRYPT_ANY_TOKEN, 0, 0); + + return 0; +} + +static int luks2_keyslot_dump(struct crypt_device *cd, int keyslot) +{ + json_object *jobj_keyslot, *jobj1, *jobj_kdf, *jobj_af, *jobj_area; + + jobj_keyslot = LUKS2_get_keyslot_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), keyslot); + if (!jobj_keyslot) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) || + !json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + json_object_object_get_ex(jobj_area, "encryption", &jobj1); + log_std(cd, "\tCipher: %s\n", json_object_get_string(jobj1)); + + json_object_object_get_ex(jobj_area, "key_size", &jobj1); + log_std(cd, "\tCipher key: %u bits\n", crypt_jobj_get_uint32(jobj1) * 8); + + json_object_object_get_ex(jobj_kdf, "type", &jobj1); + log_std(cd, "\tPBKDF: %s\n", json_object_get_string(jobj1)); + + if (!strcmp(json_object_get_string(jobj1), CRYPT_KDF_PBKDF2)) { + json_object_object_get_ex(jobj_kdf, "hash", &jobj1); + log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1)); + + json_object_object_get_ex(jobj_kdf, "iterations", &jobj1); + log_std(cd, "\tIterations: %" PRIu64 "\n", crypt_jobj_get_uint64(jobj1)); + } else { + json_object_object_get_ex(jobj_kdf, "time", &jobj1); + log_std(cd, "\tTime cost: %" PRIu64 "\n", json_object_get_int64(jobj1)); + + json_object_object_get_ex(jobj_kdf, "memory", &jobj1); + log_std(cd, "\tMemory: %" PRIu64 "\n", json_object_get_int64(jobj1)); + + json_object_object_get_ex(jobj_kdf, "cpus", &jobj1); + log_std(cd, "\tThreads: %" PRIu64 "\n", json_object_get_int64(jobj1)); + } + json_object_object_get_ex(jobj_kdf, "salt", &jobj1); + log_std(cd, "\tSalt: "); + hexprint_base64(cd, jobj1, " ", " "); + + + json_object_object_get_ex(jobj_af, "stripes", &jobj1); + log_std(cd, "\tAF stripes: %u\n", json_object_get_int(jobj1)); + + json_object_object_get_ex(jobj_af, "hash", &jobj1); + log_std(cd, "\tAF hash: %s\n", json_object_get_string(jobj1)); + + json_object_object_get_ex(jobj_area, "offset", &jobj1); + log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1)); + + json_object_object_get_ex(jobj_area, "size", &jobj1); + log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1)); + + return 0; +} + +static int luks2_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot) +{ + json_object *jobj_kdf, *jobj_af, *jobj_area, *jobj1; + const char *type; + int count; + + if (!jobj_keyslot) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) || + !json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + + count = json_object_object_length(jobj_kdf); + + jobj1 = json_contains(cd, jobj_kdf, "", "kdf section", "type", json_type_string); + if (!jobj1) + return -EINVAL; + type = json_object_get_string(jobj1); + + if (!strcmp(type, CRYPT_KDF_PBKDF2)) { + if (count != 4 || /* type, salt, hash, iterations only */ + !json_contains(cd, jobj_kdf, "kdf type", type, "hash", json_type_string) || + !json_contains(cd, jobj_kdf, "kdf type", type, "iterations", json_type_int) || + !json_contains(cd, jobj_kdf, "kdf type", type, "salt", json_type_string)) + return -EINVAL; + } else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) { + if (count != 5 || /* type, salt, time, memory, cpus only */ + !json_contains(cd, jobj_kdf, "kdf type", type, "time", json_type_int) || + !json_contains(cd, jobj_kdf, "kdf type", type, "memory", json_type_int) || + !json_contains(cd, jobj_kdf, "kdf type", type, "cpus", json_type_int) || + !json_contains(cd, jobj_kdf, "kdf type", type, "salt", json_type_string)) + return -EINVAL; + } + + if (!json_object_object_get_ex(jobj_af, "type", &jobj1)) + return -EINVAL; + if (!strcmp(json_object_get_string(jobj1), "luks1")) { + if (!json_contains(cd, jobj_af, "", "luks1 af", "hash", json_type_string) || + !json_contains(cd, jobj_af, "", "luks1 af", "stripes", json_type_int)) + return -EINVAL; + } else + return -EINVAL; + + // FIXME check numbered + if (!json_object_object_get_ex(jobj_area, "type", &jobj1)) + return -EINVAL; + if (!strcmp(json_object_get_string(jobj1), "raw")) { + if (!json_contains(cd, jobj_area, "area", "raw type", "encryption", json_type_string) || + !json_contains(cd, jobj_area, "area", "raw type", "key_size", json_type_int) || + !json_contains(cd, jobj_area, "area", "raw type", "offset", json_type_string) || + !json_contains(cd, jobj_area, "area", "raw type", "size", json_type_string)) + return -EINVAL; + } else + return -EINVAL; + + return 0; +} + +static int luks2_keyslot_update(struct crypt_device *cd, + int keyslot, + const struct luks2_keyslot_params *params) +{ + struct luks2_hdr *hdr; + json_object *jobj_keyslot; + int r; + + log_dbg(cd, "Updating LUKS2 keyslot %d.", keyslot); + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -EINVAL; + + r = luks2_keyslot_update_json(cd, jobj_keyslot, params); + + if (!r && LUKS2_check_json_size(cd, hdr)) { + log_dbg(cd, "Not enough space in header json area for updated keyslot %d.", keyslot); + r = -ENOSPC; + } + + return r; +} + +static void luks2_keyslot_repair(struct crypt_device *cd, json_object *jobj_keyslot) +{ + const char *type; + json_object *jobj_kdf, *jobj_type; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) || + !json_object_is_type(jobj_kdf, json_type_object)) + return; + + if (!json_object_object_get_ex(jobj_kdf, "type", &jobj_type) || + !json_object_is_type(jobj_type, json_type_string)) + return; + + type = json_object_get_string(jobj_type); + + if (!strcmp(type, CRYPT_KDF_PBKDF2)) { + /* type, salt, hash, iterations only */ + json_object_object_foreach(jobj_kdf, key, val) { + UNUSED(val); + if (!strcmp(key, "type") || !strcmp(key, "salt") || + !strcmp(key, "hash") || !strcmp(key, "iterations")) + continue; + json_object_object_del(jobj_kdf, key); + } + } else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) { + /* type, salt, time, memory, cpus only */ + json_object_object_foreach(jobj_kdf, key, val) { + UNUSED(val); + if (!strcmp(key, "type") || !strcmp(key, "salt") || + !strcmp(key, "time") || !strcmp(key, "memory") || + !strcmp(key, "cpus")) + continue; + json_object_object_del(jobj_kdf, key); + } + } +} + +const keyslot_handler luks2_keyslot = { + .name = "luks2", + .alloc = luks2_keyslot_alloc, + .update = luks2_keyslot_update, + .open = luks2_keyslot_open, + .store = luks2_keyslot_store, + .wipe = luks2_keyslot_wipe, + .dump = luks2_keyslot_dump, + .validate = luks2_keyslot_validate, + .repair = luks2_keyslot_repair +}; diff --git a/lib/luks2/luks2_keyslot_reenc.c b/lib/luks2/luks2_keyslot_reenc.c new file mode 100644 index 0000000..b939467 --- /dev/null +++ b/lib/luks2/luks2_keyslot_reenc.c @@ -0,0 +1,336 @@ +/* + * LUKS - Linux Unified Key Setup v2, reencryption keyslot handler + * + * Copyright (C) 2016-2020, Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020, Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +static int reenc_keyslot_open(struct crypt_device *cd, + int keyslot, + const char *password, + size_t password_len, + char *volume_key, + size_t volume_key_len) +{ + return -ENOENT; +} + +int reenc_keyslot_alloc(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const struct crypt_params_reencrypt *params) +{ + int r; + json_object *jobj_keyslots, *jobj_keyslot, *jobj_area; + uint64_t area_offset, area_length; + + log_dbg(cd, "Allocating reencrypt keyslot %d.", keyslot); + + if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX) + return -ENOMEM; + + if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots)) + return -EINVAL; + + /* encryption doesn't require area (we shift data and backup will be available) */ + if (!params->data_shift) { + r = LUKS2_find_area_max_gap(cd, hdr, &area_offset, &area_length); + if (r < 0) + return r; + } else { /* we can't have keyslot w/o area...bug? */ + r = LUKS2_find_area_gap(cd, hdr, 1, &area_offset, &area_length); + if (r < 0) + return r; + } + + jobj_keyslot = json_object_new_object(); + if (!jobj_keyslot) + return -ENOMEM; + + jobj_area = json_object_new_object(); + + if (params->data_shift) { + json_object_object_add(jobj_area, "type", json_object_new_string("datashift")); + json_object_object_add(jobj_area, "shift_size", crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT)); + } else + /* except data shift protection, initial setting is irrelevant. Type can be changed during reencryption */ + json_object_object_add(jobj_area, "type", json_object_new_string("none")); + + json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset)); + json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length)); + + json_object_object_add(jobj_keyslot, "type", json_object_new_string("reencrypt")); + json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(1)); /* useless but mandatory */ + json_object_object_add(jobj_keyslot, "mode", json_object_new_string(crypt_reencrypt_mode_to_str(params->mode))); + if (params->direction == CRYPT_REENCRYPT_FORWARD) + json_object_object_add(jobj_keyslot, "direction", json_object_new_string("forward")); + else if (params->direction == CRYPT_REENCRYPT_BACKWARD) + json_object_object_add(jobj_keyslot, "direction", json_object_new_string("backward")); + else + return -EINVAL; + + json_object_object_add(jobj_keyslot, "area", jobj_area); + + json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot); + if (LUKS2_check_json_size(cd, hdr)) { + log_dbg(cd, "New keyslot too large to fit in free metadata space."); + json_object_object_del_by_uint(jobj_keyslots, keyslot); + return -ENOSPC; + } + + JSON_DBG(cd, hdr->jobj, "JSON:"); + + return 0; +} + +static int reenc_keyslot_store_data(struct crypt_device *cd, + json_object *jobj_keyslot, + const void *buffer, size_t buffer_len) +{ + int devfd, r; + json_object *jobj_area, *jobj_offset, *jobj_length; + uint64_t area_offset, area_length; + struct device *device = crypt_metadata_device(cd); + + if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) || + !json_object_object_get_ex(jobj_area, "offset", &jobj_offset) || + !json_object_object_get_ex(jobj_area, "size", &jobj_length)) + return -EINVAL; + + area_offset = crypt_jobj_get_uint64(jobj_offset); + area_length = crypt_jobj_get_uint64(jobj_length); + + if (!area_offset || !area_length || ((uint64_t)buffer_len > area_length)) + return -EINVAL; + + devfd = device_open_locked(cd, device, O_RDWR); + if (devfd >= 0) { + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), CONST_CAST(void *)buffer, + buffer_len, area_offset) < 0) + r = -EIO; + else + r = 0; + } else + r = -EINVAL; + + if (r) + log_err(cd, _("IO error while encrypting keyslot.")); + + return r; +} + +static int reenc_keyslot_store(struct crypt_device *cd, + int keyslot, + const char *password __attribute__((unused)), + size_t password_len __attribute__((unused)), + const char *buffer, + size_t buffer_len) +{ + struct luks2_hdr *hdr; + json_object *jobj_keyslot; + int r = 0; + + if (!cd || !buffer || !buffer_len) + return -EINVAL; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + log_dbg(cd, "Reencrypt keyslot %d store.", keyslot); + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return -EINVAL; + + r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd)); + if (r) + return r; + + r = reenc_keyslot_store_data(cd, jobj_keyslot, buffer, buffer_len); + if (r < 0) { + device_write_unlock(cd, crypt_metadata_device(cd)); + return r; + } + + r = LUKS2_hdr_write(cd, hdr); + + device_write_unlock(cd, crypt_metadata_device(cd)); + + return r < 0 ? r : keyslot; +} + +int reenc_keyslot_update(struct crypt_device *cd, + const struct luks2_reenc_context *rh) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_area_type; + struct luks2_hdr *hdr; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, rh->reenc_keyslot); + if (!jobj_keyslot) + return -EINVAL; + + json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); + json_object_object_get_ex(jobj_area, "type", &jobj_area_type); + + if (rh->rp.type == REENC_PROTECTION_CHECKSUM) { + log_dbg(cd, "Updating reencrypt keyslot for checksum protection."); + json_object_object_add(jobj_area, "type", json_object_new_string("checksum")); + json_object_object_add(jobj_area, "hash", json_object_new_string(rh->rp.p.csum.hash)); + json_object_object_add(jobj_area, "sector_size", json_object_new_int64(rh->alignment)); + } else if (rh->rp.type == REENC_PROTECTION_NONE) { + log_dbg(cd, "Updating reencrypt keyslot for none protection."); + json_object_object_add(jobj_area, "type", json_object_new_string("none")); + json_object_object_del(jobj_area, "hash"); + } else if (rh->rp.type == REENC_PROTECTION_JOURNAL) { + log_dbg(cd, "Updating reencrypt keyslot for journal protection."); + json_object_object_add(jobj_area, "type", json_object_new_string("journal")); + json_object_object_del(jobj_area, "hash"); + } else + log_dbg(cd, "No update of reencrypt keyslot needed."); + + return 0; +} + +static int reenc_keyslot_wipe(struct crypt_device *cd, int keyslot) +{ + return 0; +} + +static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_direction, *jobj_mode, *jobj_resilience, + *jobj1; + + jobj_keyslot = LUKS2_get_keyslot_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), keyslot); + if (!jobj_keyslot) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_keyslot, "direction", &jobj_direction) || + !json_object_object_get_ex(jobj_keyslot, "mode", &jobj_mode) || + !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) || + !json_object_object_get_ex(jobj_area, "type", &jobj_resilience)) + return -EINVAL; + + log_std(cd, "\t%-12s%s\n", "Mode:", json_object_get_string(jobj_mode)); + log_std(cd, "\t%-12s%s\n", "Direction:", json_object_get_string(jobj_direction)); + log_std(cd, "\t%-12s%s\n", "Resilience:", json_object_get_string(jobj_resilience)); + + if (!strcmp(json_object_get_string(jobj_resilience), "checksum")) { + json_object_object_get_ex(jobj_area, "hash", &jobj1); + log_std(cd, "\t%-12s%s\n", "Hash:", json_object_get_string(jobj1)); + json_object_object_get_ex(jobj_area, "sector_size", &jobj1); + log_std(cd, "\t%-12s%d [bytes]\n", "Hash data:", json_object_get_int(jobj1)); + } else if (!strcmp(json_object_get_string(jobj_resilience), "datashift")) { + json_object_object_get_ex(jobj_area, "shift_size", &jobj1); + log_std(cd, "\t%-12s%" PRIu64 "[bytes]\n", "Shift size:", crypt_jobj_get_uint64(jobj1)); + } + + json_object_object_get_ex(jobj_area, "offset", &jobj1); + log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1)); + + json_object_object_get_ex(jobj_area, "size", &jobj1); + log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1)); + + return 0; +} + +static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot) +{ + json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction; + const char *mode, *type, *direction; + uint32_t sector_size; + uint64_t shift_size; + + /* mode (string: encrypt,reencrypt,decrypt) + * direction (string:) + * area { + * type: (string: datashift, journal, checksum, none) + * hash: (string: checksum only) + * sector_size (uint32: checksum only) + * shift_size (uint64: datashift only) + * } + */ + + /* area and area type are validated in general validation code */ + if (!jobj_keyslot || !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) || + !json_object_object_get_ex(jobj_area, "type", &jobj_type)) + return -EINVAL; + + jobj_mode = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "mode", json_type_string); + jobj_direction = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "direction", json_type_string); + + if (!jobj_mode || !jobj_direction) + return -EINVAL; + + mode = json_object_get_string(jobj_mode); + type = json_object_get_string(jobj_type); + direction = json_object_get_string(jobj_direction); + + if (strcmp(mode, "reencrypt") && strcmp(mode, "encrypt") && + strcmp(mode, "decrypt")) { + log_dbg(cd, "Illegal reencrypt mode %s.", mode); + return -EINVAL; + } + + if (strcmp(direction, "forward") && strcmp(direction, "backward")) { + log_dbg(cd, "Illegal reencrypt direction %s.", direction); + return -EINVAL; + } + + if (!strcmp(type, "checksum")) { + jobj_hash = json_contains(cd, jobj_area, "type:checksum", "Keyslot area", "hash", json_type_string); + jobj_sector_size = json_contains(cd, jobj_area, "type:checksum", "Keyslot area", "sector_size", json_type_int); + if (!jobj_hash || !jobj_sector_size) + return -EINVAL; + if (!validate_json_uint32(jobj_sector_size)) + return -EINVAL; + sector_size = crypt_jobj_get_uint32(jobj_sector_size); + if (sector_size < SECTOR_SIZE || NOTPOW2(sector_size)) { + log_dbg(cd, "Invalid sector_size (%" PRIu32 ") for checksum resilience mode.", sector_size); + return -EINVAL; + } + } else if (!strcmp(type, "datashift")) { + if (!(jobj_shift_size = json_contains(cd, jobj_area, "type:datashift", "Keyslot area", "shift_size", json_type_string))) + return -EINVAL; + + shift_size = crypt_jobj_get_uint64(jobj_shift_size); + if (!shift_size) + return -EINVAL; + + if (MISALIGNED_512(shift_size)) { + log_dbg(cd, "Shift size field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE); + return -EINVAL; + } + } + + return 0; +} + +const keyslot_handler reenc_keyslot = { + .name = "reencrypt", + .open = reenc_keyslot_open, + .store = reenc_keyslot_store, /* initialization only or also per every chunk write */ + .wipe = reenc_keyslot_wipe, + .dump = reenc_keyslot_dump, + .validate = reenc_keyslot_validate +}; diff --git a/lib/luks2/luks2_luks1_convert.c b/lib/luks2/luks2_luks1_convert.c new file mode 100644 index 0000000..603c44d --- /dev/null +++ b/lib/luks2/luks2_luks1_convert.c @@ -0,0 +1,896 @@ +/* + * LUKS - Linux Unified Key Setup v2, LUKS1 conversion code + * + * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020 Ondrej Kozina + * Copyright (C) 2015-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" +#include "../luks1/luks.h" +#include "../luks1/af.h" + +int LUKS2_check_cipher(struct crypt_device *cd, + size_t keylength, + const char *cipher, + const char *cipher_mode) +{ + return LUKS_check_cipher(cd, keylength, cipher, cipher_mode); +} + +static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struct json_object **keyslot_object) +{ + char *base64_str, cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L]; + size_t base64_len; + struct json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area; + uint64_t offset, area_size, offs_a, offs_b, length; + + keyslot_obj = json_object_new_object(); + json_object_object_add(keyslot_obj, "type", json_object_new_string("luks2")); + json_object_object_add(keyslot_obj, "key_size", json_object_new_int64(hdr_v1->keyBytes)); + + /* KDF */ + jobj_kdf = json_object_new_object(); + json_object_object_add(jobj_kdf, "type", json_object_new_string(CRYPT_KDF_PBKDF2)); + json_object_object_add(jobj_kdf, "hash", json_object_new_string(hdr_v1->hashSpec)); + json_object_object_add(jobj_kdf, "iterations", json_object_new_int64(hdr_v1->keyblock[keyslot].passwordIterations)); + /* salt field */ + base64_len = base64_encode_alloc(hdr_v1->keyblock[keyslot].passwordSalt, LUKS_SALTSIZE, &base64_str); + if (!base64_str) { + json_object_put(keyslot_obj); + json_object_put(jobj_kdf); + if (!base64_len) + return -EINVAL; + return -ENOMEM; + } + field = json_object_new_string_len(base64_str, base64_len); + free(base64_str); + json_object_object_add(jobj_kdf, "salt", field); + json_object_object_add(keyslot_obj, "kdf", jobj_kdf); + + /* AF */ + jobj_af = json_object_new_object(); + json_object_object_add(jobj_af, "type", json_object_new_string("luks1")); + json_object_object_add(jobj_af, "hash", json_object_new_string(hdr_v1->hashSpec)); + /* stripes field ignored, fixed to LUKS_STRIPES (4000) */ + json_object_object_add(jobj_af, "stripes", json_object_new_int(4000)); + json_object_object_add(keyslot_obj, "af", jobj_af); + + /* Area */ + jobj_area = json_object_new_object(); + json_object_object_add(jobj_area, "type", json_object_new_string("raw")); + + /* encryption algorithm field */ + if (*hdr_v1->cipherMode != '\0') { + (void) snprintf(cipher, sizeof(cipher), "%s-%s", hdr_v1->cipherName, hdr_v1->cipherMode); + json_object_object_add(jobj_area, "encryption", json_object_new_string(cipher)); + } else + json_object_object_add(jobj_area, "encryption", json_object_new_string(hdr_v1->cipherName)); + + /* area */ + if (LUKS_keyslot_area(hdr_v1, 0, &offs_a, &length) || + LUKS_keyslot_area(hdr_v1, 1, &offs_b, &length) || + LUKS_keyslot_area(hdr_v1, keyslot, &offset, &length)) { + json_object_put(keyslot_obj); + json_object_put(jobj_area); + return -EINVAL; + } + area_size = offs_b - offs_a; + json_object_object_add(jobj_area, "key_size", json_object_new_int(hdr_v1->keyBytes)); + json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset)); + json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_size)); + json_object_object_add(keyslot_obj, "area", jobj_area); + + *keyslot_object = keyslot_obj; + return 0; +} + +static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_object **keyslots_object) +{ + int keyslot, r; + struct json_object *keyslot_obj, *field; + + keyslot_obj = json_object_new_object(); + if (!keyslot_obj) + return -ENOMEM; + + for (keyslot = 0; keyslot < LUKS_NUMKEYS; keyslot++) { + if (hdr_v1->keyblock[keyslot].active != LUKS_KEY_ENABLED) + continue; + r = json_luks1_keyslot(hdr_v1, keyslot, &field); + if (r) { + json_object_put(keyslot_obj); + return r; + } + json_object_object_add_by_uint(keyslot_obj, keyslot, field); + } + + *keyslots_object = keyslot_obj; + return 0; +} + +static int json_luks1_segment(const struct luks_phdr *hdr_v1, struct json_object **segment_object) +{ + const char *c; + char cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L]; + struct json_object *segment_obj, *field; + uint64_t number; + + segment_obj = json_object_new_object(); + if (!segment_obj) + return -ENOMEM; + + /* type field */ + field = json_object_new_string("crypt"); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "type", field); + + /* offset field */ + number = (uint64_t)hdr_v1->payloadOffset * SECTOR_SIZE; + + field = crypt_jobj_new_uint64(number); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "offset", field); + + /* iv_tweak field */ + field = json_object_new_string("0"); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "iv_tweak", field); + + /* length field */ + field = json_object_new_string("dynamic"); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "size", field); + + /* cipher field */ + if (*hdr_v1->cipherMode != '\0') { + (void) snprintf(cipher, sizeof(cipher), "%s-%s", hdr_v1->cipherName, hdr_v1->cipherMode); + c = cipher; + } else + c = hdr_v1->cipherName; + + field = json_object_new_string(c); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "encryption", field); + + /* block field */ + field = json_object_new_int(SECTOR_SIZE); + if (!field) { + json_object_put(segment_obj); + return -ENOMEM; + } + json_object_object_add(segment_obj, "sector_size", field); + + *segment_object = segment_obj; + return 0; +} + +static int json_luks1_segments(const struct luks_phdr *hdr_v1, struct json_object **segments_object) +{ + int r; + struct json_object *segments_obj, *field; + + segments_obj = json_object_new_object(); + if (!segments_obj) + return -ENOMEM; + + r = json_luks1_segment(hdr_v1, &field); + if (r) { + json_object_put(segments_obj); + return r; + } + json_object_object_add_by_uint(segments_obj, 0, field); + + *segments_object = segments_obj; + return 0; +} + +static int json_luks1_digest(const struct luks_phdr *hdr_v1, struct json_object **digest_object) +{ + char keyslot_str[2], *base64_str; + int ks; + size_t base64_len; + struct json_object *digest_obj, *array, *field; + + digest_obj = json_object_new_object(); + if (!digest_obj) + return -ENOMEM; + + /* type field */ + field = json_object_new_string("pbkdf2"); + if (!field) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "type", field); + + /* keyslots array */ + array = json_object_new_array(); + if (!array) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "keyslots", json_object_get(array)); + + for (ks = 0; ks < LUKS_NUMKEYS; ks++) { + if (hdr_v1->keyblock[ks].active != LUKS_KEY_ENABLED) + continue; + (void) snprintf(keyslot_str, sizeof(keyslot_str), "%d", ks); + + field = json_object_new_string(keyslot_str); + if (!field || json_object_array_add(array, field) < 0) { + json_object_put(field); + json_object_put(array); + json_object_put(digest_obj); + return -ENOMEM; + } + } + + json_object_put(array); + + /* segments array */ + array = json_object_new_array(); + if (!array) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "segments", json_object_get(array)); + + field = json_object_new_string("0"); + if (!field || json_object_array_add(array, field) < 0) { + json_object_put(field); + json_object_put(array); + json_object_put(digest_obj); + return -ENOMEM; + } + + json_object_put(array); + + /* hash field */ + field = json_object_new_string(hdr_v1->hashSpec); + if (!field) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "hash", field); + + /* salt field */ + base64_len = base64_encode_alloc(hdr_v1->mkDigestSalt, LUKS_SALTSIZE, &base64_str); + if (!base64_str) { + json_object_put(digest_obj); + if (!base64_len) + return -EINVAL; + return -ENOMEM; + } + + field = json_object_new_string_len(base64_str, base64_len); + free(base64_str); + if (!field) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "salt", field); + + /* digest field */ + base64_len = base64_encode_alloc(hdr_v1->mkDigest, LUKS_DIGESTSIZE, &base64_str); + if (!base64_str) { + json_object_put(digest_obj); + if (!base64_len) + return -EINVAL; + return -ENOMEM; + } + + field = json_object_new_string_len(base64_str, base64_len); + free(base64_str); + if (!field) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "digest", field); + + /* iterations field */ + field = json_object_new_int64(hdr_v1->mkDigestIterations); + if (!field) { + json_object_put(digest_obj); + return -ENOMEM; + } + json_object_object_add(digest_obj, "iterations", field); + + *digest_object = digest_obj; + return 0; +} + +static int json_luks1_digests(const struct luks_phdr *hdr_v1, struct json_object **digests_object) +{ + int r; + struct json_object *digests_obj, *field; + + digests_obj = json_object_new_object(); + if (!digests_obj) + return -ENOMEM; + + r = json_luks1_digest(hdr_v1, &field); + if (r) { + json_object_put(digests_obj); + return r; + } + json_object_object_add(digests_obj, "0", field); + + *digests_object = digests_obj; + return 0; +} + +static int json_luks1_object(struct luks_phdr *hdr_v1, struct json_object **luks1_object, uint64_t keyslots_size) +{ + int r; + struct json_object *luks1_obj, *field; + uint64_t json_size; + + luks1_obj = json_object_new_object(); + if (!luks1_obj) + return -ENOMEM; + + /* keyslots field */ + r = json_luks1_keyslots(hdr_v1, &field); + if (r) { + json_object_put(luks1_obj); + return r; + } + json_object_object_add(luks1_obj, "keyslots", field); + + /* tokens field */ + field = json_object_new_object(); + if (!field) { + json_object_put(luks1_obj); + return -ENOMEM; + } + json_object_object_add(luks1_obj, "tokens", field); + + /* segments field */ + r = json_luks1_segments(hdr_v1, &field); + if (r) { + json_object_put(luks1_obj); + return r; + } + json_object_object_add(luks1_obj, "segments", field); + + /* digests field */ + r = json_luks1_digests(hdr_v1, &field); + if (r) { + json_object_put(luks1_obj); + return r; + } + json_object_object_add(luks1_obj, "digests", field); + + /* config field */ + /* anything else? */ + field = json_object_new_object(); + if (!field) { + json_object_put(luks1_obj); + return -ENOMEM; + } + json_object_object_add(luks1_obj, "config", field); + + json_size = LUKS2_HDR_16K_LEN - LUKS2_HDR_BIN_LEN; + json_object_object_add(field, "json_size", crypt_jobj_new_uint64(json_size)); + keyslots_size -= (keyslots_size % 4096); + json_object_object_add(field, "keyslots_size", crypt_jobj_new_uint64(keyslots_size)); + + *luks1_object = luks1_obj; + return 0; +} + +static void move_keyslot_offset(json_object *jobj, int offset_add) +{ + json_object *jobj1, *jobj2, *jobj_area; + uint64_t offset = 0; + + json_object_object_get_ex(jobj, "keyslots", &jobj1); + json_object_object_foreach(jobj1, key, val) { + UNUSED(key); + json_object_object_get_ex(val, "area", &jobj_area); + json_object_object_get_ex(jobj_area, "offset", &jobj2); + offset = crypt_jobj_get_uint64(jobj2) + offset_add; + json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset)); + } +} + +/* FIXME: return specific error code for partial write error (aka keyslots are gone) */ +static int move_keyslot_areas(struct crypt_device *cd, off_t offset_from, + off_t offset_to, size_t buf_size) +{ + int devfd, r = -EIO; + struct device *device = crypt_metadata_device(cd); + void *buf = NULL; + + log_dbg(cd, "Moving keyslot areas of size %zu from %jd to %jd.", + buf_size, (intmax_t)offset_from, (intmax_t)offset_to); + + if (posix_memalign(&buf, crypt_getpagesize(), buf_size)) + return -ENOMEM; + + devfd = device_open(cd, device, O_RDWR); + if (devfd < 0) { + free(buf); + return -EIO; + } + + /* This can safely fail (for block devices). It only allocates space if it is possible. */ + if (posix_fallocate(devfd, offset_to, buf_size)) + log_dbg(cd, "Preallocation (fallocate) of new keyslot area not available."); + + /* Try to read *new* area to check that area is there (trimmed backup). */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), buf, buf_size, + offset_to)!= (ssize_t)buf_size) + goto out; + + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), buf, buf_size, + offset_from)!= (ssize_t)buf_size) + goto out; + + if (write_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), buf, buf_size, + offset_to) != (ssize_t)buf_size) + goto out; + + r = 0; +out: + device_sync(cd, device); + crypt_safe_memzero(buf, buf_size); + free(buf); + + return r; +} + +static int luks_header_in_use(struct crypt_device *cd) +{ + int r; + + r = lookup_dm_dev_by_uuid(cd, crypt_get_uuid(cd), crypt_get_type(cd)); + if (r < 0) + log_err(cd, _("Cannot check status of device with uuid: %s."), crypt_get_uuid(cd)); + + return r; +} + +/* Check if there is a luksmeta area (foreign metadata created by the luksmeta package) */ +static int luksmeta_header_present(struct crypt_device *cd, off_t luks1_size) +{ + int devfd, r = 0; + static const uint8_t LM_MAGIC[] = { 'L', 'U', 'K', 'S', 'M', 'E', 'T', 'A' }; + struct device *device = crypt_metadata_device(cd); + void *buf = NULL; + + if (posix_memalign(&buf, crypt_getpagesize(), sizeof(LM_MAGIC))) + return -ENOMEM; + + devfd = device_open(cd, device, O_RDONLY); + if (devfd < 0) { + free(buf); + return -EIO; + } + + /* Note: we must not detect failure as problem here, header can be trimmed. */ + if (read_lseek_blockwise(devfd, device_block_size(cd, device), device_alignment(device), + buf, sizeof(LM_MAGIC), luks1_size) == (ssize_t)sizeof(LM_MAGIC) && + !memcmp(LM_MAGIC, buf, sizeof(LM_MAGIC))) { + log_err(cd, _("Unable to convert header with LUKSMETA additional metadata.")); + r = -EBUSY; + } + + free(buf); + return r; +} + +/* Convert LUKS1 -> LUKS2 */ +int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct luks2_hdr *hdr2) +{ + int r; + json_object *jobj = NULL; + size_t buf_size, buf_offset, luks1_size, luks1_shift = 2 * LUKS2_HDR_16K_LEN - LUKS_ALIGN_KEYSLOTS; + uint64_t required_size, max_size = crypt_get_data_offset(cd) * SECTOR_SIZE; + + /* for detached headers max size == device size */ + if (!max_size && (r = device_size(crypt_metadata_device(cd), &max_size))) + return r; + + luks1_size = LUKS_device_sectors(hdr1) << SECTOR_SHIFT; + luks1_size = size_round_up(luks1_size, LUKS_ALIGN_KEYSLOTS); + if (!luks1_size) + return -EINVAL; + + if (LUKS_keyslots_offset(hdr1) != (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) { + log_dbg(cd, "Unsupported keyslots material offset: %zu.", LUKS_keyslots_offset(hdr1)); + return -EINVAL; + } + + if (luksmeta_header_present(cd, luks1_size)) + return -EINVAL; + + log_dbg(cd, "Max size: %" PRIu64 ", LUKS1 (full) header size %zu , required shift: %zu", + max_size, luks1_size, luks1_shift); + + required_size = luks1_size + luks1_shift; + + if ((max_size < required_size) && + device_fallocate(crypt_metadata_device(cd), required_size)) { + log_err(cd, _("Unable to move keyslot area. Not enough space.")); + return -EINVAL; + } + + if (max_size < required_size) + max_size = required_size; + + r = json_luks1_object(hdr1, &jobj, max_size - 2 * LUKS2_HDR_16K_LEN); + if (r < 0) + return r; + + move_keyslot_offset(jobj, luks1_shift); + + // fill hdr2 + memset(hdr2, 0, sizeof(*hdr2)); + hdr2->hdr_size = LUKS2_HDR_16K_LEN; + hdr2->seqid = 1; + hdr2->version = 2; + strncpy(hdr2->checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L); + crypt_random_get(cd, (char*)hdr2->salt1, sizeof(hdr2->salt1), CRYPT_RND_SALT); + crypt_random_get(cd, (char*)hdr2->salt2, sizeof(hdr2->salt2), CRYPT_RND_SALT); + strncpy(hdr2->uuid, crypt_get_uuid(cd), LUKS2_UUID_L-1); /* UUID should be max 36 chars */ + hdr2->jobj = jobj; + + /* + * It duplicates check in LUKS2_hdr_write() but we don't want to move + * keyslot areas in case it would fail later + */ + if (max_size < LUKS2_hdr_and_areas_size(hdr2->jobj)) { + r = -EINVAL; + goto out; + } + + /* check future LUKS2 metadata before moving keyslots area */ + if (LUKS2_hdr_validate(cd, hdr2->jobj, hdr2->hdr_size - LUKS2_HDR_BIN_LEN)) { + r = -EINVAL; + goto out; + } + + if ((r = luks_header_in_use(cd))) { + if (r > 0) + r = -EBUSY; + goto out; + } + + // move keyslots 4k -> 32k offset + buf_offset = 2 * LUKS2_HDR_16K_LEN; + buf_size = luks1_size - LUKS_ALIGN_KEYSLOTS; + + /* check future LUKS2 keyslots area is at least as large as LUKS1 keyslots area */ + if (buf_size > LUKS2_keyslots_size(hdr2->jobj)) { + log_err(cd, _("Unable to move keyslot area. LUKS2 keyslots area too small.")); + r = -EINVAL; + goto out; + } + + if ((r = move_keyslot_areas(cd, 8 * SECTOR_SIZE, buf_offset, buf_size)) < 0) { + log_err(cd, _("Unable to move keyslot area.")); + goto out; + } + + // Write JSON hdr2 + r = LUKS2_hdr_write(cd, hdr2); +out: + LUKS2_hdr_free(cd, hdr2); + + return r; +} + +static int keyslot_LUKS1_compatible(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, uint32_t key_size, const char *hash) +{ + json_object *jobj_keyslot, *jobj, *jobj_kdf, *jobj_af; + uint64_t l2_offset, l2_length; + size_t ks_key_size; + const char *ks_cipher, *data_cipher; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot); + if (!jobj_keyslot) + return 1; + + if (!json_object_object_get_ex(jobj_keyslot, "type", &jobj) || + strcmp(json_object_get_string(jobj), "luks2")) + return 0; + + /* Using PBKDF2, this implies memory and parallel is not used. */ + jobj = NULL; + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) || + !json_object_object_get_ex(jobj_kdf, "type", &jobj) || + strcmp(json_object_get_string(jobj), CRYPT_KDF_PBKDF2) || + !json_object_object_get_ex(jobj_kdf, "hash", &jobj) || + strcmp(json_object_get_string(jobj), hash)) + return 0; + + jobj = NULL; + if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) || + !json_object_object_get_ex(jobj_af, "stripes", &jobj) || + json_object_get_int(jobj) != LUKS_STRIPES) + return 0; + + jobj = NULL; + if (!json_object_object_get_ex(jobj_af, "hash", &jobj) || + (crypt_hash_size(json_object_get_string(jobj)) < 0) || + strcmp(json_object_get_string(jobj), hash)) + return 0; + + /* FIXME: should this go to validation code instead (aka invalid luks2 header if assigned to segment 0)? */ + /* FIXME: check all keyslots are assigned to segment id 0, and segments count == 1 */ + ks_cipher = LUKS2_get_keyslot_cipher(hdr, keyslot, &ks_key_size); + data_cipher = LUKS2_get_cipher(hdr, CRYPT_DEFAULT_SEGMENT); + if (!ks_cipher || !data_cipher || key_size != ks_key_size || strcmp(ks_cipher, data_cipher)) { + log_dbg(cd, "Cipher in keyslot %d is different from volume key encryption.", keyslot); + return 0; + } + + if (LUKS2_keyslot_area(hdr, keyslot, &l2_offset, &l2_length)) + return 0; + + if (l2_length != (size_round_up(AF_split_sectors(key_size, LUKS_STRIPES) * SECTOR_SIZE, 4096))) { + log_dbg(cd, "Area length in LUKS2 keyslot (%d) is not compatible with LUKS1", keyslot); + return 0; + } + + return 1; +} + +/* Convert LUKS2 -> LUKS1 */ +int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct luks_phdr *hdr1) +{ + size_t buf_size, buf_offset; + char cipher[LUKS_CIPHERNAME_L-1], cipher_mode[LUKS_CIPHERMODE_L-1]; + char digest[LUKS_DIGESTSIZE], digest_salt[LUKS_SALTSIZE]; + const char *hash; + size_t len; + json_object *jobj_keyslot, *jobj_digest, *jobj_segment, *jobj_kdf, *jobj_area, *jobj1, *jobj2; + uint32_t key_size; + int i, r, last_active = 0; + uint64_t offset, area_length; + char buf[256], luksMagic[] = LUKS_MAGIC; + + jobj_digest = LUKS2_get_digest_jobj(hdr2, 0); + if (!jobj_digest) + return -EINVAL; + + jobj_segment = LUKS2_get_segment_jobj(hdr2, CRYPT_DEFAULT_SEGMENT); + if (!jobj_segment) + return -EINVAL; + + if (json_segment_get_sector_size(jobj_segment) != SECTOR_SIZE) { + log_err(cd, _("Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes.")); + return -EINVAL; + } + + json_object_object_get_ex(hdr2->jobj, "digests", &jobj1); + if (!json_object_object_get_ex(jobj_digest, "type", &jobj2) || + strcmp(json_object_get_string(jobj2), "pbkdf2") || + json_object_object_length(jobj1) != 1) { + log_err(cd, _("Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible.")); + return -EINVAL; + } + if (!json_object_object_get_ex(jobj_digest, "hash", &jobj2)) + return -EINVAL; + hash = json_object_get_string(jobj2); + + r = crypt_parse_name_and_mode(LUKS2_get_cipher(hdr2, CRYPT_DEFAULT_SEGMENT), cipher, NULL, cipher_mode); + if (r < 0) + return r; + + if (crypt_cipher_wrapped_key(cipher, cipher_mode)) { + log_err(cd, _("Cannot convert to LUKS1 format - device uses wrapped key cipher %s."), cipher); + return -EINVAL; + } + + r = LUKS2_tokens_count(hdr2); + if (r < 0) + return r; + if (r > 0) { + log_err(cd, _("Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."), r); + return -EINVAL; + } + + r = LUKS2_get_volume_key_size(hdr2, 0); + if (r < 0) + return -EINVAL; + key_size = r; + + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) { + if (LUKS2_keyslot_info(hdr2, i) == CRYPT_SLOT_INACTIVE) + continue; + + if (LUKS2_keyslot_info(hdr2, i) == CRYPT_SLOT_INVALID) { + log_err(cd, _("Cannot convert to LUKS1 format - keyslot %u is in invalid state."), i); + return -EINVAL; + } + + if (i >= LUKS_NUMKEYS) { + log_err(cd, _("Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."), i); + return -EINVAL; + } + + if (!keyslot_LUKS1_compatible(cd, hdr2, i, key_size, hash)) { + log_err(cd, _("Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."), i); + return -EINVAL; + } + } + + memset(hdr1, 0, sizeof(*hdr1)); + + for (i = 0; i < LUKS_NUMKEYS; i++) { + hdr1->keyblock[i].active = LUKS_KEY_DISABLED; + hdr1->keyblock[i].stripes = LUKS_STRIPES; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr2, i); + + if (jobj_keyslot) { + if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + if (!json_object_object_get_ex(jobj_area, "offset", &jobj1)) + return -EINVAL; + offset = crypt_jobj_get_uint64(jobj1); + } else { + if (LUKS2_find_area_gap(cd, hdr2, key_size, &offset, &area_length)) + return -EINVAL; + /* + * We have to create placeholder luks2 keyslots in place of all + * inactive keyslots. Otherwise we would allocate all + * inactive luks1 keyslots over same binary keyslot area. + */ + if (placeholder_keyslot_alloc(cd, i, offset, area_length, key_size)) + return -EINVAL; + } + + offset /= SECTOR_SIZE; + if (offset > UINT32_MAX) + return -EINVAL; + + hdr1->keyblock[i].keyMaterialOffset = offset; + hdr1->keyblock[i].keyMaterialOffset -= + ((2 * LUKS2_HDR_16K_LEN - LUKS_ALIGN_KEYSLOTS) / SECTOR_SIZE); + + if (!jobj_keyslot) + continue; + + hdr1->keyblock[i].active = LUKS_KEY_ENABLED; + last_active = i; + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf)) + continue; + + if (!json_object_object_get_ex(jobj_kdf, "iterations", &jobj1)) + continue; + hdr1->keyblock[i].passwordIterations = crypt_jobj_get_uint32(jobj1); + + if (!json_object_object_get_ex(jobj_kdf, "salt", &jobj1)) + continue; + len = sizeof(buf); + memset(buf, 0, len); + if (!base64_decode(json_object_get_string(jobj1), + json_object_get_string_len(jobj1), buf, &len)) + continue; + if (len > 0 && len != LUKS_SALTSIZE) + continue; + memcpy(hdr1->keyblock[i].passwordSalt, buf, LUKS_SALTSIZE); + } + + if (!jobj_keyslot) { + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr2, last_active); + if (!jobj_keyslot) + return -EINVAL; + } + + if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area)) + return -EINVAL; + if (!json_object_object_get_ex(jobj_area, "encryption", &jobj1)) + return -EINVAL; + r = crypt_parse_name_and_mode(json_object_get_string(jobj1), cipher, NULL, cipher_mode); + if (r < 0) + return r; + + strncpy(hdr1->cipherName, cipher, sizeof(hdr1->cipherName) - 1); + strncpy(hdr1->cipherMode, cipher_mode, sizeof(hdr1->cipherMode) - 1); + + if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf)) + return -EINVAL; + if (!json_object_object_get_ex(jobj_kdf, "hash", &jobj1)) + return -EINVAL; + strncpy(hdr1->hashSpec, json_object_get_string(jobj1), sizeof(hdr1->hashSpec) - 1); + + hdr1->keyBytes = key_size; + + if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1)) + return -EINVAL; + hdr1->mkDigestIterations = crypt_jobj_get_uint32(jobj1); + + if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1)) + return -EINVAL; + len = sizeof(digest); + if (!base64_decode(json_object_get_string(jobj1), + json_object_get_string_len(jobj1), digest, &len)) + return -EINVAL; + /* We can store full digest here, not only sha1 length */ + if (len < LUKS_DIGESTSIZE) + return -EINVAL; + memcpy(hdr1->mkDigest, digest, LUKS_DIGESTSIZE); + + if (!json_object_object_get_ex(jobj_digest, "salt", &jobj1)) + return -EINVAL; + len = sizeof(digest_salt); + if (!base64_decode(json_object_get_string(jobj1), + json_object_get_string_len(jobj1), digest_salt, &len)) + return -EINVAL; + if (len != LUKS_SALTSIZE) + return -EINVAL; + memcpy(hdr1->mkDigestSalt, digest_salt, LUKS_SALTSIZE); + + if (!json_object_object_get_ex(jobj_segment, "offset", &jobj1)) + return -EINVAL; + offset = crypt_jobj_get_uint64(jobj1) / SECTOR_SIZE; + if (offset > UINT32_MAX) + return -EINVAL; + /* FIXME: LUKS1 requires offset == 0 || offset >= luks1_hdr_size */ + hdr1->payloadOffset = offset; + + strncpy(hdr1->uuid, hdr2->uuid, UUID_STRING_L); /* max 36 chars */ + hdr1->uuid[UUID_STRING_L-1] = '\0'; + + memcpy(hdr1->magic, luksMagic, LUKS_MAGIC_L); + + hdr1->version = 1; + + r = luks_header_in_use(cd); + if (r) + return r > 0 ? -EBUSY : r; + + // move keyslots 32k -> 4k offset + buf_offset = 2 * LUKS2_HDR_16K_LEN; + buf_size = LUKS2_keyslots_size(hdr2->jobj); + r = move_keyslot_areas(cd, buf_offset, 8 * SECTOR_SIZE, buf_size); + if (r < 0) { + log_err(cd, _("Unable to move keyslot area.")); + return r; + } + + crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0, + 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL); + + // Write LUKS1 hdr + return LUKS_write_phdr(hdr1, cd); +} diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c new file mode 100644 index 0000000..68d3194 --- /dev/null +++ b/lib/luks2/luks2_reencrypt.c @@ -0,0 +1,3445 @@ +/* + * LUKS - Linux Unified Key Setup v2, reencryption helpers + * + * Copyright (C) 2015-2020, Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2020, Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" +#include "utils_device_locking.h" + +static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new) +{ + return LUKS2_get_segment_by_flag(hdr, new ? "backup-final" : "backup-previous"); +} + +static json_object *reencrypt_segment_new(struct luks2_hdr *hdr) +{ + return reencrypt_segment(hdr, 1); +} + +static json_object *reencrypt_segment_old(struct luks2_hdr *hdr) +{ + return reencrypt_segment(hdr, 0); +} + +static const char *reencrypt_segment_cipher_new(struct luks2_hdr *hdr) +{ + return json_segment_get_cipher(reencrypt_segment(hdr, 1)); +} + +static const char *reencrypt_segment_cipher_old(struct luks2_hdr *hdr) +{ + return json_segment_get_cipher(reencrypt_segment(hdr, 0)); +} + +static int reencrypt_get_sector_size_new(struct luks2_hdr *hdr) +{ + return json_segment_get_sector_size(reencrypt_segment(hdr, 1)); +} + +static int reencrypt_get_sector_size_old(struct luks2_hdr *hdr) +{ + return json_segment_get_sector_size(reencrypt_segment(hdr, 0)); +} + +static uint64_t reencrypt_data_offset(struct luks2_hdr *hdr, unsigned new) +{ + json_object *jobj = reencrypt_segment(hdr, new); + if (jobj) + return json_segment_get_offset(jobj, 0); + + return LUKS2_get_data_offset(hdr) << SECTOR_SHIFT; +} + +static uint64_t LUKS2_reencrypt_get_data_offset_moved(struct luks2_hdr *hdr) +{ + json_object *jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment"); + + if (!jobj_segment) + return 0; + + return json_segment_get_offset(jobj_segment, 0); +} + +static uint64_t reencrypt_get_data_offset_new(struct luks2_hdr *hdr) +{ + return reencrypt_data_offset(hdr, 1); +} + +static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr) +{ + return reencrypt_data_offset(hdr, 0); +} + +static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new) +{ + int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "backup-previous"); + + if (segment < 0) + return segment; + + return LUKS2_digest_by_segment(hdr, segment); +} + +int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr) +{ + return reencrypt_digest(hdr, 1); +} + +int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr) +{ + return reencrypt_digest(hdr, 0); +} + +/* none, checksums, journal or shift */ +static const char *reencrypt_resilience_type(struct luks2_hdr *hdr) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_type; + int ks = LUKS2_find_keyslot(hdr, "reencrypt"); + + if (ks < 0) + return NULL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); + + json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); + if (!json_object_object_get_ex(jobj_area, "type", &jobj_type)) + return NULL; + + return json_object_get_string(jobj_type); +} + +static const char *reencrypt_resilience_hash(struct luks2_hdr *hdr) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash; + int ks = LUKS2_find_keyslot(hdr, "reencrypt"); + + if (ks < 0) + return NULL; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); + + json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); + if (!json_object_object_get_ex(jobj_area, "type", &jobj_type)) + return NULL; + if (strcmp(json_object_get_string(jobj_type), "checksum")) + return NULL; + if (!json_object_object_get_ex(jobj_area, "hash", &jobj_hash)) + return NULL; + + return json_object_get_string(jobj_hash); +} + +static uint32_t reencrypt_alignment(struct luks2_hdr *hdr) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash, *jobj_sector_size; + int ks = LUKS2_find_keyslot(hdr, "reencrypt"); + + if (ks < 0) + return 0; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); + + json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); + if (!json_object_object_get_ex(jobj_area, "type", &jobj_type)) + return 0; + if (strcmp(json_object_get_string(jobj_type), "checksum")) + return 0; + if (!json_object_object_get_ex(jobj_area, "hash", &jobj_hash)) + return 0; + if (!json_object_object_get_ex(jobj_area, "sector_size", &jobj_sector_size)) + return 0; + + return crypt_jobj_get_uint32(jobj_sector_size); +} + +static json_object *_enc_create_segments_shift_after(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t data_offset) +{ + int reenc_seg, i = 0; + json_object *jobj_copy, *jobj_seg_new = NULL, *jobj_segs_post = json_object_new_object(); + uint64_t tmp; + + if (!rh->jobj_segs_hot || !jobj_segs_post) + goto err; + + if (json_segments_count(rh->jobj_segs_hot) == 0) + return jobj_segs_post; + + reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot); + if (reenc_seg < 0) + goto err; + + while (i < reenc_seg) { + jobj_copy = json_segments_get_segment(rh->jobj_segs_hot, i); + if (!jobj_copy) + goto err; + json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy)); + } + + if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1), &jobj_seg_new)) { + if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg), &jobj_seg_new)) + goto err; + json_segment_remove_flag(jobj_seg_new, "in-reencryption"); + tmp = rh->length; + } else { + json_object_object_add(jobj_seg_new, "offset", crypt_jobj_new_uint64(rh->offset + data_offset)); + json_object_object_add(jobj_seg_new, "iv_tweak", crypt_jobj_new_uint64(rh->offset >> SECTOR_SHIFT)); + tmp = json_segment_get_size(jobj_seg_new, 0) + rh->length; + } + + /* alter size of new segment, reenc_seg == 0 we're finished */ + json_object_object_add(jobj_seg_new, "size", reenc_seg > 0 ? crypt_jobj_new_uint64(tmp) : json_object_new_string("dynamic")); + json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_seg_new); + + return jobj_segs_post; +err: + json_object_put(jobj_segs_post); + return NULL; +} + +static json_object *reencrypt_make_hot_segments_encrypt_shift(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t data_offset) +{ + int sg, crypt_seg, i = 0; + uint64_t segment_size; + json_object *jobj_seg_shrunk, *jobj_seg_new, *jobj_copy, *jobj_enc_seg = NULL, + *jobj_segs_hot = json_object_new_object(); + + if (!jobj_segs_hot) + return NULL; + + crypt_seg = LUKS2_segment_by_type(hdr, "crypt"); + + /* FIXME: This is hack. Find proper way to fix it. */ + sg = LUKS2_last_segment_by_type(hdr, "linear"); + if (rh->offset && sg < 0) + goto err; + if (sg < 0) + return jobj_segs_hot; + + jobj_enc_seg = json_segment_create_crypt(data_offset + rh->offset, + rh->offset >> SECTOR_SHIFT, + &rh->length, + reencrypt_segment_cipher_new(hdr), + reencrypt_get_sector_size_new(hdr), + 1); + + while (i < sg) { + jobj_copy = LUKS2_get_segment_jobj(hdr, i); + if (!jobj_copy) + goto err; + json_object_object_add_by_uint(jobj_segs_hot, i++, json_object_get(jobj_copy)); + } + + segment_size = LUKS2_segment_size(hdr, sg, 0); + if (segment_size > rh->length) { + jobj_seg_shrunk = NULL; + if (json_object_copy(LUKS2_get_segment_jobj(hdr, sg), &jobj_seg_shrunk)) + goto err; + json_object_object_add(jobj_seg_shrunk, "size", crypt_jobj_new_uint64(segment_size - rh->length)); + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_seg_shrunk); + } + + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_enc_seg); + jobj_enc_seg = NULL; /* see err: label */ + + /* first crypt segment after encryption ? */ + if (crypt_seg >= 0) { + jobj_seg_new = LUKS2_get_segment_jobj(hdr, crypt_seg); + if (!jobj_seg_new) + goto err; + json_object_object_add_by_uint(jobj_segs_hot, sg, json_object_get(jobj_seg_new)); + } + + return jobj_segs_hot; +err: + json_object_put(jobj_enc_seg); + json_object_put(jobj_segs_hot); + + return NULL; +} + +static json_object *reencrypt_make_segment_new(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct luks2_reenc_context *rh, + uint64_t data_offset, + uint64_t segment_offset, + uint64_t iv_offset, + const uint64_t *segment_length) +{ + switch (rh->mode) { + case CRYPT_REENCRYPT_REENCRYPT: + case CRYPT_REENCRYPT_ENCRYPT: + return json_segment_create_crypt(data_offset + segment_offset, + crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT), + segment_length, + reencrypt_segment_cipher_new(hdr), + reencrypt_get_sector_size_new(hdr), 0); + case CRYPT_REENCRYPT_DECRYPT: + return json_segment_create_linear(data_offset + segment_offset, segment_length, 0); + } + + return NULL; +} + +static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t data_offset) +{ + int reenc_seg; + json_object *jobj_new_seg_after, *jobj_old_seg, *jobj_old_seg_copy = NULL, + *jobj_segs_post = json_object_new_object(); + uint64_t fixed_length = rh->offset + rh->length; + + if (!rh->jobj_segs_hot || !jobj_segs_post) + goto err; + + reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot); + if (reenc_seg < 0) + return NULL; + + jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1); + + /* + * if there's no old segment after reencryption, we're done. + * Set size to 'dynamic' again. + */ + jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, jobj_old_seg ? &fixed_length : NULL); + if (!jobj_new_seg_after) + goto err; + json_object_object_add_by_uint(jobj_segs_post, 0, jobj_new_seg_after); + + if (jobj_old_seg) { + if (rh->fixed_length) { + if (json_object_copy(jobj_old_seg, &jobj_old_seg_copy)) + goto err; + jobj_old_seg = jobj_old_seg_copy; + fixed_length = rh->device_size - fixed_length; + json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(fixed_length)); + } else + json_object_get(jobj_old_seg); + json_object_object_add_by_uint(jobj_segs_post, 1, jobj_old_seg); + } + + return jobj_segs_post; +err: + json_object_put(jobj_segs_post); + return NULL; +} + +static json_object *reencrypt_make_post_segments_backward(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t data_offset) +{ + int reenc_seg; + uint64_t fixed_length; + + json_object *jobj_new_seg_after, *jobj_old_seg, + *jobj_segs_post = json_object_new_object(); + + if (!rh->jobj_segs_hot || !jobj_segs_post) + goto err; + + reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot); + if (reenc_seg < 0) + return NULL; + + jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg - 1); + if (jobj_old_seg) + json_object_object_add_by_uint(jobj_segs_post, reenc_seg - 1, json_object_get(jobj_old_seg)); + if (rh->fixed_length && rh->offset) { + fixed_length = rh->device_size - rh->offset; + jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, &fixed_length); + } else + jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, NULL); + if (!jobj_new_seg_after) + goto err; + json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_new_seg_after); + + return jobj_segs_post; +err: + json_object_put(jobj_segs_post); + return NULL; +} + +static json_object *reencrypt_make_segment_reencrypt(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct luks2_reenc_context *rh, + uint64_t data_offset, + uint64_t segment_offset, + uint64_t iv_offset, + const uint64_t *segment_length) +{ + switch (rh->mode) { + case CRYPT_REENCRYPT_REENCRYPT: + case CRYPT_REENCRYPT_ENCRYPT: + return json_segment_create_crypt(data_offset + segment_offset, + crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT), + segment_length, + reencrypt_segment_cipher_new(hdr), + reencrypt_get_sector_size_new(hdr), 1); + case CRYPT_REENCRYPT_DECRYPT: + return json_segment_create_linear(data_offset + segment_offset, segment_length, 1); + } + + return NULL; +} + +static json_object *reencrypt_make_segment_old(struct crypt_device *cd, + struct luks2_hdr *hdr, + const struct luks2_reenc_context *rh, + uint64_t data_offset, + uint64_t segment_offset, + const uint64_t *segment_length) +{ + json_object *jobj_old_seg = NULL; + + switch (rh->mode) { + case CRYPT_REENCRYPT_REENCRYPT: + case CRYPT_REENCRYPT_DECRYPT: + jobj_old_seg = json_segment_create_crypt(data_offset + segment_offset, + crypt_get_iv_offset(cd) + (segment_offset >> SECTOR_SHIFT), + segment_length, + reencrypt_segment_cipher_old(hdr), + reencrypt_get_sector_size_old(hdr), + 0); + break; + case CRYPT_REENCRYPT_ENCRYPT: + jobj_old_seg = json_segment_create_linear(data_offset + segment_offset, segment_length, 0); + } + + return jobj_old_seg; +} + +static json_object *reencrypt_make_hot_segments_forward(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t device_size, + uint64_t data_offset) +{ + json_object *jobj_segs_hot, *jobj_reenc_seg, *jobj_old_seg, *jobj_new_seg; + uint64_t fixed_length, tmp = rh->offset + rh->length; + unsigned int sg = 0; + + jobj_segs_hot = json_object_new_object(); + if (!jobj_segs_hot) + return NULL; + + if (rh->offset) { + jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, &rh->offset); + if (!jobj_new_seg) + goto err; + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_new_seg); + } + + jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length); + if (!jobj_reenc_seg) + goto err; + + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg); + + if (tmp < device_size) { + fixed_length = device_size - tmp; + jobj_old_seg = reencrypt_make_segment_old(cd, hdr, rh, data_offset + rh->data_shift, rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL); + if (!jobj_old_seg) + goto err; + json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_old_seg); + } + + return jobj_segs_hot; +err: + json_object_put(jobj_segs_hot); + return NULL; +} + +static json_object *reencrypt_make_hot_segments_backward(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t device_size, + uint64_t data_offset) +{ + json_object *jobj_reenc_seg, *jobj_new_seg, *jobj_old_seg = NULL, + *jobj_segs_hot = json_object_new_object(); + int sg = 0; + uint64_t fixed_length, tmp = rh->offset + rh->length; + + if (!jobj_segs_hot) + return NULL; + + if (rh->offset) { + if (json_object_copy(LUKS2_get_segment_jobj(hdr, 0), &jobj_old_seg)) + goto err; + json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(rh->offset)); + + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_old_seg); + } + + jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length); + if (!jobj_reenc_seg) + goto err; + + json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg); + + if (tmp < device_size) { + fixed_length = device_size - tmp; + jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset + rh->length, rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL); + if (!jobj_new_seg) + goto err; + json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_new_seg); + } + + return jobj_segs_hot; +err: + json_object_put(jobj_segs_hot); + return NULL; +} + +static int reencrypt_make_hot_segments(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t device_size, + uint64_t data_offset) +{ + rh->jobj_segs_hot = NULL; + + if (rh->mode == CRYPT_REENCRYPT_ENCRYPT && rh->direction == CRYPT_REENCRYPT_BACKWARD && + rh->data_shift && rh->jobj_segment_moved) { + log_dbg(cd, "Calculating hot segments for encryption with data move."); + rh->jobj_segs_hot = reencrypt_make_hot_segments_encrypt_shift(cd, hdr, rh, data_offset); + } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) { + log_dbg(cd, "Calculating hot segments (forward direction)."); + rh->jobj_segs_hot = reencrypt_make_hot_segments_forward(cd, hdr, rh, device_size, data_offset); + } else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) { + log_dbg(cd, "Calculating hot segments (backward direction)."); + rh->jobj_segs_hot = reencrypt_make_hot_segments_backward(cd, hdr, rh, device_size, data_offset); + } + + return rh->jobj_segs_hot ? 0 : -EINVAL; +} + +static int reencrypt_make_post_segments(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t data_offset) +{ + rh->jobj_segs_post = NULL; + + if (rh->mode == CRYPT_REENCRYPT_ENCRYPT && rh->direction == CRYPT_REENCRYPT_BACKWARD && + rh->data_shift && rh->jobj_segment_moved) { + log_dbg(cd, "Calculating post segments for encryption with data move."); + rh->jobj_segs_post = _enc_create_segments_shift_after(cd, hdr, rh, data_offset); + } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) { + log_dbg(cd, "Calculating post segments (forward direction)."); + rh->jobj_segs_post = reencrypt_make_post_segments_forward(cd, hdr, rh, data_offset); + } else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) { + log_dbg(cd, "Calculating segments (backward direction)."); + rh->jobj_segs_post = reencrypt_make_post_segments_backward(cd, hdr, rh, data_offset); + } + + return rh->jobj_segs_post ? 0 : -EINVAL; +} + +static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr) +{ + json_object *jobj_keyslot, *jobj_area, *jobj_data_shift; + int ks = LUKS2_find_keyslot(hdr, "reencrypt"); + + if (ks < 0) + return 0; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); + + json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); + if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj_data_shift)) + return 0; + + return crypt_jobj_get_uint64(jobj_data_shift); +} + +static crypt_reencrypt_mode_info reencrypt_mode(struct luks2_hdr *hdr) +{ + const char *mode; + crypt_reencrypt_mode_info mi = CRYPT_REENCRYPT_REENCRYPT; + json_object *jobj_keyslot, *jobj_mode; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, LUKS2_find_keyslot(hdr, "reencrypt")); + if (!jobj_keyslot) + return mi; + + json_object_object_get_ex(jobj_keyslot, "mode", &jobj_mode); + mode = json_object_get_string(jobj_mode); + + /* validation enforces allowed values */ + if (!strcmp(mode, "encrypt")) + mi = CRYPT_REENCRYPT_ENCRYPT; + else if (!strcmp(mode, "decrypt")) + mi = CRYPT_REENCRYPT_DECRYPT; + + return mi; +} + +static crypt_reencrypt_direction_info reencrypt_direction(struct luks2_hdr *hdr) +{ + const char *value; + json_object *jobj_keyslot, *jobj_mode; + crypt_reencrypt_direction_info di = CRYPT_REENCRYPT_FORWARD; + + jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, LUKS2_find_keyslot(hdr, "reencrypt")); + if (!jobj_keyslot) + return di; + + json_object_object_get_ex(jobj_keyslot, "direction", &jobj_mode); + value = json_object_get_string(jobj_mode); + + /* validation enforces allowed values */ + if (strcmp(value, "forward")) + di = CRYPT_REENCRYPT_BACKWARD; + + return di; +} + +typedef enum { REENC_OK = 0, REENC_ERR, REENC_ROLLBACK, REENC_FATAL } reenc_status_t; + +void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_context *rh) +{ + if (!rh) + return; + + if (rh->rp.type == REENC_PROTECTION_CHECKSUM) { + if (rh->rp.p.csum.ch) { + crypt_hash_destroy(rh->rp.p.csum.ch); + rh->rp.p.csum.ch = NULL; + } + if (rh->rp.p.csum.checksums) { + memset(rh->rp.p.csum.checksums, 0, rh->rp.p.csum.checksums_len); + free(rh->rp.p.csum.checksums); + rh->rp.p.csum.checksums = NULL; + } + } + + json_object_put(rh->jobj_segs_hot); + rh->jobj_segs_hot = NULL; + json_object_put(rh->jobj_segs_post); + rh->jobj_segs_post = NULL; + json_object_put(rh->jobj_segment_old); + rh->jobj_segment_old = NULL; + json_object_put(rh->jobj_segment_new); + rh->jobj_segment_new = NULL; + json_object_put(rh->jobj_segment_moved); + rh->jobj_segment_moved = NULL; + + free(rh->reenc_buffer); + rh->reenc_buffer = NULL; + crypt_storage_wrapper_destroy(rh->cw1); + rh->cw1 = NULL; + crypt_storage_wrapper_destroy(rh->cw2); + rh->cw2 = NULL; + + free(rh->device_name); + free(rh->overlay_name); + free(rh->hotzone_name); + crypt_drop_keyring_key(cd, rh->vks); + crypt_free_volume_key(rh->vks); + device_release_excl(cd, crypt_data_device(cd)); + crypt_unlock_internal(cd, rh->reenc_lock); + free(rh); +} + +static size_t reencrypt_get_alignment(struct crypt_device *cd, + struct luks2_hdr *hdr) +{ + int ss; + size_t alignment = device_block_size(cd, crypt_data_device(cd)); + + ss = reencrypt_get_sector_size_old(hdr); + if (ss > 0 && (size_t)ss > alignment) + alignment = ss; + ss = reencrypt_get_sector_size_new(hdr); + if (ss > 0 && (size_t)ss > alignment) + alignment = (size_t)ss; + + return alignment; +} + +/* returns void because it must not fail on valid LUKS2 header */ +static void _load_backup_segments(struct luks2_hdr *hdr, + struct luks2_reenc_context *rh) +{ + int segment = LUKS2_get_segment_id_by_flag(hdr, "backup-final"); + + if (segment >= 0) { + rh->jobj_segment_new = json_object_get(LUKS2_get_segment_jobj(hdr, segment)); + rh->digest_new = LUKS2_digest_by_segment(hdr, segment); + } else { + rh->jobj_segment_new = NULL; + rh->digest_new = -ENOENT; + } + + segment = LUKS2_get_segment_id_by_flag(hdr, "backup-previous"); + if (segment >= 0) { + rh->jobj_segment_old = json_object_get(LUKS2_get_segment_jobj(hdr, segment)); + rh->digest_old = LUKS2_digest_by_segment(hdr, segment); + } else { + rh->jobj_segment_old = NULL; + rh->digest_old = -ENOENT; + } + + segment = LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment"); + if (segment >= 0) + rh->jobj_segment_moved = json_object_get(LUKS2_get_segment_jobj(hdr, segment)); + else + rh->jobj_segment_moved = NULL; +} + +static int reencrypt_offset_backward_moved(struct luks2_hdr *hdr, json_object *jobj_segments, uint64_t *reencrypt_length, uint64_t data_shift, uint64_t *offset) +{ + uint64_t tmp, linear_length = 0; + int sg, segs = json_segments_count(jobj_segments); + + /* find reencrypt offset with data shift */ + for (sg = 0; sg < segs; sg++) + if (LUKS2_segment_is_type(hdr, sg, "linear")) + linear_length += LUKS2_segment_size(hdr, sg, 0); + + /* all active linear segments length */ + if (linear_length) { + if (linear_length < data_shift) + return -EINVAL; + tmp = linear_length - data_shift; + if (tmp && tmp < data_shift) { + *offset = data_shift; + *reencrypt_length = tmp; + } else + *offset = tmp; + return 0; + } + + if (segs == 1) { + *offset = 0; + return 0; + } + + /* should be unreachable */ + + return -EINVAL; +} + +static int _offset_forward(struct luks2_hdr *hdr, json_object *jobj_segments, uint64_t *offset) +{ + int segs = json_segments_count(jobj_segments); + + if (segs == 1) + *offset = 0; + else if (segs == 2) { + *offset = json_segment_get_size(json_segments_get_segment(jobj_segments, 0), 0); + if (!*offset) + return -EINVAL; + } else + return -EINVAL; + + return 0; +} + +static int _offset_backward(struct luks2_hdr *hdr, json_object *jobj_segments, uint64_t device_size, uint64_t *length, uint64_t *offset) +{ + int segs = json_segments_count(jobj_segments); + uint64_t tmp; + + if (segs == 1) { + if (device_size < *length) + *length = device_size; + *offset = device_size - *length; + } else if (segs == 2) { + tmp = json_segment_get_size(json_segments_get_segment(jobj_segments, 0), 0); + if (tmp < *length) + *length = tmp; + *offset = tmp - *length; + } else + return -EINVAL; + + return 0; +} + +/* must be always relative to data offset */ +/* the LUKS2 header MUST be valid */ +static int reencrypt_offset(struct luks2_hdr *hdr, + crypt_reencrypt_direction_info di, + uint64_t device_size, + uint64_t *reencrypt_length, + uint64_t *offset) +{ + int sg; + json_object *jobj_segments; + uint64_t data_shift = reencrypt_data_shift(hdr); + + if (!offset) + return -EINVAL; + + /* if there's segment in reencryption return directly offset of it */ + json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments); + sg = json_segments_segment_in_reencrypt(jobj_segments); + if (sg >= 0) { + *offset = LUKS2_segment_offset(hdr, sg, 0) - (reencrypt_get_data_offset_new(hdr)); + return 0; + } + + if (di == CRYPT_REENCRYPT_FORWARD) + return _offset_forward(hdr, jobj_segments, offset); + else if (di == CRYPT_REENCRYPT_BACKWARD) { + if (reencrypt_mode(hdr) == CRYPT_REENCRYPT_ENCRYPT && + LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0) + return reencrypt_offset_backward_moved(hdr, jobj_segments, reencrypt_length, data_shift, offset); + return _offset_backward(hdr, jobj_segments, device_size, reencrypt_length, offset); + } + + return -EINVAL; +} + +static uint64_t reencrypt_length(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t keyslot_area_length, + uint64_t length_max) +{ + unsigned long dummy, optimal_alignment; + uint64_t length, soft_mem_limit; + + if (rh->rp.type == REENC_PROTECTION_NONE) + length = length_max ?: LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH; + else if (rh->rp.type == REENC_PROTECTION_CHECKSUM) + length = (keyslot_area_length / rh->rp.p.csum.hash_size) * rh->alignment; + else if (rh->rp.type == REENC_PROTECTION_DATASHIFT) + return reencrypt_data_shift(hdr); + else + length = keyslot_area_length; + + /* hard limit */ + if (length > LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH) + length = LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH; + + /* soft limit is 1/4 of system memory */ + soft_mem_limit = crypt_getphysmemory_kb() << 8; /* multiply by (1024/4) */ + + if (soft_mem_limit && length > soft_mem_limit) + length = soft_mem_limit; + + if (length_max && length > length_max) + length = length_max; + + length -= (length % rh->alignment); + + /* Emits error later */ + if (!length) + return length; + + device_topology_alignment(cd, crypt_data_device(cd), &optimal_alignment, &dummy, length); + + /* we have to stick with encryption sector size alignment */ + if (optimal_alignment % rh->alignment) + return length; + + /* align to opt-io size only if remaining size allows it */ + if (length > optimal_alignment) + length -= (length % optimal_alignment); + + return length; +} + +static int reencrypt_context_init(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reenc_context *rh, uint64_t device_size, const struct crypt_params_reencrypt *params) +{ + int r; + uint64_t dummy, area_length; + + rh->reenc_keyslot = LUKS2_find_keyslot(hdr, "reencrypt"); + if (rh->reenc_keyslot < 0) + return -EINVAL; + if (LUKS2_keyslot_area(hdr, rh->reenc_keyslot, &dummy, &area_length) < 0) + return -EINVAL; + + rh->mode = reencrypt_mode(hdr); + + rh->alignment = reencrypt_get_alignment(cd, hdr); + if (!rh->alignment) + return -EINVAL; + + log_dbg(cd, "Hotzone size: %" PRIu64 ", device size: %" PRIu64 ", alignment: %zu.", + params->max_hotzone_size << SECTOR_SHIFT, + params->device_size << SECTOR_SHIFT, rh->alignment); + + if ((params->max_hotzone_size << SECTOR_SHIFT) % rh->alignment) { + log_err(cd, _("Hotzone size must be multiple of calculated zone alignment (%zu bytes)."), rh->alignment); + return -EINVAL; + } + + if ((params->device_size << SECTOR_SHIFT) % rh->alignment) { + log_err(cd, _("Device size must be multiple of calculated zone alignment (%zu bytes)."), rh->alignment); + return -EINVAL; + } + + rh->direction = reencrypt_direction(hdr); + + if (!strcmp(params->resilience, "datashift")) { + log_dbg(cd, "Initializing reencryption context with data_shift resilience."); + rh->rp.type = REENC_PROTECTION_DATASHIFT; + rh->data_shift = reencrypt_data_shift(hdr); + } else if (!strcmp(params->resilience, "journal")) { + log_dbg(cd, "Initializing reencryption context with journal resilience."); + rh->rp.type = REENC_PROTECTION_JOURNAL; + } else if (!strcmp(params->resilience, "checksum")) { + log_dbg(cd, "Initializing reencryption context with checksum resilience."); + rh->rp.type = REENC_PROTECTION_CHECKSUM; + + r = snprintf(rh->rp.p.csum.hash, + sizeof(rh->rp.p.csum.hash), "%s", params->hash); + if (r < 0 || (size_t)r >= sizeof(rh->rp.p.csum.hash)) { + log_dbg(cd, "Invalid hash parameter"); + return -EINVAL; + } + + if (crypt_hash_init(&rh->rp.p.csum.ch, params->hash)) { + log_dbg(cd, "Failed to initialize checksum resilience hash %s", params->hash); + return -EINVAL; + } + + r = crypt_hash_size(params->hash); + if (r < 1) { + log_dbg(cd, "Invalid hash size"); + return -EINVAL; + } + rh->rp.p.csum.hash_size = r; + + rh->rp.p.csum.checksums_len = area_length; + if (posix_memalign(&rh->rp.p.csum.checksums, device_alignment(crypt_metadata_device(cd)), + rh->rp.p.csum.checksums_len)) + return -ENOMEM; + } else if (!strcmp(params->resilience, "none")) { + log_dbg(cd, "Initializing reencryption context with none resilience."); + rh->rp.type = REENC_PROTECTION_NONE; + } else { + log_err(cd, _("Unsupported resilience mode %s"), params->resilience); + return -EINVAL; + } + + if (params->device_size) { + log_dbg(cd, "Switching reencryption to fixed size mode."); + device_size = params->device_size << SECTOR_SHIFT; + rh->fixed_length = true; + } else + rh->fixed_length = false; + + rh->length = reencrypt_length(cd, hdr, rh, area_length, params->max_hotzone_size << SECTOR_SHIFT); + if (!rh->length) { + log_dbg(cd, "Invalid reencryption length."); + return -EINVAL; + } + + if (reencrypt_offset(hdr, rh->direction, device_size, &rh->length, &rh->offset)) { + log_dbg(cd, "Failed to get reencryption offset."); + return -EINVAL; + } + + if (rh->offset > device_size) + return -EINVAL; + if (rh->length > device_size - rh->offset) + rh->length = device_size - rh->offset; + + log_dbg(cd, "reencrypt-direction: %s", rh->direction == CRYPT_REENCRYPT_FORWARD ? "forward" : "backward"); + + _load_backup_segments(hdr, rh); + + if (rh->direction == CRYPT_REENCRYPT_BACKWARD) + rh->progress = device_size - rh->offset - rh->length; + else + rh->progress = rh->offset; + + log_dbg(cd, "backup-previous digest id: %d", rh->digest_old); + log_dbg(cd, "backup-final digest id: %d", rh->digest_new); + log_dbg(cd, "reencrypt length: %" PRIu64, rh->length); + log_dbg(cd, "reencrypt offset: %" PRIu64, rh->offset); + log_dbg(cd, "reencrypt shift: %s%" PRIu64, (rh->data_shift && rh->direction == CRYPT_REENCRYPT_BACKWARD ? "-" : ""), rh->data_shift); + log_dbg(cd, "reencrypt alignment: %zu", rh->alignment); + log_dbg(cd, "reencrypt progress: %" PRIu64, rh->progress); + + rh->device_size = device_size; + + return rh->length < 512 ? -EINVAL : 0; +} + +static size_t reencrypt_buffer_length(struct luks2_reenc_context *rh) +{ + if (rh->data_shift) + return rh->data_shift; + return rh->length; +} + +static int reencrypt_load_clean(struct crypt_device *cd, + struct luks2_hdr *hdr, + uint64_t device_size, + struct luks2_reenc_context **rh, + const struct crypt_params_reencrypt *params) +{ + int r; + const struct crypt_params_reencrypt hdr_reenc_params = { + .resilience = reencrypt_resilience_type(hdr), + .hash = reencrypt_resilience_hash(hdr), + .device_size = params ? params->device_size : 0 + }; + struct luks2_reenc_context *tmp = crypt_zalloc(sizeof (*tmp)); + + if (!tmp) + return -ENOMEM; + + r = -EINVAL; + if (!hdr_reenc_params.resilience) + goto err; + + /* skip context update if data shift is detected in header */ + if (!strcmp(hdr_reenc_params.resilience, "datashift")) + params = NULL; + + log_dbg(cd, "Initializing reencryption context (%s).", params ? "update" : "load"); + + if (!params || !params->resilience) + params = &hdr_reenc_params; + + r = reencrypt_context_init(cd, hdr, tmp, device_size, params); + if (r) + goto err; + + if (posix_memalign(&tmp->reenc_buffer, device_alignment(crypt_data_device(cd)), + reencrypt_buffer_length(tmp))) { + r = -ENOMEM; + goto err; + } + + *rh = tmp; + + return 0; +err: + LUKS2_reenc_context_free(cd, tmp); + + return r; +} + +static int reencrypt_make_segments(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t device_size) +{ + int r; + uint64_t data_offset = reencrypt_get_data_offset_new(hdr); + + log_dbg(cd, "Calculating segments."); + + r = reencrypt_make_hot_segments(cd, hdr, rh, device_size, data_offset); + if (!r) { + r = reencrypt_make_post_segments(cd, hdr, rh, data_offset); + if (r) + json_object_put(rh->jobj_segs_hot); + } + + if (r) + log_dbg(cd, "Failed to make reencryption segments."); + + return r; +} + +static int reencrypt_make_segments_crashed(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh) +{ + int r; + uint64_t data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT; + + if (!rh) + return -EINVAL; + + rh->jobj_segs_hot = json_object_new_object(); + if (!rh->jobj_segs_hot) + return -ENOMEM; + + json_object_object_foreach(LUKS2_get_segments_jobj(hdr), key, val) { + if (json_segment_is_backup(val)) + continue; + json_object_object_add(rh->jobj_segs_hot, key, json_object_get(val)); + } + + r = reencrypt_make_post_segments(cd, hdr, rh, data_offset); + if (r) { + json_object_put(rh->jobj_segs_hot); + rh->jobj_segs_hot = NULL; + } + + return r; +} + +static int reencrypt_load_crashed(struct crypt_device *cd, + struct luks2_hdr *hdr, uint64_t device_size, struct luks2_reenc_context **rh) +{ + bool dynamic; + uint64_t minimal_size; + int r, reenc_seg; + struct crypt_params_reencrypt params = {}; + + if (LUKS2_get_data_size(hdr, &minimal_size, &dynamic)) + return -EINVAL; + + if (!dynamic) + params.device_size = minimal_size >> SECTOR_SHIFT; + + r = reencrypt_load_clean(cd, hdr, device_size, rh, ¶ms); + + if (!r) { + reenc_seg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr)); + if (reenc_seg < 0) + r = -EINVAL; + else + (*rh)->length = LUKS2_segment_size(hdr, reenc_seg, 0); + } + + if (!r && ((*rh)->rp.type == REENC_PROTECTION_CHECKSUM)) { + /* we have to override calculated alignment with value stored in mda */ + (*rh)->alignment = reencrypt_alignment(hdr); + if (!(*rh)->alignment) { + log_dbg(cd, "Failed to get read resilience sector_size from metadata."); + r = -EINVAL; + } + } + + if (!r) + r = reencrypt_make_segments_crashed(cd, hdr, *rh); + + if (r) { + LUKS2_reenc_context_free(cd, *rh); + *rh = NULL; + } + return r; +} + +static int reencrypt_init_storage_wrappers(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + struct volume_key *vks) +{ + int r; + struct volume_key *vk; + uint32_t wrapper_flags = (getuid() || geteuid()) ? 0 : DISABLE_KCAPI; + + vk = crypt_volume_key_by_id(vks, rh->digest_old); + r = crypt_storage_wrapper_init(cd, &rh->cw1, crypt_data_device(cd), + reencrypt_get_data_offset_old(hdr), + crypt_get_iv_offset(cd), + reencrypt_get_sector_size_old(hdr), + reencrypt_segment_cipher_old(hdr), + vk, wrapper_flags | OPEN_READONLY); + if (r) { + log_err(cd, _("Failed to initialize old segment storage wrapper.")); + return r; + } + rh->wflags1 = wrapper_flags | OPEN_READONLY; + log_dbg(cd, "Old cipher storage wrapper type: %d.", crypt_storage_wrapper_get_type(rh->cw1)); + + vk = crypt_volume_key_by_id(vks, rh->digest_new); + r = crypt_storage_wrapper_init(cd, &rh->cw2, crypt_data_device(cd), + reencrypt_get_data_offset_new(hdr), + crypt_get_iv_offset(cd), + reencrypt_get_sector_size_new(hdr), + reencrypt_segment_cipher_new(hdr), + vk, wrapper_flags); + if (r) { + log_err(cd, _("Failed to initialize new segment storage wrapper.")); + return r; + } + rh->wflags2 = wrapper_flags; + log_dbg(cd, "New cipher storage wrapper type: %d", crypt_storage_wrapper_get_type(rh->cw2)); + + return 0; +} + +static int reencrypt_context_set_names(struct luks2_reenc_context *rh, const char *name) +{ + if (!rh | !name) + return -EINVAL; + + if (*name == '/') { + if (!(rh->device_name = dm_device_name(name))) + return -EINVAL; + } else if (!(rh->device_name = strdup(name))) + return -ENOMEM; + + if (asprintf(&rh->hotzone_name, "%s-hotzone-%s", rh->device_name, + rh->direction == CRYPT_REENCRYPT_FORWARD ? "forward" : "backward") < 0) { + rh->hotzone_name = NULL; + return -ENOMEM; + } + if (asprintf(&rh->overlay_name, "%s-overlay", rh->device_name) < 0) { + rh->overlay_name = NULL; + return -ENOMEM; + } + + rh->online = true; + return 0; +} + +static int modify_offset(uint64_t *offset, uint64_t data_shift, crypt_reencrypt_direction_info di) +{ + int r = -EINVAL; + + if (!offset) + return r; + + if (di == CRYPT_REENCRYPT_FORWARD) { + if (*offset >= data_shift) { + *offset -= data_shift; + r = 0; + } + } else if (di == CRYPT_REENCRYPT_BACKWARD) { + *offset += data_shift; + r = 0; + } + + return r; +} + +static int reencrypt_update_flag(struct crypt_device *cd, int enable, bool commit) +{ + uint32_t reqs; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + if (LUKS2_config_get_requirements(cd, hdr, &reqs)) + return -EINVAL; + + /* nothing to do */ + if (enable && (reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT)) + return -EINVAL; + + /* nothing to do */ + if (!enable && !(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT)) + return -EINVAL; + + if (enable) + reqs |= CRYPT_REQUIREMENT_ONLINE_REENCRYPT; + else + reqs &= ~CRYPT_REQUIREMENT_ONLINE_REENCRYPT; + + log_dbg(cd, "Going to %s reencryption requirement flag.", enable ? "store" : "wipe"); + + return LUKS2_config_set_requirements(cd, hdr, reqs, commit); +} + +static int reencrypt_recover_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + struct volume_key *vks) +{ + struct volume_key *vk_old, *vk_new; + size_t count, s; + ssize_t read, w; + unsigned resilience; + uint64_t area_offset, area_length, area_length_read, crash_iv_offset, + data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT; + int devfd, r, new_sector_size, old_sector_size, rseg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot); + char *checksum_tmp = NULL, *data_buffer = NULL; + struct crypt_storage_wrapper *cw1 = NULL, *cw2 = NULL; + + resilience = rh->rp.type; + + if (rseg < 0 || rh->length < 512) + return -EINVAL; + + vk_new = crypt_volume_key_by_id(vks, rh->digest_new); + if (!vk_new && rh->mode != CRYPT_REENCRYPT_DECRYPT) + return -EINVAL; + vk_old = crypt_volume_key_by_id(vks, rh->digest_old); + if (!vk_old && rh->mode != CRYPT_REENCRYPT_ENCRYPT) + return -EINVAL; + old_sector_size = json_segment_get_sector_size(reencrypt_segment_old(hdr)); + new_sector_size = json_segment_get_sector_size(reencrypt_segment_new(hdr)); + if (rh->mode == CRYPT_REENCRYPT_DECRYPT) + crash_iv_offset = rh->offset >> SECTOR_SHIFT; /* TODO: + old iv_tweak */ + else + crash_iv_offset = json_segment_get_iv_offset(json_segments_get_segment(rh->jobj_segs_hot, rseg)); + + log_dbg(cd, "crash_offset: %" PRIu64 ", crash_length: %" PRIu64 ", crash_iv_offset: %" PRIu64, data_offset + rh->offset, rh->length, crash_iv_offset); + + r = crypt_storage_wrapper_init(cd, &cw2, crypt_data_device(cd), + data_offset + rh->offset, crash_iv_offset, new_sector_size, + reencrypt_segment_cipher_new(hdr), vk_new, 0); + if (r) { + log_err(cd, _("Failed to initialize new segment storage wrapper.")); + return r; + } + + if (LUKS2_keyslot_area(hdr, rh->reenc_keyslot, &area_offset, &area_length)) { + r = -EINVAL; + goto out; + } + + if (posix_memalign((void**)&data_buffer, device_alignment(crypt_data_device(cd)), rh->length)) { + r = -ENOMEM; + goto out; + } + + switch (resilience) { + case REENC_PROTECTION_CHECKSUM: + log_dbg(cd, "Checksums based recovery."); + + r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd), + data_offset + rh->offset, crash_iv_offset, old_sector_size, + reencrypt_segment_cipher_old(hdr), vk_old, 0); + if (r) { + log_err(cd, _("Failed to initialize old segment storage wrapper.")); + goto out; + } + + count = rh->length / rh->alignment; + area_length_read = count * rh->rp.p.csum.hash_size; + if (area_length_read > area_length) { + log_dbg(cd, "Internal error in calculated area_length."); + r = -EINVAL; + goto out; + } + + checksum_tmp = malloc(rh->rp.p.csum.hash_size); + if (!checksum_tmp) { + r = -ENOMEM; + goto out; + } + + /* TODO: lock for read */ + devfd = device_open(cd, crypt_metadata_device(cd), O_RDONLY); + if (devfd < 0) + goto out; + + /* read old data checksums */ + read = read_lseek_blockwise(devfd, device_block_size(cd, crypt_metadata_device(cd)), + device_alignment(crypt_metadata_device(cd)), rh->rp.p.csum.checksums, area_length_read, area_offset); + if (read < 0 || (size_t)read != area_length_read) { + log_err(cd, _("Failed to read checksums for current hotzone.")); + r = -EINVAL; + goto out; + } + + read = crypt_storage_wrapper_read(cw2, 0, data_buffer, rh->length); + if (read < 0 || (size_t)read != rh->length) { + log_err(cd, _("Failed to read hotzone area starting at %" PRIu64 "."), rh->offset + data_offset); + r = -EINVAL; + goto out; + } + + for (s = 0; s < count; s++) { + if (crypt_hash_write(rh->rp.p.csum.ch, data_buffer + (s * rh->alignment), rh->alignment)) { + log_dbg(cd, "Failed to write hash."); + r = EINVAL; + goto out; + } + if (crypt_hash_final(rh->rp.p.csum.ch, checksum_tmp, rh->rp.p.csum.hash_size)) { + log_dbg(cd, "Failed to finalize hash."); + r = EINVAL; + goto out; + } + if (!memcmp(checksum_tmp, (char *)rh->rp.p.csum.checksums + (s * rh->rp.p.csum.hash_size), rh->rp.p.csum.hash_size)) { + log_dbg(cd, "Sector %zu (size %zu, offset %zu) needs recovery", s, rh->alignment, s * rh->alignment); + if (crypt_storage_wrapper_decrypt(cw1, s * rh->alignment, data_buffer + (s * rh->alignment), rh->alignment)) { + log_err(cd, _("Failed to decrypt sector %zu."), s); + r = -EINVAL; + goto out; + } + w = crypt_storage_wrapper_encrypt_write(cw2, s * rh->alignment, data_buffer + (s * rh->alignment), rh->alignment); + if (w < 0 || (size_t)w != rh->alignment) { + log_err(cd, _("Failed to recover sector %zu."), s); + r = -EINVAL; + goto out; + } + } + } + + r = 0; + break; + case REENC_PROTECTION_JOURNAL: + log_dbg(cd, "Journal based recovery."); + + /* FIXME: validation candidate */ + if (rh->length > area_length) { + r = -EINVAL; + log_dbg(cd, "Invalid journal size."); + goto out; + } + + /* TODO locking */ + r = crypt_storage_wrapper_init(cd, &cw1, crypt_metadata_device(cd), + area_offset, crash_iv_offset, old_sector_size, + reencrypt_segment_cipher_old(hdr), vk_old, 0); + if (r) { + log_err(cd, _("Failed to initialize old segment storage wrapper.")); + goto out; + } + read = crypt_storage_wrapper_read_decrypt(cw1, 0, data_buffer, rh->length); + if (read < 0 || (size_t)read != rh->length) { + log_dbg(cd, "Failed to read journaled data."); + r = -EIO; + /* may content plaintext */ + crypt_safe_memzero(data_buffer, rh->length); + goto out; + } + read = crypt_storage_wrapper_encrypt_write(cw2, 0, data_buffer, rh->length); + /* may content plaintext */ + crypt_safe_memzero(data_buffer, rh->length); + if (read < 0 || (size_t)read != rh->length) { + log_dbg(cd, "recovery write failed."); + r = -EINVAL; + goto out; + } + + r = 0; + break; + case REENC_PROTECTION_DATASHIFT: + log_dbg(cd, "Data shift based recovery."); + + if (rseg == 0) { + r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd), + json_segment_get_offset(rh->jobj_segment_moved, 0), 0, 0, + reencrypt_segment_cipher_old(hdr), NULL, 0); + } else + r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd), + data_offset + rh->offset - rh->data_shift, 0, 0, + reencrypt_segment_cipher_old(hdr), NULL, 0); + if (r) { + log_err(cd, _("Failed to initialize old segment storage wrapper.")); + goto out; + } + + read = crypt_storage_wrapper_read_decrypt(cw1, 0, data_buffer, rh->length); + if (read < 0 || (size_t)read != rh->length) { + log_dbg(cd, "Failed to read data."); + r = -EIO; + /* may content plaintext */ + crypt_safe_memzero(data_buffer, rh->length); + goto out; + } + + read = crypt_storage_wrapper_encrypt_write(cw2, 0, data_buffer, rh->length); + /* may content plaintext */ + crypt_safe_memzero(data_buffer, rh->length); + if (read < 0 || (size_t)read != rh->length) { + log_dbg(cd, "recovery write failed."); + r = -EINVAL; + goto out; + } + r = 0; + break; + default: + r = -EINVAL; + } + + if (!r) + rh->read = rh->length; +out: + free(data_buffer); + free(checksum_tmp); + crypt_storage_wrapper_destroy(cw1); + crypt_storage_wrapper_destroy(cw2); + + return r; +} + +static int reencrypt_add_moved_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh) +{ + int s = LUKS2_segment_first_unused_id(hdr); + + if (!rh->jobj_segment_moved) + return 0; + + if (s < 0) + return s; + + if (json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), s, json_object_get(rh->jobj_segment_moved))) { + json_object_put(rh->jobj_segment_moved); + return -EINVAL; + } + + return 0; +} + +static int reencrypt_add_backup_segment(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + unsigned final) +{ + int digest, s = LUKS2_segment_first_unused_id(hdr); + json_object *jobj; + + if (s < 0) + return s; + + digest = final ? rh->digest_new : rh->digest_old; + jobj = final ? rh->jobj_segment_new : rh->jobj_segment_old; + + if (json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), s, json_object_get(jobj))) { + json_object_put(jobj); + return -EINVAL; + } + + if (strcmp(json_segment_type(jobj), "crypt")) + return 0; + + return LUKS2_digest_segment_assign(cd, hdr, s, digest, 1, 0); +} + +static int reencrypt_assign_segments_simple(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + unsigned hot, + unsigned commit) +{ + int r, sg; + + if (hot && json_segments_count(rh->jobj_segs_hot) > 0) { + log_dbg(cd, "Setting 'hot' segments."); + + r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0); + if (!r) + rh->jobj_segs_hot = NULL; + } else if (!hot && json_segments_count(rh->jobj_segs_post) > 0) { + log_dbg(cd, "Setting 'post' segments."); + r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0); + if (!r) + rh->jobj_segs_post = NULL; + } else { + log_dbg(cd, "No segments to set."); + return -EINVAL; + } + + if (r) { + log_dbg(cd, "Failed to assign new enc segments."); + return r; + } + + r = reencrypt_add_backup_segment(cd, hdr, rh, 0); + if (r) { + log_dbg(cd, "Failed to assign reencryption previous backup segment."); + return r; + } + + r = reencrypt_add_backup_segment(cd, hdr, rh, 1); + if (r) { + log_dbg(cd, "Failed to assign reencryption final backup segment."); + return r; + } + + r = reencrypt_add_moved_segment(cd, hdr, rh); + if (r) { + log_dbg(cd, "Failed to assign reencryption moved backup segment."); + return r; + } + + for (sg = 0; sg < LUKS2_segments_count(hdr); sg++) { + if (LUKS2_segment_is_type(hdr, sg, "crypt") && + LUKS2_digest_segment_assign(cd, hdr, sg, rh->mode == CRYPT_REENCRYPT_ENCRYPT ? rh->digest_new : rh->digest_old, 1, 0)) { + log_dbg(cd, "Failed to assign digest %u to segment %u.", rh->digest_new, sg); + return -EINVAL; + } + } + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +static int reencrypt_assign_segments(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + unsigned hot, + unsigned commit) +{ + bool forward; + int rseg, scount, r = -EINVAL; + + /* FIXME: validate in reencrypt context load */ + if (rh->digest_new < 0 && rh->mode != CRYPT_REENCRYPT_DECRYPT) + return -EINVAL; + + if (LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0)) + return -EINVAL; + + if (rh->mode == CRYPT_REENCRYPT_ENCRYPT || rh->mode == CRYPT_REENCRYPT_DECRYPT) + return reencrypt_assign_segments_simple(cd, hdr, rh, hot, commit); + + if (hot && rh->jobj_segs_hot) { + log_dbg(cd, "Setting 'hot' segments."); + + r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0); + if (!r) + rh->jobj_segs_hot = NULL; + } else if (!hot && rh->jobj_segs_post) { + log_dbg(cd, "Setting 'post' segments."); + r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0); + if (!r) + rh->jobj_segs_post = NULL; + } + + if (r) + return r; + + scount = LUKS2_segments_count(hdr); + + /* segment in reencryption has to hold reference on both digests */ + rseg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr)); + if (rseg < 0 && hot) + return -EINVAL; + + if (rseg >= 0) { + LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_new, 1, 0); + LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_old, 1, 0); + } + + forward = (rh->direction == CRYPT_REENCRYPT_FORWARD); + if (hot) { + if (rseg > 0) + LUKS2_digest_segment_assign(cd, hdr, 0, forward ? rh->digest_new : rh->digest_old, 1, 0); + if (scount > rseg + 1) + LUKS2_digest_segment_assign(cd, hdr, rseg + 1, forward ? rh->digest_old : rh->digest_new, 1, 0); + } else { + LUKS2_digest_segment_assign(cd, hdr, 0, forward || scount == 1 ? rh->digest_new : rh->digest_old, 1, 0); + if (scount > 1) + LUKS2_digest_segment_assign(cd, hdr, 1, forward ? rh->digest_old : rh->digest_new, 1, 0); + } + + r = reencrypt_add_backup_segment(cd, hdr, rh, 0); + if (r) { + log_dbg(cd, "Failed to assign hot reencryption backup segment."); + return r; + } + r = reencrypt_add_backup_segment(cd, hdr, rh, 1); + if (r) { + log_dbg(cd, "Failed to assign post reencryption backup segment."); + return r; + } + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t dev_size, uint64_t data_shift, bool move_first_segment, crypt_reencrypt_direction_info di) +{ + int r; + uint64_t first_segment_offset, first_segment_length, + second_segment_offset, second_segment_length, + data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT; + json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments; + + if (dev_size < data_shift) + return -EINVAL; + + if (data_shift && (di == CRYPT_REENCRYPT_FORWARD)) + return -ENOTSUP; + + if (move_first_segment) { + /* + * future data_device layout: + * [future LUKS2 header (data shift size)][second data segment][gap (data shift size)][first data segment (data shift size)] + */ + first_segment_offset = dev_size; + first_segment_length = data_shift; + second_segment_offset = data_shift; + second_segment_length = dev_size - 2 * data_shift; + } else if (data_shift) { + first_segment_offset = data_offset; + first_segment_length = dev_size; + } else { + /* future data_device layout with detached header: [first data segment] */ + first_segment_offset = data_offset; + first_segment_length = 0; /* dynamic */ + } + + jobj_segments = json_object_new_object(); + if (!jobj_segments) + return -ENOMEM; + + r = -EINVAL; + if (move_first_segment) { + jobj_segment_first = json_segment_create_linear(first_segment_offset, &first_segment_length, 0); + if (second_segment_length && + !(jobj_segment_second = json_segment_create_linear(second_segment_offset, &second_segment_length, 0))) { + log_dbg(cd, "Failed generate 2nd segment."); + goto err; + } + } else + jobj_segment_first = json_segment_create_linear(first_segment_offset, first_segment_length ? &first_segment_length : NULL, 0); + + if (!jobj_segment_first) { + log_dbg(cd, "Failed generate 1st segment."); + goto err; + } + + json_object_object_add(jobj_segments, "0", jobj_segment_first); + if (jobj_segment_second) + json_object_object_add(jobj_segments, "1", jobj_segment_second); + + r = LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0); + + if (!r) + r = LUKS2_segments_set(cd, hdr, jobj_segments, 0); +err: + return r; +} + +static int reencrypt_make_targets(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct device *hz_device, + struct volume_key *vks, + struct dm_target *result, + uint64_t size) +{ + bool reenc_seg; + struct volume_key *vk; + uint64_t segment_size, segment_offset, segment_start = 0; + int r; + int s = 0; + json_object *jobj, *jobj_segments = LUKS2_get_segments_jobj(hdr); + + while (result) { + jobj = json_segments_get_segment(jobj_segments, s); + if (!jobj) { + log_dbg(cd, "Internal error. Segment %u is null.", s); + r = -EINVAL; + goto out; + } + + reenc_seg = (s == json_segments_segment_in_reencrypt(jobj_segments)); + + segment_offset = json_segment_get_offset(jobj, 1); + segment_size = json_segment_get_size(jobj, 1); + /* 'dynamic' length allowed in last segment only */ + if (!segment_size && !result->next) + segment_size = (size >> SECTOR_SHIFT) - segment_start; + if (!segment_size) { + log_dbg(cd, "Internal error. Wrong segment size %u", s); + r = -EINVAL; + goto out; + } + + if (!strcmp(json_segment_type(jobj), "crypt")) { + vk = crypt_volume_key_by_id(vks, reenc_seg ? LUKS2_reencrypt_digest_new(hdr) : LUKS2_digest_by_segment(hdr, s)); + if (!vk) { + log_err(cd, _("Missing key for dm-crypt segment %u"), s); + r = -EINVAL; + goto out; + } + + if (reenc_seg) + segment_offset -= crypt_get_data_offset(cd); + + r = dm_crypt_target_set(result, segment_start, segment_size, + reenc_seg ? hz_device : crypt_data_device(cd), + vk, + json_segment_get_cipher(jobj), + json_segment_get_iv_offset(jobj), + segment_offset, + "none", + 0, + json_segment_get_sector_size(jobj)); + if (r) { + log_err(cd, _("Failed to set dm-crypt segment.")); + goto out; + } + } else if (!strcmp(json_segment_type(jobj), "linear")) { + r = dm_linear_target_set(result, segment_start, segment_size, reenc_seg ? hz_device : crypt_data_device(cd), segment_offset); + if (r) { + log_err(cd, _("Failed to set dm-linear segment.")); + goto out; + } + } else { + r = -EINVAL; + goto out; + } + + segment_start += segment_size; + s++; + result = result->next; + } + + return s; +out: + return r; +} + +/* GLOBAL FIXME: audit function names and parameters names */ + +/* FIXME: + * 1) audit log routines + * 2) can't we derive hotzone device name from crypt context? (unlocked name, device uuid, etc?) + */ +static int reencrypt_load_overlay_device(struct crypt_device *cd, struct luks2_hdr *hdr, + const char *overlay, const char *hotzone, struct volume_key *vks, uint64_t size, + uint32_t flags) +{ + char hz_path[PATH_MAX]; + int r; + + struct device *hz_dev = NULL; + struct crypt_dm_active_device dmd = { + .flags = flags, + }; + + log_dbg(cd, "Loading new table for overlay device %s.", overlay); + + r = snprintf(hz_path, PATH_MAX, "%s/%s", dm_get_dir(), hotzone); + if (r < 0 || r >= PATH_MAX) { + r = -EINVAL; + goto out; + } + + r = device_alloc(cd, &hz_dev, hz_path); + if (r) + goto out; + + r = dm_targets_allocate(&dmd.segment, LUKS2_segments_count(hdr)); + if (r) + goto out; + + r = reencrypt_make_targets(cd, hdr, hz_dev, vks, &dmd.segment, size); + if (r < 0) + goto out; + + r = dm_reload_device(cd, overlay, &dmd, 0, 0); + + /* what else on error here ? */ +out: + dm_targets_free(cd, &dmd); + device_free(cd, hz_dev); + + return r; +} + +static int reencrypt_replace_device(struct crypt_device *cd, const char *target, const char *source, uint32_t flags) +{ + int r, exists = 1; + struct crypt_dm_active_device dmd_source, dmd_target = {}; + uint32_t dmflags = DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH; + + log_dbg(cd, "Replacing table in device %s with table from device %s.", target, source); + + /* check only whether target device exists */ + r = dm_status_device(cd, target); + if (r < 0) { + if (r == -ENODEV) + exists = 0; + else + return r; + } + + r = dm_query_device(cd, source, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER | + DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmd_source); + + if (r < 0) + return r; + + if (exists && ((r = dm_query_device(cd, target, 0, &dmd_target)) < 0)) + goto err; + + dmd_source.flags |= flags; + dmd_source.uuid = crypt_get_uuid(cd); + + if (exists) { + if (dmd_target.size != dmd_source.size) { + log_err(cd, _("Source and target device sizes don't match. Source %" PRIu64 ", target: %" PRIu64 "."), + dmd_source.size, dmd_target.size); + r = -EINVAL; + goto err; + } + r = dm_reload_device(cd, target, &dmd_source, 0, 0); + if (!r) { + log_dbg(cd, "Resuming device %s", target); + r = dm_resume_device(cd, target, dmflags | act2dmflags(dmd_source.flags)); + } + } else + r = dm_create_device(cd, target, CRYPT_SUBDEV, &dmd_source); +err: + dm_targets_free(cd, &dmd_source); + dm_targets_free(cd, &dmd_target); + + return r; +} + +static int reencrypt_swap_backing_device(struct crypt_device *cd, const char *name, + const char *new_backend_name) +{ + int r; + struct device *overlay_dev = NULL; + char overlay_path[PATH_MAX] = { 0 }; + struct crypt_dm_active_device dmd = {}; + + log_dbg(cd, "Redirecting %s mapping to new backing device: %s.", name, new_backend_name); + + r = snprintf(overlay_path, PATH_MAX, "%s/%s", dm_get_dir(), new_backend_name); + if (r < 0 || r >= PATH_MAX) { + r = -EINVAL; + goto out; + } + + r = device_alloc(cd, &overlay_dev, overlay_path); + if (r) + goto out; + + r = device_block_adjust(cd, overlay_dev, DEV_OK, + 0, &dmd.size, &dmd.flags); + if (r) + goto out; + + r = dm_linear_target_set(&dmd.segment, 0, dmd.size, overlay_dev, 0); + if (r) + goto out; + + r = dm_reload_device(cd, name, &dmd, 0, 0); + if (!r) { + log_dbg(cd, "Resuming device %s", name); + r = dm_resume_device(cd, name, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH); + } + +out: + dm_targets_free(cd, &dmd); + device_free(cd, overlay_dev); + + return r; +} + +static int reencrypt_activate_hotzone_device(struct crypt_device *cd, const char *name, uint64_t device_size, uint32_t flags) +{ + int r; + uint64_t new_offset = reencrypt_get_data_offset_new(crypt_get_hdr(cd, CRYPT_LUKS2)) >> SECTOR_SHIFT; + + struct crypt_dm_active_device dmd = { + .flags = flags, + .uuid = crypt_get_uuid(cd), + .size = device_size >> SECTOR_SHIFT + }; + + log_dbg(cd, "Activating hotzone device %s.", name); + + r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK, + new_offset, &dmd.size, &dmd.flags); + if (r) + goto err; + + r = dm_linear_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), new_offset); + if (r) + goto err; + + r = dm_create_device(cd, name, CRYPT_SUBDEV, &dmd); +err: + dm_targets_free(cd, &dmd); + + return r; +} + +static int reencrypt_init_device_stack(struct crypt_device *cd, + const struct luks2_reenc_context *rh) +{ + int r; + + /* Activate hotzone device 1:1 linear mapping to data_device */ + r = reencrypt_activate_hotzone_device(cd, rh->hotzone_name, rh->device_size, CRYPT_ACTIVATE_PRIVATE); + if (r) { + log_err(cd, _("Failed to activate hotzone device %s."), rh->hotzone_name); + return r; + } + + /* + * Activate overlay device with exactly same table as original 'name' mapping. + * Note that within this step the 'name' device may already include a table + * constructed from more than single dm-crypt segment. Therefore transfer + * mapping as is. + * + * If we're about to resume reencryption orig mapping has to be already validated for + * abrupt shutdown and rchunk_offset has to point on next chunk to reencrypt! + * + * TODO: in crypt_activate_by* + */ + r = reencrypt_replace_device(cd, rh->overlay_name, rh->device_name, CRYPT_ACTIVATE_PRIVATE); + if (r) { + log_err(cd, _("Failed to activate overlay device %s with actual origin table."), rh->overlay_name); + goto err; + } + + /* swap origin mapping to overlay device */ + r = reencrypt_swap_backing_device(cd, rh->device_name, rh->overlay_name); + if (r) { + log_err(cd, _("Failed to load new mapping for device %s."), rh->device_name); + goto err; + } + + /* + * Now the 'name' (unlocked luks) device is mapped via dm-linear to an overlay dev. + * The overlay device has a original live table of 'name' device in-before the swap. + */ + + return 0; +err: + /* TODO: force error helper devices on error path */ + dm_remove_device(cd, rh->overlay_name, 0); + dm_remove_device(cd, rh->hotzone_name, 0); + + return r; +} + +/* TODO: + * 1) audit error path. any error in this routine is fatal and should be unlikely. + * usually it would hint some collision with another userspace process touching + * dm devices directly. + */ +static int reenc_refresh_helper_devices(struct crypt_device *cd, const char *overlay, const char *hotzone) +{ + int r; + + /* + * we have to explicitly suspend the overlay device before suspending + * the hotzone one. Resuming overlay device (aka switching tables) only + * after suspending the hotzone may lead to deadlock. + * + * In other words: always suspend the stack from top to bottom! + */ + r = dm_suspend_device(cd, overlay, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH); + if (r) { + log_err(cd, _("Failed to suspend device %s."), overlay); + return r; + } + + /* suspend HZ device */ + r = dm_suspend_device(cd, hotzone, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH); + if (r) { + log_err(cd, _("Failed to suspend device %s."), hotzone); + return r; + } + + /* resume overlay device: inactive table (with hotozne) -> live */ + r = dm_resume_device(cd, overlay, DM_RESUME_PRIVATE); + if (r) + log_err(cd, _("Failed to resume device %s."), overlay); + + return r; +} + +static int reencrypt_refresh_overlay_devices(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *overlay, + const char *hotzone, + struct volume_key *vks, + uint64_t device_size, + uint32_t flags) +{ + int r = reencrypt_load_overlay_device(cd, hdr, overlay, hotzone, vks, device_size, flags); + if (r) { + log_err(cd, _("Failed to reload device %s."), overlay); + return REENC_ERR; + } + + r = reenc_refresh_helper_devices(cd, overlay, hotzone); + if (r) { + log_err(cd, _("Failed to refresh reencryption devices stack.")); + return REENC_ROLLBACK; + } + + return REENC_OK; +} + +static int reencrypt_move_data(struct crypt_device *cd, int devfd, uint64_t data_shift) +{ + void *buffer; + int r; + ssize_t ret; + uint64_t buffer_len, offset; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + log_dbg(cd, "Going to move data from head of data device."); + + buffer_len = data_shift; + if (!buffer_len) + return -EINVAL; + + offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0); + + /* this is nonsense anyway */ + if (buffer_len != json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0)) { + log_dbg(cd, "buffer_len %" PRIu64", segment size %" PRIu64, buffer_len, json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0)); + return -EINVAL; + } + + if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buffer_len)) + return -ENOMEM; + + ret = read_lseek_blockwise(devfd, + device_block_size(cd, crypt_data_device(cd)), + device_alignment(crypt_data_device(cd)), + buffer, buffer_len, 0); + if (ret < 0 || (uint64_t)ret != buffer_len) { + r = -EIO; + goto err; + } + + log_dbg(cd, "Going to write %" PRIu64 " bytes at offset %" PRIu64, buffer_len, offset); + ret = write_lseek_blockwise(devfd, + device_block_size(cd, crypt_data_device(cd)), + device_alignment(crypt_data_device(cd)), + buffer, buffer_len, offset); + if (ret < 0 || (uint64_t)ret != buffer_len) { + r = -EIO; + goto err; + } + + r = 0; +err: + memset(buffer, 0, buffer_len); + free(buffer); + return r; +} + +static int reencrypt_make_backup_segments(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot_new, + const char *cipher, + uint64_t data_offset, + const struct crypt_params_reencrypt *params) +{ + int r, segment, moved_segment = -1, digest_old = -1, digest_new = -1; + json_object *jobj_segment_new = NULL, *jobj_segment_old = NULL, *jobj_segment_bcp = NULL; + uint32_t sector_size = params->luks2 ? params->luks2->sector_size : SECTOR_SIZE; + uint64_t segment_offset, tmp, data_shift = params->data_shift << SECTOR_SHIFT; + + if (params->mode != CRYPT_REENCRYPT_DECRYPT) { + digest_new = LUKS2_digest_by_keyslot(hdr, keyslot_new); + if (digest_new < 0) + return -EINVAL; + } + + if (params->mode != CRYPT_REENCRYPT_ENCRYPT) { + digest_old = LUKS2_digest_by_segment(hdr, CRYPT_DEFAULT_SEGMENT); + if (digest_old < 0) + return -EINVAL; + } + + segment = LUKS2_segment_first_unused_id(hdr); + if (segment < 0) + return -EINVAL; + + if (params->mode == CRYPT_REENCRYPT_ENCRYPT && + (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT)) { + json_object_copy(LUKS2_get_segment_jobj(hdr, 0), &jobj_segment_bcp); + r = LUKS2_segment_set_flag(jobj_segment_bcp, "backup-moved-segment"); + if (r) + goto err; + moved_segment = segment++; + json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), moved_segment, jobj_segment_bcp); + } + + /* FIXME: Add detection for case (digest old == digest new && old segment == new segment) */ + if (digest_old >= 0) + json_object_copy(LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT), &jobj_segment_old); + else if (params->mode == CRYPT_REENCRYPT_ENCRYPT) { + r = LUKS2_get_data_size(hdr, &tmp, NULL); + if (r) + goto err; + jobj_segment_old = json_segment_create_linear(0, tmp ? &tmp : NULL, 0); + } + + if (!jobj_segment_old) { + r = -EINVAL; + goto err; + } + + r = LUKS2_segment_set_flag(jobj_segment_old, "backup-previous"); + if (r) + goto err; + json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_old); + jobj_segment_old = NULL; + if (digest_old >= 0) + LUKS2_digest_segment_assign(cd, hdr, segment, digest_old, 1, 0); + segment++; + + if (digest_new >= 0) { + segment_offset = data_offset; + if (params->mode != CRYPT_REENCRYPT_ENCRYPT && + modify_offset(&segment_offset, data_shift, params->direction)) { + r = -EINVAL; + goto err; + } + jobj_segment_new = json_segment_create_crypt(segment_offset, + crypt_get_iv_offset(cd), + NULL, cipher, sector_size, 0); + } else if (params->mode == CRYPT_REENCRYPT_DECRYPT) { + segment_offset = data_offset; + if (modify_offset(&segment_offset, data_shift, params->direction)) { + r = -EINVAL; + goto err; + } + jobj_segment_new = json_segment_create_linear(segment_offset, NULL, 0); + } + + if (!jobj_segment_new) { + r = -EINVAL; + goto err; + } + + r = LUKS2_segment_set_flag(jobj_segment_new, "backup-final"); + if (r) + goto err; + json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_new); + jobj_segment_new = NULL; + if (digest_new >= 0) + LUKS2_digest_segment_assign(cd, hdr, segment, digest_new, 1, 0); + + /* FIXME: also check occupied space by keyslot in shrunk area */ + if (params->direction == CRYPT_REENCRYPT_FORWARD && data_shift && + crypt_metadata_device(cd) == crypt_data_device(cd) && + LUKS2_set_keyslots_size(cd, hdr, json_segment_get_offset(reencrypt_segment_new(hdr), 0))) { + log_err(cd, _("Failed to set new keyslots area size.")); + r = -EINVAL; + goto err; + } + + return 0; +err: + json_object_put(jobj_segment_new); + json_object_put(jobj_segment_old); + return r; +} + +static int reencrypt_verify_and_upload_keys(struct crypt_device *cd, struct luks2_hdr *hdr, int digest_old, int digest_new, struct volume_key *vks) +{ + int r; + struct volume_key *vk; + + if (digest_new >= 0) { + vk = crypt_volume_key_by_id(vks, digest_new); + if (!vk) + return -ENOENT; + else { + if (LUKS2_digest_verify_by_digest(cd, hdr, digest_new, vk) != digest_new) + return -EINVAL; + + if (crypt_use_keyring_for_vk(cd) && + (r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk)))) + return r; + } + } + + if (digest_old >= 0 && digest_old != digest_new) { + vk = crypt_volume_key_by_id(vks, digest_old); + if (!vk) { + r = -ENOENT; + goto err; + } else { + if (LUKS2_digest_verify_by_digest(cd, hdr, digest_old, vk) != digest_old) { + r = -EINVAL; + goto err; + } + if (crypt_use_keyring_for_vk(cd) && + (r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk)))) + goto err; + } + } + + return 0; +err: + crypt_drop_keyring_key(cd, vks); + return r; +} + +/* This function must be called with metadata lock held */ +static int reencrypt_init(struct crypt_device *cd, + const char *name, + struct luks2_hdr *hdr, + const char *passphrase, + size_t passphrase_size, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params, + struct volume_key **vks) +{ + bool move_first_segment; + char _cipher[128]; + uint32_t sector_size; + int r, reencrypt_keyslot, devfd = -1; + uint64_t data_offset, dev_size = 0; + struct crypt_dm_active_device dmd_target, dmd_source = { + .uuid = crypt_get_uuid(cd), + .flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */ + }; + + if (!params || params->mode > CRYPT_REENCRYPT_DECRYPT) + return -EINVAL; + + if (params->mode != CRYPT_REENCRYPT_DECRYPT && + (!params->luks2 || !(cipher && cipher_mode) || keyslot_new < 0)) + return -EINVAL; + + log_dbg(cd, "Initializing reencryption (mode: %s) in LUKS2 metadata.", + crypt_reencrypt_mode_to_str(params->mode)); + + move_first_segment = (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT); + + /* implicit sector size 512 for decryption */ + sector_size = params->luks2 ? params->luks2->sector_size : SECTOR_SIZE; + if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE || + NOTPOW2(sector_size)) { + log_err(cd, _("Unsupported encryption sector size.")); + return -EINVAL; + } + + if (!cipher_mode || *cipher_mode == '\0') + snprintf(_cipher, sizeof(_cipher), "%s", cipher); + else + snprintf(_cipher, sizeof(_cipher), "%s-%s", cipher, cipher_mode); + + if (MISALIGNED(params->data_shift, sector_size >> SECTOR_SHIFT)) { + log_err(cd, _("Data shift is not aligned to requested encryption sector size (%" PRIu32 " bytes)."), sector_size); + return -EINVAL; + } + + data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT; + + r = device_check_access(cd, crypt_data_device(cd), DEV_OK); + if (r) + return r; + + r = device_check_size(cd, crypt_data_device(cd), data_offset, 1); + if (r) + return r; + + r = device_size(crypt_data_device(cd), &dev_size); + if (r) + return r; + + dev_size -= data_offset; + + if (MISALIGNED(dev_size, sector_size)) { + log_err(cd, _("Data device is not aligned to requested encryption sector size (%" PRIu32 " bytes)."), sector_size); + return -EINVAL; + } + + reencrypt_keyslot = LUKS2_keyslot_find_empty(hdr); + if (reencrypt_keyslot < 0) { + log_err(cd, _("All key slots full.")); + return -EINVAL; + } + + /* + * We must perform data move with exclusive open data device + * to exclude another cryptsetup process to colide with + * encryption initialization (or mount) + */ + if (move_first_segment) { + if (dev_size < 2 * (params->data_shift << SECTOR_SHIFT)) { + log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd))); + return -EINVAL; + } + if (params->data_shift < LUKS2_get_data_offset(hdr)) { + log_err(cd, _("Data shift (%" PRIu64 " sectors) is less than future data offset (%" PRIu64 " sectors)."), params->data_shift, LUKS2_get_data_offset(hdr)); + return -EINVAL; + } + devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR); + if (devfd < 0) { + if (devfd == -EBUSY) + log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd))); + return -EINVAL; + } + } + + if (params->mode == CRYPT_REENCRYPT_ENCRYPT) { + /* in-memory only */ + r = reencrypt_set_encrypt_segments(cd, hdr, dev_size, params->data_shift << SECTOR_SHIFT, move_first_segment, params->direction); + if (r) + goto err; + } + + r = LUKS2_keyslot_reencrypt_create(cd, hdr, reencrypt_keyslot, + params); + if (r < 0) + goto err; + + r = reencrypt_make_backup_segments(cd, hdr, keyslot_new, _cipher, data_offset, params); + if (r) { + log_dbg(cd, "Failed to create reencryption backup device segments."); + goto err; + } + + r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, vks); + if (r < 0) + goto err; + + if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) { + r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks); + if (r) + goto err; + + r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE | + DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY | + DM_ACTIVE_CRYPT_CIPHER, &dmd_target); + if (r < 0) + goto err; + + r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source); + if (!r) { + r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target); + if (r) + log_err(cd, _("Mismatching parameters on device %s."), name); + } + + dm_targets_free(cd, &dmd_source); + dm_targets_free(cd, &dmd_target); + free(CONST_CAST(void*)dmd_target.uuid); + + if (r) + goto err; + } + + if (move_first_segment && reencrypt_move_data(cd, devfd, params->data_shift << SECTOR_SHIFT)) { + r = -EIO; + goto err; + } + + /* This must be first and only write in LUKS2 metadata during _reencrypt_init */ + r = reencrypt_update_flag(cd, 1, true); + if (r) { + log_dbg(cd, "Failed to set online-reencryption requirement."); + r = -EINVAL; + } else + r = reencrypt_keyslot; +err: + device_release_excl(cd, crypt_data_device(cd)); + if (r < 0) + crypt_load(cd, CRYPT_LUKS2, NULL); + + return r; +} + +static int reencrypt_hotzone_protect_final(struct crypt_device *cd, + struct luks2_hdr *hdr, struct luks2_reenc_context *rh, + const void *buffer, size_t buffer_len) +{ + const void *pbuffer; + size_t data_offset, len; + int r; + + if (rh->rp.type == REENC_PROTECTION_NONE) + return 0; + + if (rh->rp.type == REENC_PROTECTION_CHECKSUM) { + log_dbg(cd, "Checksums hotzone resilience."); + + for (data_offset = 0, len = 0; data_offset < buffer_len; data_offset += rh->alignment, len += rh->rp.p.csum.hash_size) { + if (crypt_hash_write(rh->rp.p.csum.ch, (const char *)buffer + data_offset, rh->alignment)) { + log_dbg(cd, "Failed to hash sector at offset %zu.", data_offset); + return -EINVAL; + } + if (crypt_hash_final(rh->rp.p.csum.ch, (char *)rh->rp.p.csum.checksums + len, rh->rp.p.csum.hash_size)) { + log_dbg(cd, "Failed to finalize hash."); + return -EINVAL; + } + } + pbuffer = rh->rp.p.csum.checksums; + } else if (rh->rp.type == REENC_PROTECTION_JOURNAL) { + log_dbg(cd, "Journal hotzone resilience."); + len = buffer_len; + pbuffer = buffer; + } else if (rh->rp.type == REENC_PROTECTION_DATASHIFT) { + log_dbg(cd, "Data shift hotzone resilience."); + return LUKS2_hdr_write(cd, hdr); + } else + return -EINVAL; + + log_dbg(cd, "Going to store %zu bytes in reencrypt keyslot.", len); + + r = LUKS2_keyslot_reencrypt_store(cd, hdr, rh->reenc_keyslot, pbuffer, len); + + return r > 0 ? 0 : r; +} + +static int reencrypt_context_update(struct crypt_device *cd, + struct luks2_reenc_context *rh) +{ + if (rh->read < 0) + return -EINVAL; + + if (rh->direction == CRYPT_REENCRYPT_BACKWARD) { + if (rh->data_shift && rh->mode == CRYPT_REENCRYPT_ENCRYPT) { + if (rh->offset) + rh->offset -= rh->data_shift; + if (rh->offset && (rh->offset < rh->data_shift)) { + rh->length = rh->offset; + rh->offset = rh->data_shift; + } + if (!rh->offset) + rh->length = rh->data_shift; + } else { + if (rh->offset < rh->length) + rh->length = rh->offset; + rh->offset -= rh->length; + } + } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) { + rh->offset += (uint64_t)rh->read; + /* it fails in-case of device_size < rh->offset later */ + if (rh->device_size - rh->offset < rh->length) + rh->length = rh->device_size - rh->offset; + } else + return -EINVAL; + + if (rh->device_size < rh->offset) { + log_dbg(cd, "Calculated reencryption offset %" PRIu64 " is beyond device size %" PRIu64 ".", rh->offset, rh->device_size); + return -EINVAL; + } + + rh->progress += (uint64_t)rh->read; + + return 0; +} + +static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr, + uint64_t device_size, + const struct crypt_params_reencrypt *params, + struct luks2_reenc_context **rh) +{ + int r; + struct luks2_reenc_context *tmp = NULL; + crypt_reencrypt_info ri = LUKS2_reenc_status(hdr); + + if (ri == CRYPT_REENCRYPT_CLEAN) + r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params); + else if (ri == CRYPT_REENCRYPT_CRASH) + r = reencrypt_load_crashed(cd, hdr, device_size, &tmp); + else if (ri == CRYPT_REENCRYPT_NONE) { + log_err(cd, _("Device not marked for LUKS2 reencryption.")); + return -EINVAL; + } else + r = -EINVAL; + + if (r < 0 || !tmp) { + log_err(cd, _("Failed to load LUKS2 reencryption context.")); + return r; + } + + *rh = tmp; + + return 0; +} + +static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock) +{ + int r; + char *lock_resource; + + if (!crypt_metadata_locking_enabled()) { + *reencrypt_lock = NULL; + return 0; + } + + r = asprintf(&lock_resource, "LUKS2-reencryption-%s", uuid); + if (r < 0) + return -ENOMEM; + if (r < 20) { + r = -EINVAL; + goto out; + } + + r = crypt_write_lock(cd, lock_resource, false, reencrypt_lock); +out: + free(lock_resource); + + return r; +} + +/* internal only */ +int crypt_reencrypt_lock_by_dm_uuid(struct crypt_device *cd, const char *dm_uuid, struct crypt_lock_handle **reencrypt_lock) +{ + int r; + char hdr_uuid[37]; + const char *uuid = crypt_get_uuid(cd); + + if (!dm_uuid) + return -EINVAL; + + if (!uuid) { + r = snprintf(hdr_uuid, sizeof(hdr_uuid), "%.8s-%.4s-%.4s-%.4s-%.12s", + dm_uuid + 6, dm_uuid + 14, dm_uuid + 18, dm_uuid + 22, dm_uuid + 26); + if (r < 0 || (size_t)r != (sizeof(hdr_uuid) - 1)) + return -EINVAL; + } else if (crypt_uuid_cmp(dm_uuid, uuid)) + return -EINVAL; + + return reencrypt_lock_internal(cd, uuid, reencrypt_lock); +} + +/* internal only */ +int crypt_reencrypt_lock(struct crypt_device *cd, struct crypt_lock_handle **reencrypt_lock) +{ + if (!cd || !crypt_get_type(cd) || strcmp(crypt_get_type(cd), CRYPT_LUKS2)) + return -EINVAL; + + return reencrypt_lock_internal(cd, crypt_get_uuid(cd), reencrypt_lock); +} + +/* internal only */ +void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock) +{ + crypt_unlock_internal(cd, reencrypt_lock); +} + +static int reencrypt_lock_and_verify(struct crypt_device *cd, struct luks2_hdr *hdr, + struct crypt_lock_handle **reencrypt_lock) +{ + int r; + crypt_reencrypt_info ri; + struct crypt_lock_handle *h; + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_INVALID) { + log_err(cd, _("Failed to get reencryption state.")); + return -EINVAL; + } + if (ri < CRYPT_REENCRYPT_CLEAN) { + log_err(cd, _("Device is not in reencryption.")); + return -EINVAL; + } + + r = crypt_reencrypt_lock(cd, &h); + if (r < 0) { + if (r == -EBUSY) + log_err(cd, _("Reencryption process is already running.")); + else + log_err(cd, _("Failed to acquire reencryption lock.")); + return r; + } + + /* With reencryption lock held, reload device context and verify metadata state */ + r = crypt_load(cd, CRYPT_LUKS2, NULL); + if (r) { + crypt_reencrypt_unlock(cd, h); + return r; + } + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_CLEAN) { + *reencrypt_lock = h; + return 0; + } + + crypt_reencrypt_unlock(cd, h); + log_err(cd, _("Cannot proceed with reencryption. Run reencryption recovery first.")); + return -EINVAL; +} + +static int reencrypt_load_by_passphrase(struct crypt_device *cd, + const char *name, + const char *passphrase, + size_t passphrase_size, + int keyslot_old, + int keyslot_new, + struct volume_key **vks, + const struct crypt_params_reencrypt *params) +{ + int r, old_ss, new_ss; + struct luks2_hdr *hdr; + struct crypt_lock_handle *reencrypt_lock; + struct luks2_reenc_context *rh; + struct crypt_dm_active_device dmd_target, dmd_source = { + .uuid = crypt_get_uuid(cd), + .flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */ + }; + uint64_t minimal_size, device_size, mapping_size = 0, required_size = 0; + bool dynamic; + struct crypt_params_reencrypt rparams = {}; + uint32_t flags = 0; + + if (params) { + rparams = *params; + required_size = params->device_size; + } + + log_dbg(cd, "Loading LUKS2 reencryption context."); + + rh = crypt_get_reenc_context(cd); + if (rh) { + LUKS2_reenc_context_free(cd, rh); + crypt_set_reenc_context(cd, NULL); + rh = NULL; + } + + hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + r = reencrypt_lock_and_verify(cd, hdr, &reencrypt_lock); + if (r) + return r; + + /* From now on we hold reencryption lock */ + + if (LUKS2_get_data_size(hdr, &minimal_size, &dynamic)) + return -EINVAL; + + /* some configurations provides fixed device size */ + r = luks2_check_device_size(cd, hdr, minimal_size, &device_size, false, dynamic); + if (r) { + r = -EINVAL; + goto err; + } + + minimal_size >>= SECTOR_SHIFT; + + old_ss = reencrypt_get_sector_size_old(hdr); + new_ss = reencrypt_get_sector_size_new(hdr); + + r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks); + if (r == -ENOENT) { + log_dbg(cd, "Keys are not ready. Unlocking all volume keys."); + r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, vks); + if (r < 0) + goto err; + r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks); + } + + if (r < 0) + goto err; + + if (name) { + r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE | + DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY | + DM_ACTIVE_CRYPT_CIPHER, &dmd_target); + if (r < 0) + goto err; + flags = dmd_target.flags; + + r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source); + if (!r) { + r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target); + if (r) + log_err(cd, _("Mismatching parameters on device %s."), name); + } + + dm_targets_free(cd, &dmd_source); + dm_targets_free(cd, &dmd_target); + free(CONST_CAST(void*)dmd_target.uuid); + if (r) + goto err; + mapping_size = dmd_target.size; + } + + r = -EINVAL; + if (required_size && mapping_size && (required_size != mapping_size)) { + log_err(cd, _("Active device size and requested reencryption size don't match.")); + goto err; + } + + if (mapping_size) + required_size = mapping_size; + + if (required_size) { + /* TODO: Add support for changing fixed minimal size in reencryption mda where possible */ + if ((minimal_size && (required_size < minimal_size)) || + (required_size > (device_size >> SECTOR_SHIFT)) || + (!dynamic && (required_size != minimal_size)) || + (old_ss > 0 && MISALIGNED(required_size, old_ss >> SECTOR_SHIFT)) || + (new_ss > 0 && MISALIGNED(required_size, new_ss >> SECTOR_SHIFT))) { + log_err(cd, _("Illegal device size requested in reencryption parameters.")); + goto err; + } + rparams.device_size = required_size; + } + + r = reencrypt_load(cd, hdr, device_size, &rparams, &rh); + if (r < 0 || !rh) + goto err; + + if (name && (r = reencrypt_context_set_names(rh, name))) + goto err; + + /* Reassure device is not mounted and there's no dm mapping active */ + if (!name && (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0)) { + log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd))); + r = -EBUSY; + goto err; + } + device_release_excl(cd, crypt_data_device(cd)); + + /* FIXME: There's a race for dm device activation not managed by cryptsetup. + * + * 1) excl close + * 2) rogue dm device activation + * 3) one or more dm-crypt based wrapper activation + * 4) next excl open get's skipped due to 3) device from 2) remains undetected. + */ + r = reencrypt_init_storage_wrappers(cd, hdr, rh, *vks); + if (r) + goto err; + + /* If one of wrappers is based on dmcrypt fallback it already blocked mount */ + if (!name && crypt_storage_wrapper_get_type(rh->cw1) != DMCRYPT && + crypt_storage_wrapper_get_type(rh->cw2) != DMCRYPT) { + if (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0) { + log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd))); + r = -EBUSY; + goto err; + } + } + + rh->flags = flags; + + MOVE_REF(rh->vks, *vks); + MOVE_REF(rh->reenc_lock, reencrypt_lock); + + crypt_set_reenc_context(cd, rh); + + return 0; +err: + crypt_reencrypt_unlock(cd, reencrypt_lock); + LUKS2_reenc_context_free(cd, rh); + return r; +} + +static int reencrypt_recovery_by_passphrase(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot_old, + int keyslot_new, + const char *passphrase, + size_t passphrase_size) +{ + int r; + crypt_reencrypt_info ri; + struct crypt_lock_handle *reencrypt_lock; + + r = crypt_reencrypt_lock(cd, &reencrypt_lock); + if (r) { + if (r == -EBUSY) + log_err(cd, _("Reencryption in-progress. Cannot perform recovery.")); + else + log_err(cd, _("Failed to get reencryption lock.")); + return r; + } + + if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) { + crypt_reencrypt_unlock(cd, reencrypt_lock); + return r; + } + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_INVALID) { + crypt_reencrypt_unlock(cd, reencrypt_lock); + return -EINVAL; + } + + if (ri == CRYPT_REENCRYPT_CRASH) { + r = LUKS2_reencrypt_locked_recovery_by_passphrase(cd, keyslot_old, keyslot_new, + passphrase, passphrase_size, 0, NULL); + if (r < 0) + log_err(cd, _("LUKS2 reencryption recovery failed.")); + } else { + log_dbg(cd, "No LUKS2 reencryption recovery needed."); + r = 0; + } + + crypt_reencrypt_unlock(cd, reencrypt_lock); + return r; +} + +static int reencrypt_init_by_passphrase(struct crypt_device *cd, + const char *name, + const char *passphrase, + size_t passphrase_size, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params) +{ + int r; + crypt_reencrypt_info ri; + struct volume_key *vks = NULL; + uint32_t flags = params ? params->flags : 0; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + /* short-circuit in recovery and finish immediately. */ + if (flags & CRYPT_REENCRYPT_RECOVERY) + return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size); + + if (cipher) { + r = crypt_keyslot_get_key_size(cd, keyslot_new); + if (r < 0) + return r; + r = LUKS2_check_cipher(cd, r, cipher, cipher_mode); + if (r < 0) + return r; + } + + r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd)); + if (r) + return r; + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_INVALID) { + device_write_unlock(cd, crypt_metadata_device(cd)); + return -EINVAL; + } + + if ((ri > CRYPT_REENCRYPT_NONE) && (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY)) { + device_write_unlock(cd, crypt_metadata_device(cd)); + log_err(cd, _("LUKS2 reencryption already initialized in metadata.")); + return -EBUSY; + } + + if (ri == CRYPT_REENCRYPT_NONE && !(flags & CRYPT_REENCRYPT_RESUME_ONLY)) { + r = reencrypt_init(cd, name, hdr, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params, &vks); + if (r < 0) + log_err(cd, _("Failed to initialize LUKS2 reencryption in metadata.")); + } else if (ri > CRYPT_REENCRYPT_NONE) { + log_dbg(cd, "LUKS2 reencryption already initialized."); + r = 0; + } + + device_write_unlock(cd, crypt_metadata_device(cd)); + + if (r < 0 || (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY)) + goto out; + + r = reencrypt_load_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, &vks, params); +out: + if (r < 0) + crypt_drop_keyring_key(cd, vks); + crypt_free_volume_key(vks); + return r < 0 ? r : LUKS2_find_keyslot(hdr, "reencrypt"); +} + +int crypt_reencrypt_init_by_keyring(struct crypt_device *cd, + const char *name, + const char *passphrase_description, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params) +{ + int r; + char *passphrase; + size_t passphrase_size; + + if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase_description) + return -EINVAL; + if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY)) + return -EINVAL; + + r = keyring_get_passphrase(passphrase_description, &passphrase, &passphrase_size); + if (r < 0) { + log_err(cd, _("Failed to read passphrase from keyring (error %d)."), r); + return -EINVAL; + } + + r = reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params); + + crypt_safe_memzero(passphrase, passphrase_size); + free(passphrase); + + return r; +} + +int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd, + const char *name, + const char *passphrase, + size_t passphrase_size, + int keyslot_old, + int keyslot_new, + const char *cipher, + const char *cipher_mode, + const struct crypt_params_reencrypt *params) +{ + if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase) + return -EINVAL; + if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY)) + return -EINVAL; + + return reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params); +} + +static reenc_status_t reencrypt_step(struct crypt_device *cd, + struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, + uint64_t device_size, + bool online) +{ + int r; + + /* update reencrypt keyslot protection parameters in memory only */ + r = reenc_keyslot_update(cd, rh); + if (r < 0) { + log_dbg(cd, "Keyslot update failed."); + return REENC_ERR; + } + + /* in memory only */ + r = reencrypt_make_segments(cd, hdr, rh, device_size); + if (r) + return REENC_ERR; + + r = reencrypt_assign_segments(cd, hdr, rh, 1, 0); + if (r) { + log_err(cd, _("Failed to set device segments for next reencryption hotzone.")); + return REENC_ERR; + } + + if (online) { + r = reencrypt_refresh_overlay_devices(cd, hdr, rh->overlay_name, rh->hotzone_name, rh->vks, rh->device_size, rh->flags); + /* Teardown overlay devices with dm-error. None bio shall pass! */ + if (r != REENC_OK) + return r; + } + + log_dbg(cd, "Reencrypting chunk starting at offset: %" PRIu64 ", size :%" PRIu64 ".", rh->offset, rh->length); + log_dbg(cd, "data_offset: %" PRIu64, crypt_get_data_offset(cd) << SECTOR_SHIFT); + + if (!rh->offset && rh->mode == CRYPT_REENCRYPT_ENCRYPT && rh->data_shift && + rh->jobj_segment_moved) { + crypt_storage_wrapper_destroy(rh->cw1); + log_dbg(cd, "Reinitializing old segment storage wrapper for moved segment."); + r = crypt_storage_wrapper_init(cd, &rh->cw1, crypt_data_device(cd), + LUKS2_reencrypt_get_data_offset_moved(hdr), + crypt_get_iv_offset(cd), + reencrypt_get_sector_size_old(hdr), + reencrypt_segment_cipher_old(hdr), + crypt_volume_key_by_id(rh->vks, rh->digest_old), + rh->wflags1); + if (r) { + log_err(cd, _("Failed to initialize old segment storage wrapper.")); + return REENC_ROLLBACK; + } + } + + rh->read = crypt_storage_wrapper_read(rh->cw1, rh->offset, rh->reenc_buffer, rh->length); + if (rh->read < 0) { + /* severity normal */ + log_err(cd, _("Failed to read hotzone area starting at %" PRIu64 "."), rh->offset); + return REENC_ROLLBACK; + } + + /* metadata commit point */ + r = reencrypt_hotzone_protect_final(cd, hdr, rh, rh->reenc_buffer, rh->read); + if (r < 0) { + /* severity normal */ + log_err(cd, _("Failed to write reencryption resilience metadata.")); + return REENC_ROLLBACK; + } + + r = crypt_storage_wrapper_decrypt(rh->cw1, rh->offset, rh->reenc_buffer, rh->read); + if (r) { + /* severity normal */ + log_err(cd, _("Decryption failed.")); + return REENC_ROLLBACK; + } + if (rh->read != crypt_storage_wrapper_encrypt_write(rh->cw2, rh->offset, rh->reenc_buffer, rh->read)) { + /* severity fatal */ + log_err(cd, _("Failed to write hotzone area starting at %" PRIu64 "."), rh->offset); + return REENC_FATAL; + } + + if (rh->rp.type != REENC_PROTECTION_NONE && crypt_storage_wrapper_datasync(rh->cw2)) { + log_err(cd, _("Failed to sync data.")); + return REENC_FATAL; + } + + /* metadata commit safe point */ + r = reencrypt_assign_segments(cd, hdr, rh, 0, rh->rp.type != REENC_PROTECTION_NONE); + if (r) { + /* severity fatal */ + log_err(cd, _("Failed to update metadata after current reencryption hotzone completed.")); + return REENC_FATAL; + } + + if (online) { + /* severity normal */ + log_dbg(cd, "Resuming device %s", rh->hotzone_name); + r = dm_resume_device(cd, rh->hotzone_name, DM_RESUME_PRIVATE); + if (r) { + log_err(cd, _("Failed to resume device %s."), rh->hotzone_name); + return REENC_ERR; + } + } + + return REENC_OK; +} + +static int reencrypt_erase_backup_segments(struct crypt_device *cd, + struct luks2_hdr *hdr) +{ + int segment = LUKS2_get_segment_id_by_flag(hdr, "backup-previous"); + if (segment >= 0) { + if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0)) + return -EINVAL; + json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment); + } + segment = LUKS2_get_segment_id_by_flag(hdr, "backup-final"); + if (segment >= 0) { + if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0)) + return -EINVAL; + json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment); + } + segment = LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment"); + if (segment >= 0) { + if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0)) + return -EINVAL; + json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment); + } + + return 0; +} + +static int reencrypt_wipe_moved_segment(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reenc_context *rh) +{ + int r = 0; + uint64_t offset, length; + + if (rh->jobj_segment_moved) { + offset = json_segment_get_offset(rh->jobj_segment_moved, 0); + length = json_segment_get_size(rh->jobj_segment_moved, 0); + log_dbg(cd, "Wiping %" PRIu64 " bytes of backup segment data at offset %" PRIu64, + length, offset); + r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_RANDOM, + offset, length, 1024 * 1024, NULL, NULL); + } + + return r; +} + +static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reenc_context *rh) +{ + int i, r; + uint32_t dmt_flags; + bool finished = !(rh->device_size > rh->progress); + + if (rh->rp.type == REENC_PROTECTION_NONE && + LUKS2_hdr_write(cd, hdr)) { + log_err(cd, _("Failed to write LUKS2 metadata.")); + return -EINVAL; + } + + if (rh->online) { + r = LUKS2_reload(cd, rh->device_name, rh->vks, rh->device_size, rh->flags); + if (r) + log_err(cd, _("Failed to reload device %s."), rh->device_name); + if (!r) { + r = dm_resume_device(cd, rh->device_name, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH); + if (r) + log_err(cd, _("Failed to resume device %s."), rh->device_name); + } + dm_remove_device(cd, rh->overlay_name, 0); + dm_remove_device(cd, rh->hotzone_name, 0); + + if (!r && finished && rh->mode == CRYPT_REENCRYPT_DECRYPT && + !dm_flags(cd, DM_LINEAR, &dmt_flags) && (dmt_flags & DM_DEFERRED_SUPPORTED)) + dm_remove_device(cd, rh->device_name, CRYPT_DEACTIVATE_DEFERRED); + } + + if (finished) { + if (reencrypt_wipe_moved_segment(cd, hdr, rh)) + log_err(cd, _("Failed to wipe backup segment data.")); + if (reencrypt_get_data_offset_new(hdr) && LUKS2_set_keyslots_size(cd, hdr, reencrypt_get_data_offset_new(hdr))) + log_dbg(cd, "Failed to set new keyslots area size."); + if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old) + for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) + if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old) + crypt_keyslot_destroy(cd, i); + crypt_keyslot_destroy(cd, rh->reenc_keyslot); + if (reencrypt_erase_backup_segments(cd, hdr)) + log_dbg(cd, "Failed to erase backup segments"); + + /* do we need atomic erase? */ + if (reencrypt_update_flag(cd, 0, true)) + log_err(cd, _("Failed to disable reencryption requirement flag.")); + } + + return 0; +} + +static void reencrypt_teardown_fatal(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reenc_context *rh) +{ + log_err(cd, _("Fatal error while reencrypting chunk starting at %" PRIu64 ", %" PRIu64 " sectors long."), + (rh->offset >> SECTOR_SHIFT) + crypt_get_data_offset(cd), rh->length >> SECTOR_SHIFT); + + if (rh->online) { + log_err(cd, "Reencryption was run in online mode."); + if (dm_status_suspended(cd, rh->hotzone_name) > 0) { + log_dbg(cd, "Hotzone device %s suspended, replacing with dm-error.", rh->hotzone_name); + if (dm_error_device(cd, rh->hotzone_name)) { + log_err(cd, _("Failed to replace suspended device %s with dm-error target."), rh->hotzone_name); + log_err(cd, _("Do not resume the device unless replaced with error target manually.")); + } + } + } +} + +static int reencrypt_teardown(struct crypt_device *cd, struct luks2_hdr *hdr, + struct luks2_reenc_context *rh, reenc_status_t rs, bool interrupted, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr)) +{ + int r; + + switch (rs) { + case REENC_OK: + if (progress && !interrupted) + progress(rh->device_size, rh->progress, NULL); + r = reencrypt_teardown_ok(cd, hdr, rh); + break; + case REENC_FATAL: + reencrypt_teardown_fatal(cd, hdr, rh); + /* fall-through */ + default: + r = -EIO; + } + + /* this frees reencryption lock */ + LUKS2_reenc_context_free(cd, rh); + crypt_set_reenc_context(cd, NULL); + + return r; +} + +int crypt_reencrypt(struct crypt_device *cd, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr)) +{ + int r; + crypt_reencrypt_info ri; + struct luks2_hdr *hdr; + struct luks2_reenc_context *rh; + reenc_status_t rs; + bool quit = false; + + if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT)) + return -EINVAL; + + hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + ri = LUKS2_reenc_status(hdr); + if (ri > CRYPT_REENCRYPT_CLEAN) { + log_err(cd, _("Cannot proceed with reencryption. Unexpected reencryption status.")); + return -EINVAL; + } + + rh = crypt_get_reenc_context(cd); + if (!rh || (!rh->reenc_lock && crypt_metadata_locking_enabled())) { + log_err(cd, _("Missing or invalid reencrypt context.")); + return -EINVAL; + } + + log_dbg(cd, "Resuming LUKS2 reencryption."); + + if (rh->online && reencrypt_init_device_stack(cd, rh)) { + log_err(cd, _("Failed to initialize reencryption device stack.")); + return -EINVAL; + } + + log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, rh->device_size); + + rs = REENC_OK; + + while (!quit && (rh->device_size > rh->progress)) { + rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online); + if (rs != REENC_OK) + break; + + log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, rh->device_size); + if (progress && progress(rh->device_size, rh->progress, NULL)) + quit = true; + + r = reencrypt_context_update(cd, rh); + if (r) { + log_err(cd, _("Failed to update reencryption context.")); + rs = REENC_ERR; + break; + } + + log_dbg(cd, "Next reencryption offset will be %" PRIu64 " sectors.", rh->offset); + log_dbg(cd, "Next reencryption chunk size will be %" PRIu64 " sectors).", rh->length); + } + + r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress); + return r; +} + +static int reencrypt_recovery(struct crypt_device *cd, + struct luks2_hdr *hdr, + uint64_t device_size, + struct volume_key *vks) +{ + int r; + struct luks2_reenc_context *rh = NULL; + + r = reencrypt_load(cd, hdr, device_size, NULL, &rh); + if (r < 0) { + log_err(cd, _("Failed to load LUKS2 reencryption context.")); + return r; + } + + r = reencrypt_recover_segment(cd, hdr, rh, vks); + if (r < 0) + goto err; + + if ((r = reencrypt_assign_segments(cd, hdr, rh, 0, 0))) + goto err; + + r = reencrypt_context_update(cd, rh); + if (r) { + log_err(cd, _("Failed to update reencryption context.")); + goto err; + } + + r = reencrypt_teardown_ok(cd, hdr, rh); + if (!r) + r = LUKS2_hdr_write(cd, hdr); +err: + LUKS2_reenc_context_free(cd, rh); + + return r; +} + +/* + * use only for calculation of minimal data device size. + * The real data offset is taken directly from segments! + */ +int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise) +{ + crypt_reencrypt_info ri = LUKS2_reenc_status(hdr); + uint64_t data_offset = LUKS2_get_data_offset(hdr); + + if (ri == CRYPT_REENCRYPT_CLEAN && reencrypt_direction(hdr) == CRYPT_REENCRYPT_FORWARD) + data_offset += reencrypt_data_shift(hdr) >> SECTOR_SHIFT; + + return blockwise ? data_offset : data_offset << SECTOR_SHIFT; +} + +/* internal only */ +int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic) +{ + int r; + uint64_t data_offset, real_size = 0; + + if (reencrypt_direction(hdr) == CRYPT_REENCRYPT_BACKWARD && + (LUKS2_get_segment_by_flag(hdr, "backup-moved-segment") || dynamic)) + check_size += reencrypt_data_shift(hdr); + + r = device_check_access(cd, crypt_data_device(cd), activation ? DEV_EXCL : DEV_OK); + if (r) + return r; + + data_offset = LUKS2_reencrypt_data_offset(hdr, false); + + r = device_check_size(cd, crypt_data_device(cd), data_offset, 1); + if (r) + return r; + + r = device_size(crypt_data_device(cd), &real_size); + if (r) + return r; + + log_dbg(cd, "Required minimal device size: %" PRIu64 " (%" PRIu64 " sectors)" + ", real device size: %" PRIu64 " (%" PRIu64 " sectors)\n" + "calculated device size: %" PRIu64 " (%" PRIu64 " sectors)", + check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT, + real_size - data_offset, (real_size - data_offset) >> SECTOR_SHIFT); + + if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) { + log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd))); + return -EINVAL; + } + + *dev_size = real_size - data_offset; + + return 0; +} + +/* returns keyslot number on success (>= 0) or negative errnor otherwise */ +int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd, + int keyslot_old, + int keyslot_new, + const char *passphrase, + size_t passphrase_size, + uint32_t flags, + struct volume_key **vks) +{ + uint64_t minimal_size, device_size; + int keyslot, r = -EINVAL; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + struct volume_key *vk = NULL, *_vks = NULL; + + log_dbg(cd, "Entering reencryption crash recovery."); + + if (LUKS2_get_data_size(hdr, &minimal_size, NULL)) + return r; + + r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, + passphrase, passphrase_size, &_vks); + if (r < 0) + goto err; + keyslot = r; + + if (crypt_use_keyring_for_vk(cd)) + vk = _vks; + + while (vk) { + r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk)); + if (r < 0) + goto err; + vk = crypt_volume_key_next(vk); + } + + if (luks2_check_device_size(cd, hdr, minimal_size, &device_size, true, false)) + goto err; + + r = reencrypt_recovery(cd, hdr, device_size, _vks); + + if (!r && vks) + MOVE_REF(*vks, _vks); +err: + if (r < 0) + crypt_drop_keyring_key(cd, _vks); + crypt_free_volume_key(_vks); + + return r < 0 ? r : keyslot; +} + +crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd, struct crypt_params_reencrypt *params) +{ + crypt_reencrypt_info ri; + struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !params) + return ri; + + params->mode = reencrypt_mode(hdr); + params->direction = reencrypt_direction(hdr); + params->resilience = reencrypt_resilience_type(hdr); + params->hash = reencrypt_resilience_hash(hdr); + params->data_shift = reencrypt_data_shift(hdr) >> SECTOR_SHIFT; + params->max_hotzone_size = 0; + if (LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0) + params->flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT; + + return ri; +} diff --git a/lib/luks2/luks2_segment.c b/lib/luks2/luks2_segment.c new file mode 100644 index 0000000..8708ba5 --- /dev/null +++ b/lib/luks2/luks2_segment.c @@ -0,0 +1,412 @@ +/* + * LUKS - Linux Unified Key Setup v2, internal segment handling + * + * Copyright (C) 2018-2020, Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2020, Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "luks2_internal.h" + +/* use only on already validated 'segments' object */ +uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise) +{ + uint64_t tmp, min = blockwise ? UINT64_MAX >> SECTOR_SHIFT : UINT64_MAX; + + if (!jobj_segments) + return 0; + + json_object_object_foreach(jobj_segments, key, val) { + UNUSED(key); + + if (json_segment_is_backup(val)) + continue; + + tmp = json_segment_get_offset(val, blockwise); + + if (!tmp) + return tmp; + + if (tmp < min) + min = tmp; + } + + return min; +} + +uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise) +{ + json_object *jobj; + + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "offset", &jobj)) + return 0; + + return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj); +} + +const char *json_segment_type(json_object *jobj_segment) +{ + json_object *jobj; + + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "type", &jobj)) + return NULL; + + return json_object_get_string(jobj); +} + +uint64_t json_segment_get_iv_offset(json_object *jobj_segment) +{ + json_object *jobj; + + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj)) + return 0; + + return crypt_jobj_get_uint64(jobj); +} + +uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise) +{ + json_object *jobj; + + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "size", &jobj)) + return 0; + + return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj); +} + +const char *json_segment_get_cipher(json_object *jobj_segment) +{ + json_object *jobj; + + /* FIXME: Pseudo "null" cipher should be handled elsewhere */ + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "encryption", &jobj)) + return "null"; + + return json_object_get_string(jobj); +} + +int json_segment_get_sector_size(json_object *jobj_segment) +{ + json_object *jobj; + + if (!jobj_segment || + !json_object_object_get_ex(jobj_segment, "sector_size", &jobj)) + return -1; + + return json_object_get_int(jobj); +} + +static json_object *json_segment_get_flags(json_object *jobj_segment) +{ + json_object *jobj; + + if (!jobj_segment || !(json_object_object_get_ex(jobj_segment, "flags", &jobj))) + return NULL; + return jobj; +} + +static bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len) +{ + int r, i; + json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment); + + if (!jobj_flags) + return false; + + for (i = 0; i < (int)json_object_array_length(jobj_flags); i++) { + jobj = json_object_array_get_idx(jobj_flags, i); + if (len) + r = strncmp(json_object_get_string(jobj), flag_str, len); + else + r = strcmp(json_object_get_string(jobj), flag_str); + if (!r) + return true; + } + + return false; +} + +bool json_segment_is_backup(json_object *jobj_segment) +{ + return json_segment_contains_flag(jobj_segment, "backup-", 7); +} + +json_object *json_segments_get_segment(json_object *jobj_segments, int segment) +{ + json_object *jobj; + char segment_name[16]; + + if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1) + return NULL; + + if (!json_object_object_get_ex(jobj_segments, segment_name, &jobj)) + return NULL; + + return jobj; +} + +unsigned json_segments_count(json_object *jobj_segments) +{ + unsigned count = 0; + + if (!jobj_segments) + return 0; + + json_object_object_foreach(jobj_segments, slot, val) { + UNUSED(slot); + if (!json_segment_is_backup(val)) + count++; + } + + return count; +} + +static void _get_segment_or_id_by_flag(json_object *jobj_segments, const char *flag, unsigned id, void *retval) +{ + json_object *jobj_flags, **jobj_ret = (json_object **)retval; + int *ret = (int *)retval; + + if (!flag) + return; + + json_object_object_foreach(jobj_segments, key, value) { + if (!json_object_object_get_ex(value, "flags", &jobj_flags)) + continue; + if (LUKS2_array_jobj(jobj_flags, flag)) { + if (id) + *ret = atoi(key); + else + *jobj_ret = value; + return; + } + } +} + +void json_segment_remove_flag(json_object *jobj_segment, const char *flag) +{ + json_object *jobj_flags, *jobj_flags_new; + + if (!jobj_segment) + return; + + jobj_flags = json_segment_get_flags(jobj_segment); + if (!jobj_flags) + return; + + jobj_flags_new = LUKS2_array_remove(jobj_flags, flag); + if (!jobj_flags_new) + return; + + if (json_object_array_length(jobj_flags_new) <= 0) { + json_object_put(jobj_flags_new); + json_object_object_del(jobj_segment, "flags"); + } else + json_object_object_add(jobj_segment, "flags", jobj_flags_new); +} + +static json_object *_segment_create_generic(const char *type, uint64_t offset, const uint64_t *length) +{ + json_object *jobj = json_object_new_object(); + if (!jobj) + return NULL; + + json_object_object_add(jobj, "type", json_object_new_string(type)); + json_object_object_add(jobj, "offset", crypt_jobj_new_uint64(offset)); + json_object_object_add(jobj, "size", length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic")); + + return jobj; +} + +json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption) +{ + json_object *jobj = _segment_create_generic("linear", offset, length); + if (reencryption) + LUKS2_segment_set_flag(jobj, "in-reencryption"); + return jobj; +} + +json_object *json_segment_create_crypt(uint64_t offset, + uint64_t iv_offset, const uint64_t *length, + const char *cipher, uint32_t sector_size, + unsigned reencryption) +{ + json_object *jobj = _segment_create_generic("crypt", offset, length); + if (!jobj) + return NULL; + + json_object_object_add(jobj, "iv_tweak", crypt_jobj_new_uint64(iv_offset)); + json_object_object_add(jobj, "encryption", json_object_new_string(cipher)); + json_object_object_add(jobj, "sector_size", json_object_new_int(sector_size)); + if (reencryption) + LUKS2_segment_set_flag(jobj, "in-reencryption"); + + return jobj; +} + +uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise) +{ + return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise); +} + +int json_segments_segment_in_reencrypt(json_object *jobj_segments) +{ + json_object *jobj_flags; + + json_object_object_foreach(jobj_segments, slot, val) { + if (!json_object_object_get_ex(val, "flags", &jobj_flags) || + !LUKS2_array_jobj(jobj_flags, "in-reencryption")) + continue; + + return atoi(slot); + } + + return -1; +} + +uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise) +{ + return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise); +} + +int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type) +{ + return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type); +} + +int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type) +{ + json_object *jobj_segments; + int last_found = -1; + + if (!type) + return -1; + + if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) + return -1; + + json_object_object_foreach(jobj_segments, slot, val) { + if (json_segment_is_backup(val)) + continue; + if (strcmp(type, json_segment_type(val) ?: "")) + continue; + + if (atoi(slot) > last_found) + last_found = atoi(slot); + } + + return last_found; +} + +int LUKS2_segment_by_type(struct luks2_hdr *hdr, const char *type) +{ + json_object *jobj_segments; + int first_found = -1; + + if (!type) + return -EINVAL; + + if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) + return -EINVAL; + + json_object_object_foreach(jobj_segments, slot, val) { + if (json_segment_is_backup(val)) + continue; + if (strcmp(type, json_segment_type(val) ?: "")) + continue; + + if (first_found < 0) + first_found = atoi(slot); + else if (atoi(slot) < first_found) + first_found = atoi(slot); + } + + return first_found; +} + +int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr) +{ + json_object *jobj_segments; + int id, last_id = -1; + + if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) + return -EINVAL; + + json_object_object_foreach(jobj_segments, slot, val) { + UNUSED(val); + id = atoi(slot); + if (id > last_id) + last_id = id; + } + + return last_id + 1; +} + +int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag) +{ + json_object *jobj_flags; + + if (!jobj_segment || !flag) + return -EINVAL; + + if (!json_object_object_get_ex(jobj_segment, "flags", &jobj_flags)) { + jobj_flags = json_object_new_array(); + if (!jobj_flags) + return -ENOMEM; + json_object_object_add(jobj_segment, "flags", jobj_flags); + } + + if (LUKS2_array_jobj(jobj_flags, flag)) + return 0; + + json_object_array_add(jobj_flags, json_object_new_string(flag)); + + return 0; +} + +int LUKS2_segments_set(struct crypt_device *cd, struct luks2_hdr *hdr, + json_object *jobj_segments, int commit) +{ + json_object_object_add(hdr->jobj, "segments", jobj_segments); + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} + +int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag) +{ + int ret = -ENOENT; + json_object *jobj_segments = LUKS2_get_segments_jobj(hdr); + + if (jobj_segments) + _get_segment_or_id_by_flag(jobj_segments, flag, 1, &ret); + + return ret; +} + +json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag) +{ + json_object *jobj_segment = NULL, + *jobj_segments = LUKS2_get_segments_jobj(hdr); + + if (jobj_segments) + _get_segment_or_id_by_flag(jobj_segments, flag, 0, &jobj_segment); + + return jobj_segment; +} diff --git a/lib/luks2/luks2_token.c b/lib/luks2/luks2_token.c new file mode 100644 index 0000000..ad6722a --- /dev/null +++ b/lib/luks2/luks2_token.c @@ -0,0 +1,610 @@ +/* + * LUKS - Linux Unified Key Setup v2, token handling + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "luks2_internal.h" + +/* Builtin tokens */ +extern const crypt_token_handler keyring_handler; + +static token_handler token_handlers[LUKS2_TOKENS_MAX] = { + /* keyring builtin token */ + { + .get = token_keyring_get, + .set = token_keyring_set, + .h = &keyring_handler + }, +}; + +static int is_builtin_candidate(const char *type) +{ + return !strncmp(type, LUKS2_BUILTIN_TOKEN_PREFIX, LUKS2_BUILTIN_TOKEN_PREFIX_LEN); +} + +int crypt_token_register(const crypt_token_handler *handler) +{ + int i; + + if (is_builtin_candidate(handler->name)) { + log_dbg(NULL, "'" LUKS2_BUILTIN_TOKEN_PREFIX "' is reserved prefix for builtin tokens."); + return -EINVAL; + } + + for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++) { + if (!strcmp(token_handlers[i].h->name, handler->name)) { + log_dbg(NULL, "Keyslot handler %s is already registered.", handler->name); + return -EINVAL; + } + } + + if (i == LUKS2_TOKENS_MAX) + return -EINVAL; + + token_handlers[i].h = handler; + return 0; +} + +static const token_handler +*LUKS2_token_handler_type_internal(struct crypt_device *cd, const char *type) +{ + int i; + + for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++) + if (!strcmp(token_handlers[i].h->name, type)) + return token_handlers + i; + + return NULL; +} + +static const crypt_token_handler +*LUKS2_token_handler_type(struct crypt_device *cd, const char *type) +{ + const token_handler *th = LUKS2_token_handler_type_internal(cd, type); + + return th ? th->h : NULL; +} + +static const token_handler +*LUKS2_token_handler_internal(struct crypt_device *cd, int token) +{ + struct luks2_hdr *hdr; + json_object *jobj1, *jobj2; + + if (token < 0) + return NULL; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return NULL; + + if (!(jobj1 = LUKS2_get_token_jobj(hdr, token))) + return NULL; + + if (!json_object_object_get_ex(jobj1, "type", &jobj2)) + return NULL; + + return LUKS2_token_handler_type_internal(cd, json_object_get_string(jobj2)); +} + +static const crypt_token_handler +*LUKS2_token_handler(struct crypt_device *cd, int token) +{ + const token_handler *th = LUKS2_token_handler_internal(cd, token); + + return th ? th->h : NULL; +} + +static int LUKS2_token_find_free(struct luks2_hdr *hdr) +{ + int i; + + for (i = 0; i < LUKS2_TOKENS_MAX; i++) + if (!LUKS2_get_token_jobj(hdr, i)) + return i; + + return -EINVAL; +} + +int LUKS2_token_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *json, + int commit) +{ + const crypt_token_handler *h; + const token_handler *th; + json_object *jobj_tokens, *jobj_type, *jobj; + enum json_tokener_error jerr; + char num[16]; + + if (token == CRYPT_ANY_TOKEN) { + if (!json) + return -EINVAL; + token = LUKS2_token_find_free(hdr); + } + + if (token < 0 || token >= LUKS2_TOKENS_MAX) + return -EINVAL; + + if (!json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens)) + return -EINVAL; + + snprintf(num, sizeof(num), "%d", token); + + /* Remove token */ + if (!json) + json_object_object_del(jobj_tokens, num); + else { + + jobj = json_tokener_parse_verbose(json, &jerr); + if (!jobj) { + log_dbg(cd, "Token JSON parse failed."); + return -EINVAL; + } + + if (LUKS2_token_validate(cd, hdr->jobj, jobj, num)) { + json_object_put(jobj); + return -EINVAL; + } + + json_object_object_get_ex(jobj, "type", &jobj_type); + if (is_builtin_candidate(json_object_get_string(jobj_type))) { + th = LUKS2_token_handler_type_internal(cd, json_object_get_string(jobj_type)); + if (!th || !th->set) { + log_dbg(cd, "%s is builtin token candidate with missing handler", json_object_get_string(jobj_type)); + json_object_put(jobj); + return -EINVAL; + } + h = th->h; + } else + h = LUKS2_token_handler_type(cd, json_object_get_string(jobj_type)); + + if (h && h->validate && h->validate(cd, json)) { + json_object_put(jobj); + log_dbg(cd, "Token type %s validation failed.", h->name); + return -EINVAL; + } + + json_object_object_add(jobj_tokens, num, jobj); + if (LUKS2_check_json_size(cd, hdr)) { + log_dbg(cd, "Not enough space in header json area for new token."); + json_object_object_del(jobj_tokens, num); + return -ENOSPC; + } + } + + if (commit) + return LUKS2_hdr_write(cd, hdr) ?: token; + + return token; +} + +crypt_token_info LUKS2_token_status(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char **type) +{ + const char *tmp; + const token_handler *th; + json_object *jobj_type, *jobj_token; + + if (token < 0 || token >= LUKS2_TOKENS_MAX) + return CRYPT_TOKEN_INVALID; + + if (!(jobj_token = LUKS2_get_token_jobj(hdr, token))) + return CRYPT_TOKEN_INACTIVE; + + json_object_object_get_ex(jobj_token, "type", &jobj_type); + tmp = json_object_get_string(jobj_type); + + if ((th = LUKS2_token_handler_type_internal(cd, tmp))) { + if (type) + *type = th->h->name; + return th->set ? CRYPT_TOKEN_INTERNAL : CRYPT_TOKEN_EXTERNAL; + } + + if (type) + *type = tmp; + + return is_builtin_candidate(tmp) ? CRYPT_TOKEN_INTERNAL_UNKNOWN : CRYPT_TOKEN_EXTERNAL_UNKNOWN; +} + +int LUKS2_builtin_token_get(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *type, + void *params) +{ + const token_handler *th = LUKS2_token_handler_type_internal(cd, type); + + // internal error + assert(th && th->get); + + return th->get(LUKS2_get_token_jobj(hdr, token), params) ?: token; +} + +int LUKS2_builtin_token_create(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *type, + const void *params, + int commit) +{ + const token_handler *th; + int r; + json_object *jobj_token, *jobj_tokens; + + th = LUKS2_token_handler_type_internal(cd, type); + + // at this point all builtin handlers must exist and have validate fn defined + assert(th && th->set && th->h->validate); + + if (token == CRYPT_ANY_TOKEN) { + if ((token = LUKS2_token_find_free(hdr)) < 0) + log_err(cd, _("No free token slot.")); + } + if (token < 0 || token >= LUKS2_TOKENS_MAX) + return -EINVAL; + + r = th->set(&jobj_token, params); + if (r) { + log_err(cd, _("Failed to create builtin token %s."), type); + return r; + } + + // builtin tokens must produce valid json + r = LUKS2_token_validate(cd, hdr->jobj, jobj_token, "new"); + assert(!r); + r = th->h->validate(cd, json_object_to_json_string_ext(jobj_token, + JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE)); + assert(!r); + + json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens); + json_object_object_add_by_uint(jobj_tokens, token, jobj_token); + if (LUKS2_check_json_size(cd, hdr)) { + log_dbg(cd, "Not enough space in header json area for new %s token.", type); + json_object_object_del_by_uint(jobj_tokens, token); + return -ENOSPC; + } + + if (commit) + return LUKS2_hdr_write(cd, hdr) ?: token; + + return token; +} + +static int LUKS2_token_open(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + char **buffer, + size_t *buffer_len, + void *usrptr) +{ + const char *json; + const crypt_token_handler *h; + int r; + + if (!(h = LUKS2_token_handler(cd, token))) + return -ENOENT; + + if (h->validate) { + if (LUKS2_token_json_get(cd, hdr, token, &json)) + return -EINVAL; + + if (h->validate(cd, json)) { + log_dbg(cd, "Token %d (%s) validation failed.", token, h->name); + return -EINVAL; + } + } + + r = h->open(cd, token, buffer, buffer_len, usrptr); + if (r < 0) + log_dbg(cd, "Token %d (%s) open failed with %d.", token, h->name, r); + + return r; +} + +static void LUKS2_token_buffer_free(struct crypt_device *cd, + int token, + void *buffer, + size_t buffer_len) +{ + const crypt_token_handler *h = LUKS2_token_handler(cd, token); + + if (h->buffer_free) + h->buffer_free(buffer, buffer_len); + else { + crypt_safe_memzero(buffer, buffer_len); + free(buffer); + } +} + +static int LUKS2_keyslot_open_by_token(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + int segment, + const char *buffer, + size_t buffer_len, + struct volume_key **vk) +{ + const crypt_token_handler *h; + json_object *jobj_token, *jobj_token_keyslots, *jobj; + unsigned int num = 0; + int i, r; + + if (!(h = LUKS2_token_handler(cd, token))) + return -ENOENT; + + jobj_token = LUKS2_get_token_jobj(hdr, token); + if (!jobj_token) + return -EINVAL; + + json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots); + if (!jobj_token_keyslots) + return -EINVAL; + + /* Try to open keyslot referenced in token */ + r = -EINVAL; + for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots) && r < 0; i++) { + jobj = json_object_array_get_idx(jobj_token_keyslots, i); + num = atoi(json_object_get_string(jobj)); + log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).", num, token, h->name); + r = LUKS2_keyslot_open(cd, num, segment, buffer, buffer_len, vk); + } + + if (r < 0) + return r; + + return num; +} + +int LUKS2_token_open_and_activate(struct crypt_device *cd, + struct luks2_hdr *hdr, + int token, + const char *name, + uint32_t flags, + void *usrptr) +{ + int keyslot, r; + char *buffer; + size_t buffer_len; + struct volume_key *vk = NULL; + + r = LUKS2_token_open(cd, hdr, token, &buffer, &buffer_len, usrptr); + if (r < 0) + return r; + + r = LUKS2_keyslot_open_by_token(cd, hdr, token, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, + buffer, buffer_len, &vk); + + LUKS2_token_buffer_free(cd, token, buffer, buffer_len); + + if (r < 0) + return r; + + keyslot = r; + + if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) { + if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot))) + flags |= CRYPT_ACTIVATE_KEYRING_KEY; + } + + if (r >= 0 && name) + r = LUKS2_activate(cd, name, vk, flags); + + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + + return r < 0 ? r : keyslot; +} + +int LUKS2_token_open_and_activate_any(struct crypt_device *cd, + struct luks2_hdr *hdr, + const char *name, + uint32_t flags) +{ + char *buffer; + json_object *tokens_jobj; + size_t buffer_len; + int keyslot, token, r = -EINVAL; + struct volume_key *vk = NULL; + + json_object_object_get_ex(hdr->jobj, "tokens", &tokens_jobj); + + json_object_object_foreach(tokens_jobj, slot, val) { + UNUSED(val); + token = atoi(slot); + + r = LUKS2_token_open(cd, hdr, token, &buffer, &buffer_len, NULL); + if (r < 0) + continue; + + r = LUKS2_keyslot_open_by_token(cd, hdr, token, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, + buffer, buffer_len, &vk); + LUKS2_token_buffer_free(cd, token, buffer, buffer_len); + if (r >= 0) + break; + } + + keyslot = r; + + if (r >= 0 && (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) { + if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot))) + flags |= CRYPT_ACTIVATE_KEYRING_KEY; + } + + if (r >= 0 && name) + r = LUKS2_activate(cd, name, vk, flags); + + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + + return r < 0 ? r : keyslot; +} + +void LUKS2_token_dump(struct crypt_device *cd, int token) +{ + const crypt_token_handler *h; + json_object *jobj_token; + + h = LUKS2_token_handler(cd, token); + if (h && h->dump) { + jobj_token = LUKS2_get_token_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), token); + if (jobj_token) + h->dump(cd, json_object_to_json_string_ext(jobj_token, + JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE)); + } +} + +int LUKS2_token_json_get(struct crypt_device *cd, struct luks2_hdr *hdr, + int token, const char **json) +{ + json_object *jobj_token; + + jobj_token = LUKS2_get_token_jobj(hdr, token); + if (!jobj_token) + return -EINVAL; + + *json = json_object_to_json_string_ext(jobj_token, + JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE); + return 0; +} + +static int assign_one_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr, + int token, int keyslot, int assign) +{ + json_object *jobj1, *jobj_token, *jobj_token_keyslots; + char num[16]; + + log_dbg(cd, "Keyslot %i %s token %i.", keyslot, assign ? "assigned to" : "unassigned from", token); + + jobj_token = LUKS2_get_token_jobj(hdr, token); + if (!jobj_token) + return -EINVAL; + + json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots); + if (!jobj_token_keyslots) + return -EINVAL; + + snprintf(num, sizeof(num), "%d", keyslot); + if (assign) { + jobj1 = LUKS2_array_jobj(jobj_token_keyslots, num); + if (!jobj1) + json_object_array_add(jobj_token_keyslots, json_object_new_string(num)); + } else { + jobj1 = LUKS2_array_remove(jobj_token_keyslots, num); + if (jobj1) + json_object_object_add(jobj_token, "keyslots", jobj1); + } + + return 0; +} + +static int assign_one_token(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int token, int assign) +{ + json_object *jobj_keyslots; + int r = 0; + + if (!LUKS2_get_token_jobj(hdr, token)) + return -EINVAL; + + if (keyslot == CRYPT_ANY_SLOT) { + json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots); + + json_object_object_foreach(jobj_keyslots, key, val) { + UNUSED(val); + r = assign_one_keyslot(cd, hdr, token, atoi(key), assign); + if (r < 0) + break; + } + } else + r = assign_one_keyslot(cd, hdr, token, keyslot, assign); + + return r; +} + +int LUKS2_token_assign(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int token, int assign, int commit) +{ + json_object *jobj_tokens; + int r = 0; + + if (token == CRYPT_ANY_TOKEN) { + json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens); + + json_object_object_foreach(jobj_tokens, key, val) { + UNUSED(val); + r = assign_one_token(cd, hdr, keyslot, atoi(key), assign); + if (r < 0) + break; + } + } else + r = assign_one_token(cd, hdr, keyslot, token, assign); + + if (r < 0) + return r; + + // FIXME: do not write header in nothing changed + if (commit) + return LUKS2_hdr_write(cd, hdr) ?: token; + + return token; +} + +int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int token) +{ + int i; + json_object *jobj_token, *jobj_token_keyslots, *jobj; + + if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX) + return -EINVAL; + + jobj_token = LUKS2_get_token_jobj(hdr, token); + if (!jobj_token) + return -ENOENT; + + json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots); + + for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots); i++) { + jobj = json_object_array_get_idx(jobj_token_keyslots, i); + if (keyslot == atoi(json_object_get_string(jobj))) + return 0; + } + + return -ENOENT; +} + +int LUKS2_tokens_count(struct luks2_hdr *hdr) +{ + json_object *jobj_tokens = LUKS2_get_tokens_jobj(hdr); + if (!jobj_tokens) + return -EINVAL; + + return json_object_object_length(jobj_tokens); +} diff --git a/lib/luks2/luks2_token_keyring.c b/lib/luks2/luks2_token_keyring.c new file mode 100644 index 0000000..448ad45 --- /dev/null +++ b/lib/luks2/luks2_token_keyring.c @@ -0,0 +1,170 @@ +/* + * LUKS - Linux Unified Key Setup v2, kernel keyring token + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "luks2_internal.h" + +static int keyring_open(struct crypt_device *cd, + int token, + char **buffer, + size_t *buffer_len, + void *usrptr __attribute__((unused))) +{ + json_object *jobj_token, *jobj_key; + struct luks2_hdr *hdr; + int r; + + if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) + return -EINVAL; + + jobj_token = LUKS2_get_token_jobj(hdr, token); + if (!jobj_token) + return -EINVAL; + + json_object_object_get_ex(jobj_token, "key_description", &jobj_key); + + r = keyring_get_passphrase(json_object_get_string(jobj_key), buffer, buffer_len); + if (r == -ENOTSUP) { + log_dbg(cd, "Kernel keyring features disabled."); + return -EINVAL; + } else if (r < 0) { + log_dbg(cd, "keyring_get_passphrase failed (error %d)", r); + return -EINVAL; + } + + return 0; +} + +static int keyring_validate(struct crypt_device *cd __attribute__((unused)), + const char *json) +{ + enum json_tokener_error jerr; + json_object *jobj_token, *jobj_key; + int r = 1; + + log_dbg(cd, "Validating keyring token json"); + + jobj_token = json_tokener_parse_verbose(json, &jerr); + if (!jobj_token) { + log_dbg(cd, "Keyring token JSON parse failed."); + return r; + } + + if (json_object_object_length(jobj_token) != 3) { + log_dbg(cd, "Keyring token is expected to have exactly 3 fields."); + goto out; + } + + if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) { + log_dbg(cd, "missing key_description field."); + goto out; + } + + if (!json_object_is_type(jobj_key, json_type_string)) { + log_dbg(cd, "key_description is not a string."); + goto out; + } + + /* TODO: perhaps check that key description is in '%s:%s' + * format where both strings are not empty */ + r = !strlen(json_object_get_string(jobj_key)); +out: + json_object_put(jobj_token); + return r; +} + +static void keyring_dump(struct crypt_device *cd, const char *json) +{ + enum json_tokener_error jerr; + json_object *jobj_token, *jobj_key; + + jobj_token = json_tokener_parse_verbose(json, &jerr); + if (!jobj_token) + return; + + if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) { + json_object_put(jobj_token); + return; + } + + log_std(cd, "\tKey description: %s\n", json_object_get_string(jobj_key)); + + json_object_put(jobj_token); +} + +int token_keyring_set(json_object **jobj_builtin_token, + const void *params) +{ + json_object *jobj_token, *jobj; + const struct crypt_token_params_luks2_keyring *keyring_params = (const struct crypt_token_params_luks2_keyring *) params; + + jobj_token = json_object_new_object(); + if (!jobj_token) + return -ENOMEM; + + jobj = json_object_new_string(LUKS2_TOKEN_KEYRING); + if (!jobj) { + json_object_put(jobj_token); + return -ENOMEM; + } + json_object_object_add(jobj_token, "type", jobj); + + jobj = json_object_new_array(); + if (!jobj) { + json_object_put(jobj_token); + return -ENOMEM; + } + json_object_object_add(jobj_token, "keyslots", jobj); + + jobj = json_object_new_string(keyring_params->key_description); + if (!jobj) { + json_object_put(jobj_token); + return -ENOMEM; + } + json_object_object_add(jobj_token, "key_description", jobj); + + *jobj_builtin_token = jobj_token; + return 0; +} + +int token_keyring_get(json_object *jobj_token, + void *params) +{ + json_object *jobj; + struct crypt_token_params_luks2_keyring *keyring_params = (struct crypt_token_params_luks2_keyring *) params; + + json_object_object_get_ex(jobj_token, "type", &jobj); + assert(!strcmp(json_object_get_string(jobj), LUKS2_TOKEN_KEYRING)); + + json_object_object_get_ex(jobj_token, "key_description", &jobj); + + keyring_params->key_description = json_object_get_string(jobj); + + return 0; +} + +const crypt_token_handler keyring_handler = { + .name = LUKS2_TOKEN_KEYRING, + .open = keyring_open, + .validate = keyring_validate, + .dump = keyring_dump +}; diff --git a/lib/random.c b/lib/random.c index 25c8a2c..060be4f 100644 --- a/lib/random.c +++ b/lib/random.c @@ -1,7 +1,7 @@ /* * cryptsetup kernel RNG access functions * - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -152,21 +151,24 @@ int crypt_random_init(struct crypt_device *ctx) /* Used for CRYPT_RND_NORMAL */ if(urandom_fd == -1) - urandom_fd = open(URANDOM_DEVICE, O_RDONLY); + urandom_fd = open(URANDOM_DEVICE, O_RDONLY | O_CLOEXEC); if(urandom_fd == -1) goto fail; /* Used for CRYPT_RND_KEY */ if(random_fd == -1) - random_fd = open(RANDOM_DEVICE, O_RDONLY | O_NONBLOCK); + random_fd = open(RANDOM_DEVICE, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if(random_fd == -1) goto fail; + if (crypt_fips_mode()) + log_verbose(ctx, _("Running in FIPS mode.")); + random_initialised = 1; return 0; fail: crypt_random_exit(); - log_err(ctx, _("Fatal error during RNG initialisation.\n")); + log_err(ctx, _("Fatal error during RNG initialisation.")); return -ENOSYS; } @@ -203,13 +205,12 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit } break; default: - log_err(ctx, _("Unknown RNG quality requested.\n")); + log_err(ctx, _("Unknown RNG quality requested.")); return -EINVAL; } if (status) - log_err(ctx, _("Error %d reading from RNG: %s\n"), - errno, strerror(errno)); + log_err(ctx, _("Error reading from RNG.")); return status; } @@ -231,9 +232,11 @@ void crypt_random_exit(void) int crypt_random_default_key_rng(void) { + /* coverity[pointless_string_compare] */ if (!strcmp(DEFAULT_RNG, RANDOM_DEVICE)) return CRYPT_RNG_RANDOM; + /* coverity[pointless_string_compare] */ if (!strcmp(DEFAULT_RNG, URANDOM_DEVICE)) return CRYPT_RNG_URANDOM; diff --git a/lib/setup.c b/lib/setup.c index 01e2c80..567f262 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1,10 +1,10 @@ /* * libcryptsetup - cryptsetup library * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2014, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,16 +26,22 @@ #include #include #include -#include #include #include "libcryptsetup.h" #include "luks.h" +#include "luks2.h" #include "loopaes.h" #include "verity.h" #include "tcrypt.h" +#include "integrity.h" +#include "bitlk.h" +#include "utils_device_locking.h" #include "internal.h" +#define CRYPT_CD_UNRESTRICTED (1 << 0) +#define CRYPT_CD_QUIET (1 << 1) + struct crypt_device { char *type; @@ -43,11 +49,20 @@ struct crypt_device { struct device *metadata_device; struct volume_key *volume_key; - uint64_t timeout; - uint64_t iteration_time; - int tries; - int password_verify; int rng_type; + uint32_t compatibility; + struct crypt_pbkdf_type pbkdf; + + /* global context scope settings */ + unsigned key_in_keyring:1; + + uint64_t data_offset; + uint64_t metadata_size; /* Used in LUKS2 format */ + uint64_t keyslots_size; /* Used in LUKS2 format */ + + /* Workaround for OOM during parallel activation (like in systemd) */ + bool memory_hard_pbkdf_lock_enabled; + struct crypt_lock_handle *pbkdf_memory_hard_lock; // FIXME: private binary headers and access it properly // through sub-library (LUKS1, TCRYPT) @@ -55,35 +70,57 @@ struct crypt_device { union { struct { /* used in CRYPT_LUKS1 */ struct luks_phdr hdr; - uint64_t PBKDF2_per_sec; + char *cipher_spec; } luks1; + struct { /* used in CRYPT_LUKS2 */ + struct luks2_hdr hdr; + char cipher[MAX_CIPHER_LEN]; /* only for compatibility */ + char cipher_mode[MAX_CIPHER_LEN]; /* only for compatibility */ + char *keyslot_cipher; + unsigned int keyslot_key_size; + struct luks2_reenc_context *rh; + } luks2; struct { /* used in CRYPT_PLAIN */ struct crypt_params_plain hdr; + char *cipher_spec; char *cipher; - char *cipher_mode; + const char *cipher_mode; unsigned int key_size; } plain; struct { /* used in CRYPT_LOOPAES */ struct crypt_params_loopaes hdr; + char *cipher_spec; char *cipher; - char *cipher_mode; + const char *cipher_mode; unsigned int key_size; } loopaes; struct { /* used in CRYPT_VERITY */ struct crypt_params_verity hdr; - char *root_hash; + const char *root_hash; unsigned int root_hash_size; char *uuid; + struct device *fec_device; } verity; struct { /* used in CRYPT_TCRYPT */ struct crypt_params_tcrypt params; struct tcrypt_phdr hdr; } tcrypt; + struct { /* used in CRYPT_INTEGRITY */ + struct crypt_params_integrity params; + struct volume_key *journal_mac_key; + struct volume_key *journal_crypt_key; + uint32_t sb_flags; + } integrity; + struct { /* used in CRYPT_BITLK */ + struct bitlk_metadata params; + char *cipher_spec; + } bitlk; struct { /* used if initialized without header by name */ char *active_name; /* buffers, must refresh from kernel on every query */ + char cipher_spec[MAX_CIPHER_LEN*2+1]; char cipher[MAX_CIPHER_LEN]; - char cipher_mode[MAX_CIPHER_LEN]; + const char *cipher_mode; unsigned int key_size; } none; } u; @@ -93,24 +130,24 @@ struct crypt_device { void *log_usrptr; int (*confirm)(const char *msg, void *usrptr); void *confirm_usrptr; - int (*password)(const char *msg, char *buf, size_t length, void *usrptr); - void *password_usrptr; - - /* last error message */ - char error[MAX_ERROR_LENGTH]; }; /* Just to suppress redundant messages about crypto backend */ static int _crypto_logged = 0; -/* Global error */ -/* FIXME: not thread safe, remove this later */ -static char global_error[MAX_ERROR_LENGTH] = {0}; - /* Log helper */ static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL; static int _debug_level = 0; +/* Library can do metadata locking */ +static int _metadata_locking = 1; + +/* Library scope detection for kernel keyring support */ +static int _kernel_keyring_supported; + +/* Library allowed to use kernel keyring for loading VK in kernel crypto layer */ +static int _vk_via_keyring = 1; + void crypt_set_debug_level(int level) { _debug_level = level; @@ -121,32 +158,21 @@ int crypt_get_debug_level(void) return _debug_level; } -static void crypt_set_error(struct crypt_device *cd, const char *error) +void crypt_log(struct crypt_device *cd, int level, const char *msg) { - size_t size = strlen(error); - - /* Set global error, ugly hack... */ - strncpy(global_error, error, MAX_ERROR_LENGTH - 2); - if (size < MAX_ERROR_LENGTH && global_error[size - 1] == '\n') - global_error[size - 1] = '\0'; + if (!msg) + return; - /* Set error string per context */ - if (cd) { - strncpy(cd->error, error, MAX_ERROR_LENGTH - 2); - if (size < MAX_ERROR_LENGTH && cd->error[size - 1] == '\n') - cd->error[size - 1] = '\0'; - } -} + if (level < _debug_level) + return; -void crypt_log(struct crypt_device *cd, int level, const char *msg) -{ if (cd && cd->log) cd->log(level, msg, cd->log_usrptr); else if (_default_log) _default_log(level, msg, NULL); - - if (level == CRYPT_LOG_ERROR) - crypt_set_error(cd, msg); + /* Default to stdout/stderr if there is no callback. */ + else + fprintf(level == CRYPT_LOG_ERROR ? stderr : stdout, "%s", msg); } __attribute__((format(printf, 5, 6))) @@ -154,24 +180,22 @@ void logger(struct crypt_device *cd, int level, const char *file, int line, const char *format, ...) { va_list argp; - char *target = NULL; + char target[LOG_MAX_LEN + 2]; + int len; va_start(argp, format); - if (vasprintf(&target, format, argp) > 0 ) { - if (level >= 0) { - crypt_log(cd, level, target); -#ifdef CRYPT_DEBUG - } else if (_debug_level) - printf("# %s:%d %s\n", file ?: "?", line, target); -#else - } else if (_debug_level) - printf("# %s\n", target); -#endif + len = vsnprintf(&target[0], LOG_MAX_LEN, format, argp); + if (len > 0 && len < LOG_MAX_LEN) { + /* All verbose and error messages in tools end with EOL. */ + if (level == CRYPT_LOG_VERBOSE || level == CRYPT_LOG_ERROR || + level == CRYPT_LOG_DEBUG || level == CRYPT_LOG_DEBUG_JSON) + strncat(target, "\n", LOG_MAX_LEN); + + crypt_log(cd, level, target); } va_end(argp); - free(target); } static const char *mdata_device_path(struct crypt_device *cd) @@ -179,6 +203,11 @@ static const char *mdata_device_path(struct crypt_device *cd) return device_path(cd->metadata_device ?: cd->device); } +static const char *data_device_path(struct crypt_device *cd) +{ + return device_path(cd->device); +} + /* internal only */ struct device *crypt_metadata_device(struct crypt_device *cd) { @@ -197,18 +226,19 @@ int init_crypto(struct crypt_device *ctx) r = crypt_random_init(ctx); if (r < 0) { - log_err(ctx, _("Cannot initialize crypto RNG backend.\n")); + log_err(ctx, _("Cannot initialize crypto RNG backend.")); return r; } - r = crypt_backend_init(ctx); + r = crypt_backend_init(); if (r < 0) - log_err(ctx, _("Cannot initialize crypto backend.\n")); + log_err(ctx, _("Cannot initialize crypto backend.")); if (!r && !_crypto_logged) { - log_dbg("Crypto backend (%s) initialized.", crypt_backend_version()); + log_dbg(ctx, "Crypto backend (%s) initialized in cryptsetup library version %s.", + crypt_backend_version(), PACKAGE_VERSION); if (!uname(&uts)) - log_dbg("Detected kernel %s %s %s.", + log_dbg(ctx, "Detected kernel %s %s %s.", uts.sysname, uts.release, uts.machine); _crypto_logged = 1; } @@ -233,10 +263,10 @@ static int process_key(struct crypt_device *cd, const char *hash_name, r = crypt_plain_hash(cd, hash_name, (*vk)->key, key_size, pass, passLen); if (r < 0) { if (r == -ENOENT) - log_err(cd, _("Hash algorithm %s not supported.\n"), + log_err(cd, _("Hash algorithm %s not supported."), hash_name); else - log_err(cd, _("Key processing error (using hash %s).\n"), + log_err(cd, _("Key processing error (using hash %s)."), hash_name); crypt_free_volume_key(*vk); *vk = NULL; @@ -256,11 +286,21 @@ static int isPLAIN(const char *type) return (type && !strcmp(CRYPT_PLAIN, type)); } -static int isLUKS(const char *type) +static int isLUKS1(const char *type) { return (type && !strcmp(CRYPT_LUKS1, type)); } +static int isLUKS2(const char *type) +{ + return (type && !strcmp(CRYPT_LUKS2, type)); +} + +static int isLUKS(const char *type) +{ + return (isLUKS2(type) || isLUKS1(type)); +} + static int isLOOPAES(const char *type) { return (type && !strcmp(CRYPT_LOOPAES, type)); @@ -276,20 +316,75 @@ static int isTCRYPT(const char *type) return (type && !strcmp(CRYPT_TCRYPT, type)); } -static int onlyLUKS(struct crypt_device *cd) +static int isINTEGRITY(const char *type) +{ + return (type && !strcmp(CRYPT_INTEGRITY, type)); +} + +static int isBITLK(const char *type) +{ + return (type && !strcmp(CRYPT_BITLK, type)); +} + +static int _onlyLUKS(struct crypt_device *cd, uint32_t cdflags) { int r = 0; if (cd && !cd->type) { - log_err(cd, _("Cannot determine device type. Incompatible activation of device?\n")); + if (!(cdflags & CRYPT_CD_QUIET)) + log_err(cd, _("Cannot determine device type. Incompatible activation of device?")); r = -EINVAL; } + if (!cd || !isLUKS(cd->type)) { - log_err(cd, _("This operation is supported only for LUKS device.\n")); + if (!(cdflags & CRYPT_CD_QUIET)) + log_err(cd, _("This operation is supported only for LUKS device.")); r = -EINVAL; } - return r; + if (r || (cdflags & CRYPT_CD_UNRESTRICTED) || isLUKS1(cd->type)) + return r; + + return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, cdflags & CRYPT_CD_QUIET); +} + +static int onlyLUKS(struct crypt_device *cd) +{ + return _onlyLUKS(cd, 0); +} + +static int _onlyLUKS2(struct crypt_device *cd, uint32_t cdflags, uint32_t mask) +{ + int r = 0; + + if (cd && !cd->type) { + if (!(cdflags & CRYPT_CD_QUIET)) + log_err(cd, _("Cannot determine device type. Incompatible activation of device?")); + r = -EINVAL; + } + + if (!cd || !isLUKS2(cd->type)) { + if (!(cdflags & CRYPT_CD_QUIET)) + log_err(cd, _("This operation is supported only for LUKS2 device.")); + r = -EINVAL; + } + + if (r || (cdflags & CRYPT_CD_UNRESTRICTED)) + return r; + + return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, mask, cdflags & CRYPT_CD_QUIET); +} + +/* Internal only */ +int onlyLUKS2(struct crypt_device *cd) +{ + return _onlyLUKS2(cd, 0, 0); +} + +/* Internal only */ +int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask) +{ + return _onlyLUKS2(cd, 0, mask); } static void crypt_set_null_type(struct crypt_device *cd) @@ -300,6 +395,9 @@ static void crypt_set_null_type(struct crypt_device *cd) free(cd->type); cd->type = NULL; cd->u.none.active_name = NULL; + cd->data_offset = 0; + cd->metadata_size = 0; + cd->keyslots_size = 0; } static void crypt_reset_null_type(struct crypt_device *cd) @@ -314,34 +412,44 @@ static void crypt_reset_null_type(struct crypt_device *cd) /* keyslot helpers */ static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot) { + crypt_keyslot_info ki; + if (*keyslot == CRYPT_ANY_SLOT) { - *keyslot = LUKS_keyslot_find_empty(&cd->u.luks1.hdr); + if (isLUKS1(cd->type)) + *keyslot = LUKS_keyslot_find_empty(&cd->u.luks1.hdr); + else + *keyslot = LUKS2_keyslot_find_empty(&cd->u.luks2.hdr); if (*keyslot < 0) { - log_err(cd, _("All key slots full.\n")); + log_err(cd, _("All key slots full.")); return -EINVAL; } } - switch (LUKS_keyslot_info(&cd->u.luks1.hdr, *keyslot)) { + if (isLUKS1(cd->type)) + ki = LUKS_keyslot_info(&cd->u.luks1.hdr, *keyslot); + else + ki = LUKS2_keyslot_info(&cd->u.luks2.hdr, *keyslot); + switch (ki) { case CRYPT_SLOT_INVALID: - log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"), + log_err(cd, _("Key slot %d is invalid, please select between 0 and %d."), *keyslot, LUKS_NUMKEYS - 1); return -EINVAL; case CRYPT_SLOT_INACTIVE: break; default: - log_err(cd, _("Key slot %d is full, please select another one.\n"), + log_err(cd, _("Key slot %d is full, please select another one."), *keyslot); return -EINVAL; } + log_dbg(cd, "Selected keyslot %d.", *keyslot); return 0; } /* * compares UUIDs returned by device-mapper (striped by cryptsetup) and uuid in header */ -static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid) +int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid) { int i, j; char *str; @@ -373,7 +481,7 @@ static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid) */ static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type) { - struct crypt_dm_active_device dmd = {}; + struct crypt_dm_active_device dmd; size_t len; int r; @@ -381,7 +489,7 @@ static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type) if (cd->type || !cd->u.none.active_name) return -EINVAL; - log_dbg("Checking if active device %s without header has UUID type %s.", + log_dbg(cd, "Checking if active device %s without header has UUID type %s.", cd->u.none.active_name, type); r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd); @@ -405,45 +513,29 @@ int PLAIN_activate(struct crypt_device *cd, uint32_t flags) { int r; - char *dm_cipher = NULL; - enum devcheck device_check; struct crypt_dm_active_device dmd = { - .target = DM_CRYPT, - .size = size, - .flags = flags, - .data_device = crypt_data_device(cd), - .u.crypt = { - .cipher = NULL, - .vk = vk, - .offset = crypt_get_data_offset(cd), - .iv_offset = crypt_get_iv_offset(cd), - } + .flags = flags, + .size = size, }; - if (dmd.flags & CRYPT_ACTIVATE_SHARED) - device_check = DEV_SHARED; - else - device_check = DEV_EXCL; + log_dbg(cd, "Trying to activate PLAIN device %s using cipher %s.", + name, crypt_get_cipher_spec(cd)); - r = device_block_adjust(cd, dmd.data_device, device_check, - dmd.u.crypt.offset, &dmd.size, &dmd.flags); - if (r) - return r; + if (MISALIGNED(size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) { + log_err(cd, _("Device size is not aligned to device logical block size.")); + return -EINVAL; + } - if (crypt_get_cipher_mode(cd)) - r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); - else - r = asprintf(&dm_cipher, "%s", crypt_get_cipher(cd)); + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), + vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), + crypt_get_data_offset(cd), crypt_get_integrity(cd), + crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); if (r < 0) - return -ENOMEM; - - dmd.u.crypt.cipher = dm_cipher; - log_dbg("Trying to activate PLAIN device %s using cipher %s.", - name, dmd.u.crypt.cipher); + return r; - r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd, 0); + r = create_or_reload_device(cd, name, CRYPT_PLAIN, &dmd); - free(dm_cipher); + dm_targets_free(cd, &dmd); return r; } @@ -455,98 +547,6 @@ int crypt_confirm(struct crypt_device *cd, const char *msg) return cd->confirm(msg, cd->confirm_usrptr); } -static int key_from_terminal(struct crypt_device *cd, char *msg, char **key, - size_t *key_len, int force_verify) -{ - char *prompt = NULL, *device_name; - int r; - - *key = NULL; - if(!msg) { - if (crypt_loop_device(crypt_get_device_name(cd))) - device_name = crypt_loop_backing_file(crypt_get_device_name(cd)); - else - device_name = strdup(crypt_get_device_name(cd)); - if (!device_name) - return -ENOMEM; - r = asprintf(&prompt, _("Enter passphrase for %s: "), device_name); - free(device_name); - if (r < 0) - return -ENOMEM; - msg = prompt; - } - - if (cd->password) { - *key = crypt_safe_alloc(DEFAULT_PASSPHRASE_SIZE_MAX); - if (!*key) { - r = -ENOMEM; - goto out; - } - r = cd->password(msg, *key, DEFAULT_PASSPHRASE_SIZE_MAX, - cd->password_usrptr); - if (r < 0) { - crypt_safe_free(*key); - *key = NULL; - } else - *key_len = r; - } else - r = crypt_get_key(msg, key, key_len, 0, 0, NULL, cd->timeout, - (force_verify || cd->password_verify), cd); -out: - free(prompt); - return (r < 0) ? r: 0; -} - -static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslot, - struct volume_key **vk) -{ - char *passphrase_read = NULL; - size_t passphrase_size_read; - int r = -EINVAL, eperm = 0, tries = cd->tries; - - *vk = NULL; - do { - crypt_free_volume_key(*vk); - *vk = NULL; - - r = key_from_terminal(cd, NULL, &passphrase_read, - &passphrase_size_read, 0); - /* Continue if it is just passphrase verify mismatch */ - if (r == -EPERM) - continue; - if(r < 0) - goto out; - - r = LUKS_open_key_with_hdr(keyslot, passphrase_read, - passphrase_size_read, &cd->u.luks1.hdr, vk, cd); - if (r == -EPERM) - eperm = 1; - crypt_safe_free(passphrase_read); - passphrase_read = NULL; - } while (r == -EPERM && (--tries > 0)); -out: - if (r < 0) { - crypt_free_volume_key(*vk); - *vk = NULL; - - /* Report wrong passphrase if at least one try failed */ - if (eperm && r == -EPIPE) - r = -EPERM; - } - - crypt_safe_free(passphrase_read); - return r; -} - -static int key_from_file(struct crypt_device *cd, char *msg, - char **key, size_t *key_len, - const char *key_file, size_t key_offset, - size_t key_size) -{ - return crypt_get_key(msg, key, key_len, key_offset, key_size, key_file, - cd->timeout, 0, cd); -} - void crypt_set_log_callback(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr) @@ -563,40 +563,10 @@ void crypt_set_confirm_callback(struct crypt_device *cd, int (*confirm)(const char *msg, void *usrptr), void *usrptr) { - cd->confirm = confirm; - cd->confirm_usrptr = usrptr; -} - -void crypt_set_password_callback(struct crypt_device *cd, - int (*password)(const char *msg, char *buf, size_t length, void *usrptr), - void *usrptr) -{ - cd->password = password; - cd->password_usrptr = usrptr; -} - -static void _get_error(char *error, char *buf, size_t size) -{ - if (!buf || size < 1) - error[0] = '\0'; - else if (*error) { - strncpy(buf, error, size - 1); - buf[size - 1] = '\0'; - error[0] = '\0'; - } else - buf[0] = '\0'; -} - -void crypt_last_error(struct crypt_device *cd, char *buf, size_t size) -{ - if (cd) - return _get_error(cd->error, buf, size); -} - -/* Deprecated global error interface */ -void crypt_get_error(char *buf, size_t size) -{ - return _get_error(global_error, buf, size); + if (cd) { + cd->confirm = confirm; + cd->confirm_usrptr = usrptr; + } } const char *crypt_get_dir(void) @@ -612,27 +582,28 @@ int crypt_init(struct crypt_device **cd, const char *device) if (!cd) return -EINVAL; - log_dbg("Allocating crypt device %s context.", device); + log_dbg(NULL, "Allocating context for crypt device %s.", device ?: "(none)"); +#if !HAVE_DECL_O_CLOEXEC + log_dbg(NULL, "Running without O_CLOEXEC."); +#endif if (!(h = malloc(sizeof(struct crypt_device)))) return -ENOMEM; memset(h, 0, sizeof(*h)); - r = device_alloc(&h->device, device); + r = device_alloc(NULL, &h->device, device); if (r < 0) goto bad; - dm_backend_init(); + dm_backend_init(NULL); - h->iteration_time = 1000; - h->password_verify = 0; - h->tries = 3; h->rng_type = crypt_random_default_key_rng(); + *cd = h; return 0; bad: - device_free(h->device); + device_free(NULL, h->device); free(h); return r; } @@ -642,7 +613,7 @@ static int crypt_check_data_device_size(struct crypt_device *cd) int r; uint64_t size, size_min; - /* Check data device size, require at least one sector */ + /* Check data device size, require at least header or one sector */ size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE; r = device_size(cd->device, &size); @@ -650,7 +621,7 @@ static int crypt_check_data_device_size(struct crypt_device *cd) return r; if (size < size_min) { - log_err(cd, _("Header detected but device %s is too small.\n"), + log_err(cd, _("Header detected but device %s is too small."), device_path(cd->device)); return -EINVAL; } @@ -658,53 +629,211 @@ static int crypt_check_data_device_size(struct crypt_device *cd) return r; } -int crypt_set_data_device(struct crypt_device *cd, const char *device) +static int _crypt_set_data_device(struct crypt_device *cd, const char *device) { struct device *dev = NULL; int r; - log_dbg("Setting ciphertext data device to %s.", device ?: "(none)"); - - if (!isLUKS(cd->type) && !isVERITY(cd->type)) { - log_err(cd, _("This operation is not supported for this device type.\n")); - return -EINVAL; - } - - /* metadata device must be set */ - if (!cd->device || !device) - return -EINVAL; - - r = device_alloc(&dev, device); + r = device_alloc(cd, &dev, device); if (r < 0) return r; if (!cd->metadata_device) { cd->metadata_device = cd->device; } else - device_free(cd->device); + device_free(cd, cd->device); cd->device = dev; return crypt_check_data_device_size(cd); } -static int _crypt_load_luks1(struct crypt_device *cd, int require_header, int repair) +int crypt_set_data_device(struct crypt_device *cd, const char *device) +{ + /* metadata device must be set */ + if (!cd || !cd->device || !device) + return -EINVAL; + + log_dbg(cd, "Setting ciphertext data device to %s.", device ?: "(none)"); + + if (!isLUKS1(cd->type) && !isLUKS2(cd->type) && !isVERITY(cd->type) && + !isINTEGRITY(cd->type)) { + log_err(cd, _("This operation is not supported for this device type.")); + return -EINVAL; + } + + if (isLUKS2(cd->type) && crypt_get_reenc_context(cd)) { + log_err(cd, _("Illegal operation with reencryption in-progress.")); + return -EINVAL; + } + + return _crypt_set_data_device(cd, device); +} + +int crypt_init_data_device(struct crypt_device **cd, const char *device, const char *data_device) { - struct luks_phdr hdr; int r; - r = init_crypto(cd); - if (r < 0) + if (!cd) + return -EINVAL; + + r = crypt_init(cd, device); + if (r || !data_device || !strcmp(device, data_device)) + return r; + + log_dbg(NULL, "Setting ciphertext data device to %s.", data_device); + r = _crypt_set_data_device(*cd, data_device); + if (r) { + crypt_free(*cd); + *cd = NULL; + } + + return r; +} + + +/* internal only */ +struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd) +{ + return &cd->pbkdf; +} + +/* + * crypt_load() helpers + */ +static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair) +{ + int r; + char *type = NULL; + struct luks2_hdr hdr2 = {}; + + log_dbg(cd, "%soading LUKS2 header (repair %sabled).", reload ? "Rel" : "L", repair ? "en" : "dis"); + + r = LUKS2_hdr_read(cd, &hdr2, repair); + if (r) return r; - r = LUKS_read_phdr(&hdr, require_header, repair, cd); + if (!reload && !(type = strdup(CRYPT_LUKS2))) { + r = -ENOMEM; + goto out; + } + + if (verify_pbkdf_params(cd, &cd->pbkdf)) { + r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2); + if (r) + goto out; + } + + if (reload) { + LUKS2_hdr_free(cd, &cd->u.luks2.hdr); + free(cd->u.luks2.keyslot_cipher); + } else + cd->type = type; + + r = 0; + memcpy(&cd->u.luks2.hdr, &hdr2, sizeof(hdr2)); + cd->u.luks2.keyslot_cipher = NULL; + cd->u.luks2.rh = NULL; + +out: + if (r) { + free(type); + LUKS2_hdr_free(cd, &hdr2); + } + return r; +} + +static void _luks2_reload(struct crypt_device *cd) +{ + if (!cd || !isLUKS2(cd->type)) + return; + + (void) _crypt_load_luks2(cd, 1, 0); +} + +static int _crypt_load_luks(struct crypt_device *cd, const char *requested_type, + int require_header, int repair) +{ + char *cipher_spec; + struct luks_phdr hdr = {}; + int r, version; + + r = init_crypto(cd); if (r < 0) return r; - if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) - return -ENOMEM; + /* This will return 0 if primary LUKS2 header is damaged */ + version = LUKS2_hdr_version_unlocked(cd, NULL); + + if ((isLUKS1(requested_type) && version == 2) || + (isLUKS2(requested_type) && version == 1)) + return -EINVAL; + + if (requested_type) + version = 0; + + if (isLUKS1(requested_type) || version == 1) { + if (cd->type && isLUKS2(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } - memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr)); + if (verify_pbkdf_params(cd, &cd->pbkdf)) { + r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1); + if (r) + return r; + } + + r = LUKS_read_phdr(&hdr, require_header, repair, cd); + if (r) + goto out; + + if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) { + r = -ENOMEM; + goto out; + } + + /* Set hash to the same as in the loaded header */ + if (!cd->pbkdf.hash || strcmp(cd->pbkdf.hash, hdr.hashSpec)) { + free(CONST_CAST(void*)cd->pbkdf.hash); + cd->pbkdf.hash = strdup(hdr.hashSpec); + if (!cd->pbkdf.hash) { + r = -ENOMEM; + goto out; + } + } + + if (asprintf(&cipher_spec, "%s-%s", hdr.cipherName, hdr.cipherMode) < 0) { + r = -ENOMEM; + goto out; + } + + free(cd->u.luks1.cipher_spec); + cd->u.luks1.cipher_spec = cipher_spec; + + memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr)); + } else if (isLUKS2(requested_type) || version == 2 || version == 0) { + if (cd->type && isLUKS1(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + + /* + * Current LUKS2 repair just overrides blkid probes + * and perform auto-recovery if possible. This is safe + * unless future LUKS2 repair code do something more + * sophisticated. In such case we would need to check + * for LUKS2 requirements and decide if it's safe to + * perform repair. + */ + r = _crypt_load_luks2(cd, cd->type != NULL, repair); + } else { + if (version > 2) + log_err(cd, _("Unsupported LUKS version %d."), version); + r = -EINVAL; + } +out: + crypt_safe_memzero(&hdr, sizeof(hdr)); return r; } @@ -716,6 +845,11 @@ static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcryp if (!params) return -EINVAL; + if (cd->metadata_device) { + log_err(cd, _("Detached metadata device is not supported for this crypt type.")); + return -EINVAL; + } + r = init_crypto(cd); if (r < 0) return r; @@ -728,6 +862,7 @@ static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcryp cd->u.tcrypt.params.passphrase_size = 0; cd->u.tcrypt.params.keyfiles = NULL; cd->u.tcrypt.params.keyfiles_count = 0; + cd->u.tcrypt.params.veracrypt_pim = 0; if (r < 0) return r; @@ -757,29 +892,270 @@ static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verit if (r < 0) return r; - if (params) - cd->u.verity.hdr.flags = params->flags; + //FIXME: use crypt_free + if (!cd->type && !(cd->type = strdup(CRYPT_VERITY))) { + free(CONST_CAST(void*)cd->u.verity.hdr.hash_name); + free(CONST_CAST(void*)cd->u.verity.hdr.salt); + free(cd->u.verity.uuid); + crypt_safe_memzero(&cd->u.verity.hdr, sizeof(cd->u.verity.hdr)); + return -ENOMEM; + } + + if (params) + cd->u.verity.hdr.flags = params->flags; /* Hash availability checked in sb load */ cd->u.verity.root_hash_size = crypt_hash_size(cd->u.verity.hdr.hash_name); if (cd->u.verity.root_hash_size > 4096) return -EINVAL; - if (!cd->type && !(cd->type = strdup(CRYPT_VERITY))) - return -ENOMEM; - if (params && params->data_device && (r = crypt_set_data_device(cd, params->data_device)) < 0) return r; + if (params && params->fec_device) { + r = device_alloc(cd, &cd->u.verity.fec_device, params->fec_device); + if (r < 0) + return r; + cd->u.verity.hdr.fec_area_offset = params->fec_area_offset; + cd->u.verity.hdr.fec_roots = params->fec_roots; + } + + return r; +} + +static int _crypt_load_integrity(struct crypt_device *cd, + struct crypt_params_integrity *params) +{ + int r; + + r = init_crypto(cd); + if (r < 0) + return r; + + r = INTEGRITY_read_sb(cd, &cd->u.integrity.params, &cd->u.integrity.sb_flags); + if (r < 0) + return r; + + // FIXME: add checks for fields in integrity sb vs params + + if (params) { + cd->u.integrity.params.journal_watermark = params->journal_watermark; + cd->u.integrity.params.journal_commit_time = params->journal_commit_time; + cd->u.integrity.params.buffer_sectors = params->buffer_sectors; + // FIXME: check ENOMEM + if (params->integrity) + cd->u.integrity.params.integrity = strdup(params->integrity); + cd->u.integrity.params.integrity_key_size = params->integrity_key_size; + if (params->journal_integrity) + cd->u.integrity.params.journal_integrity = strdup(params->journal_integrity); + if (params->journal_crypt) + cd->u.integrity.params.journal_crypt = strdup(params->journal_crypt); + + if (params->journal_crypt_key) { + cd->u.integrity.journal_crypt_key = + crypt_alloc_volume_key(params->journal_crypt_key_size, + params->journal_crypt_key); + if (!cd->u.integrity.journal_crypt_key) + return -ENOMEM; + } + if (params->journal_integrity_key) { + cd->u.integrity.journal_mac_key = + crypt_alloc_volume_key(params->journal_integrity_key_size, + params->journal_integrity_key); + if (!cd->u.integrity.journal_mac_key) + return -ENOMEM; + } + } + + if (!cd->type && !(cd->type = strdup(CRYPT_INTEGRITY))) { + free(CONST_CAST(void*)cd->u.integrity.params.integrity); + return -ENOMEM; + } + + return 0; +} + +static int _crypt_load_bitlk(struct crypt_device *cd, + struct bitlk_metadata *params) +{ + int r; + + r = init_crypto(cd); + if (r < 0) + return r; + + r = BITLK_read_sb(cd, &cd->u.bitlk.params); + if (r < 0) + return r; + + if (asprintf(&cd->u.bitlk.cipher_spec, "%s-%s", + cd->u.bitlk.params.cipher, cd->u.bitlk.params.cipher_mode) < 0) { + cd->u.bitlk.cipher_spec = NULL; + return -ENOMEM; + } + + if (!cd->type && !(cd->type = strdup(CRYPT_BITLK))) + return -ENOMEM; + + return 0; +} + +int crypt_load(struct crypt_device *cd, + const char *requested_type, + void *params) +{ + int r; + + if (!cd) + return -EINVAL; + + log_dbg(cd, "Trying to load %s crypt type from device %s.", + requested_type ?: "any", mdata_device_path(cd) ?: "(none)"); + + if (!crypt_metadata_device(cd)) + return -EINVAL; + + crypt_reset_null_type(cd); + cd->data_offset = 0; + cd->metadata_size = 0; + cd->keyslots_size = 0; + + if (!requested_type || isLUKS1(requested_type) || isLUKS2(requested_type)) { + if (cd->type && !isLUKS1(cd->type) && !isLUKS2(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + + r = _crypt_load_luks(cd, requested_type, 1, 0); + } else if (isVERITY(requested_type)) { + if (cd->type && !isVERITY(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + r = _crypt_load_verity(cd, params); + } else if (isTCRYPT(requested_type)) { + if (cd->type && !isTCRYPT(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + r = _crypt_load_tcrypt(cd, params); + } else if (isINTEGRITY(requested_type)) { + if (cd->type && !isINTEGRITY(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + r = _crypt_load_integrity(cd, params); + } else if (isBITLK(requested_type)) { + if (cd->type && !isBITLK(cd->type)) { + log_dbg(cd, "Context is already initialized to type %s", cd->type); + return -EINVAL; + } + r = _crypt_load_bitlk(cd, params); + } else + return -EINVAL; + + return r; +} + +/* + * crypt_init() helpers + */ +static int _init_by_name_crypt_none(struct crypt_device *cd) +{ + int r; + char _mode[MAX_CIPHER_LEN]; + struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; + + if (cd->type || !cd->u.none.active_name) + return -EINVAL; + + r = dm_query_device(cd, cd->u.none.active_name, + DM_ACTIVE_CRYPT_CIPHER | + DM_ACTIVE_CRYPT_KEYSIZE, &dmd); + if (r < 0) + return r; + if (!single_segment(&dmd) || tgt->type != DM_CRYPT) + r = -EINVAL; + if (r >= 0) + r = crypt_parse_name_and_mode(tgt->u.crypt.cipher, + cd->u.none.cipher, NULL, + _mode); + + if (!r) { + snprintf(cd->u.none.cipher_spec, sizeof(cd->u.none.cipher_spec), + "%s-%s", cd->u.none.cipher, _mode); + cd->u.none.cipher_mode = cd->u.none.cipher_spec + strlen(cd->u.none.cipher) + 1; + cd->u.none.key_size = tgt->u.crypt.vk->keylength; + } + + dm_targets_free(cd, &dmd); return r; } +static const char *LUKS_UUID(struct crypt_device *cd) +{ + if (!cd) + return NULL; + else if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.uuid; + else if (isLUKS2(cd->type)) + return cd->u.luks2.hdr.uuid; + + return NULL; +} + +static void crypt_free_type(struct crypt_device *cd) +{ + if (isPLAIN(cd->type)) { + free(CONST_CAST(void*)cd->u.plain.hdr.hash); + free(cd->u.plain.cipher); + free(cd->u.plain.cipher_spec); + } else if (isLUKS2(cd->type)) { + LUKS2_reenc_context_free(cd, cd->u.luks2.rh); + LUKS2_hdr_free(cd, &cd->u.luks2.hdr); + free(cd->u.luks2.keyslot_cipher); + } else if (isLUKS1(cd->type)) { + free(cd->u.luks1.cipher_spec); + } else if (isLOOPAES(cd->type)) { + free(CONST_CAST(void*)cd->u.loopaes.hdr.hash); + free(cd->u.loopaes.cipher); + free(cd->u.loopaes.cipher_spec); + } else if (isVERITY(cd->type)) { + free(CONST_CAST(void*)cd->u.verity.hdr.hash_name); + free(CONST_CAST(void*)cd->u.verity.hdr.data_device); + free(CONST_CAST(void*)cd->u.verity.hdr.hash_device); + free(CONST_CAST(void*)cd->u.verity.hdr.fec_device); + free(CONST_CAST(void*)cd->u.verity.hdr.salt); + free(CONST_CAST(void*)cd->u.verity.root_hash); + free(cd->u.verity.uuid); + device_free(cd, cd->u.verity.fec_device); + } else if (isINTEGRITY(cd->type)) { + free(CONST_CAST(void*)cd->u.integrity.params.integrity); + free(CONST_CAST(void*)cd->u.integrity.params.journal_integrity); + free(CONST_CAST(void*)cd->u.integrity.params.journal_crypt); + crypt_free_volume_key(cd->u.integrity.journal_crypt_key); + crypt_free_volume_key(cd->u.integrity.journal_mac_key); + } else if (isBITLK(cd->type)) { + free(cd->u.bitlk.cipher_spec); + BITLK_bitlk_metadata_free(&cd->u.bitlk.params); + } else if (!cd->type) { + free(cd->u.none.active_name); + cd->u.none.active_name = NULL; + } + + crypt_set_null_type(cd); +} + static int _init_by_name_crypt(struct crypt_device *cd, const char *name) { - struct crypt_dm_active_device dmd = {}; - char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN]; + bool found = false; + char **dep, *cipher_spec = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN], deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = {}; + const char *dev, *namei; int key_nums, r; + struct crypt_dm_active_device dmd, dmdi = {}, dmdep = {}; + struct dm_target *tgt = &dmd.segment, *tgti = &dmdi.segment; r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | @@ -787,106 +1163,245 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name) DM_ACTIVE_CRYPT_CIPHER | DM_ACTIVE_CRYPT_KEYSIZE, &dmd); if (r < 0) + return r; + + if (tgt->type != DM_CRYPT && tgt->type != DM_LINEAR) { + log_dbg(cd, "Unsupported device table detected in %s.", name); + r = -EINVAL; goto out; - if (r > 0) - r = 0; + } - if (isPLAIN(cd->type)) { - cd->u.plain.hdr.hash = NULL; /* no way to get this */ - cd->u.plain.hdr.offset = dmd.u.crypt.offset; - cd->u.plain.hdr.skip = dmd.u.crypt.iv_offset; - cd->u.plain.key_size = dmd.u.crypt.vk->keylength; + r = -EINVAL; - r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher, NULL, cipher_mode); - if (!r) { - cd->u.plain.cipher = strdup(cipher); - cd->u.plain.cipher_mode = strdup(cipher_mode); + if (dmd.uuid) { + r = snprintf(deps_uuid_prefix, sizeof(deps_uuid_prefix), CRYPT_SUBDEV "-%.32s", dmd.uuid + 6); + if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1)) + r = -EINVAL; + } + + if (r >= 0) { + r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps)); + if (r) + goto out; + } + + r = crypt_parse_name_and_mode(tgt->type == DM_LINEAR ? "null" : tgt->u.crypt.cipher, cipher, + &key_nums, cipher_mode); + if (r < 0) { + log_dbg(cd, "Cannot parse cipher and mode from active device."); + goto out; + } + + dep = deps; + + if (tgt->type == DM_CRYPT && tgt->u.crypt.integrity && (namei = device_dm_name(tgt->data_device))) { + r = dm_query_device(cd, namei, DM_ACTIVE_DEVICE, &dmdi); + if (r < 0) + goto out; + if (!single_segment(&dmdi) || tgti->type != DM_INTEGRITY) { + log_dbg(cd, "Unsupported device table detected in %s.", namei); + r = -EINVAL; + goto out; } - } else if (isLOOPAES(cd->type)) { - cd->u.loopaes.hdr.offset = dmd.u.crypt.offset; + if (!cd->metadata_device) { + device_free(cd, cd->device); + MOVE_REF(cd->device, tgti->data_device); + } + } - r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher, - &key_nums, cipher_mode); - if (!r) { - cd->u.loopaes.cipher = strdup(cipher); - cd->u.loopaes.cipher_mode = strdup(cipher_mode); - /* version 3 uses last key for IV */ - if (dmd.u.crypt.vk->keylength % key_nums) - key_nums++; - cd->u.loopaes.key_size = dmd.u.crypt.vk->keylength / key_nums; + /* do not try to lookup LUKS2 header in detached header mode */ + if (!cd->metadata_device && !found) { + while (*dep && !found) { + r = dm_query_device(cd, *dep, DM_ACTIVE_DEVICE, &dmdep); + if (r < 0) + goto out; + + tgt = &dmdep.segment; + + while (tgt && !found) { + dev = device_path(tgt->data_device); + if (!dev) { + tgt = tgt->next; + continue; + } + if (!strstr(dev, dm_get_dir()) || + !crypt_string_in(dev + strlen(dm_get_dir()) + 1, deps, ARRAY_SIZE(deps))) { + device_free(cd, cd->device); + MOVE_REF(cd->device, tgt->data_device); + found = true; + } + tgt = tgt->next; + } + dep++; + dm_targets_free(cd, &dmdep); } - } else if (isLUKS(cd->type)) { + } + + if (asprintf(&cipher_spec, "%s-%s", cipher, cipher_mode) < 0) { + cipher_spec = NULL; + r = -ENOMEM; + goto out; + } + + tgt = &dmd.segment; + r = 0; + + if (isPLAIN(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) { + cd->u.plain.hdr.hash = NULL; /* no way to get this */ + cd->u.plain.hdr.offset = tgt->u.crypt.offset; + cd->u.plain.hdr.skip = tgt->u.crypt.iv_offset; + cd->u.plain.hdr.sector_size = tgt->u.crypt.sector_size; + cd->u.plain.key_size = tgt->u.crypt.vk->keylength; + cd->u.plain.cipher = strdup(cipher); + MOVE_REF(cd->u.plain.cipher_spec, cipher_spec); + cd->u.plain.cipher_mode = cd->u.plain.cipher_spec + strlen(cipher) + 1; + } else if (isLOOPAES(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) { + cd->u.loopaes.hdr.offset = tgt->u.crypt.offset; + cd->u.loopaes.cipher = strdup(cipher); + MOVE_REF(cd->u.loopaes.cipher_spec, cipher_spec); + cd->u.loopaes.cipher_mode = cd->u.loopaes.cipher_spec + strlen(cipher) + 1; + /* version 3 uses last key for IV */ + if (tgt->u.crypt.vk->keylength % key_nums) + key_nums++; + cd->u.loopaes.key_size = tgt->u.crypt.vk->keylength / key_nums; + } else if (isLUKS1(cd->type) || isLUKS2(cd->type)) { if (crypt_metadata_device(cd)) { - r = _crypt_load_luks1(cd, 0, 0); + r = _crypt_load_luks(cd, cd->type, 0, 0); if (r < 0) { - log_dbg("LUKS device header does not match active device."); + log_dbg(cd, "LUKS device header does not match active device."); crypt_set_null_type(cd); + device_close(cd, cd->metadata_device); + device_close(cd, cd->device); r = 0; goto out; } /* check whether UUIDs match each other */ - r = crypt_uuid_cmp(dmd.uuid, cd->u.luks1.hdr.uuid); + r = crypt_uuid_cmp(dmd.uuid, LUKS_UUID(cd)); if (r < 0) { - log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s", - cd->u.luks1.hdr.uuid, dmd.uuid); - crypt_set_null_type(cd); + log_dbg(cd, "LUKS device header uuid: %s mismatches DM returned uuid %s", + LUKS_UUID(cd), dmd.uuid); + crypt_free_type(cd); r = 0; + goto out; } } else { - log_dbg("LUKS device header not available."); + log_dbg(cd, "LUKS device header not available."); crypt_set_null_type(cd); r = 0; } - } else if (isTCRYPT(cd->type)) { - r = TCRYPT_init_by_name(cd, name, &dmd, &cd->device, + } else if (isTCRYPT(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) { + r = TCRYPT_init_by_name(cd, name, dmd.uuid, tgt, &cd->device, &cd->u.tcrypt.params, &cd->u.tcrypt.hdr); + } else if (isBITLK(cd->type)) { + r = _crypt_load_bitlk(cd, NULL); + if (r < 0) { + log_dbg(cd, "BITLK device header not available."); + crypt_set_null_type(cd); + r = 0; + } } out: - crypt_free_volume_key(dmd.u.crypt.vk); - device_free(dmd.data_device); - free(CONST_CAST(void*)dmd.u.crypt.cipher); + dm_targets_free(cd, &dmd); + dm_targets_free(cd, &dmdi); + dm_targets_free(cd, &dmdep); free(CONST_CAST(void*)dmd.uuid); + free(cipher_spec); + dep = deps; + while (*dep) + free(*dep++); return r; } static int _init_by_name_verity(struct crypt_device *cd, const char *name) { - struct crypt_params_verity params = {}; - struct crypt_dm_active_device dmd = { - .target = DM_VERITY, - .u.verity.vp = ¶ms, - }; + struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; int r; r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_VERITY_HASH_DEVICE | + DM_ACTIVE_VERITY_ROOT_HASH | DM_ACTIVE_VERITY_PARAMS, &dmd); if (r < 0) + return r; + if (!single_segment(&dmd) || tgt->type != DM_VERITY) { + log_dbg(cd, "Unsupported device table detected in %s.", name); + r = -EINVAL; goto out; + } if (r > 0) r = 0; if (isVERITY(cd->type)) { cd->u.verity.uuid = NULL; // FIXME cd->u.verity.hdr.flags = CRYPT_VERITY_NO_HEADER; //FIXME - cd->u.verity.hdr.data_size = params.data_size; - cd->u.verity.root_hash_size = dmd.u.verity.root_hash_size; - cd->u.verity.root_hash = NULL; - cd->u.verity.hdr.hash_name = params.hash_name; + cd->u.verity.hdr.data_size = tgt->u.verity.vp->data_size; + cd->u.verity.root_hash_size = tgt->u.verity.root_hash_size; + MOVE_REF(cd->u.verity.hdr.hash_name, tgt->u.verity.vp->hash_name); cd->u.verity.hdr.data_device = NULL; cd->u.verity.hdr.hash_device = NULL; - cd->u.verity.hdr.data_block_size = params.data_block_size; - cd->u.verity.hdr.hash_block_size = params.hash_block_size; - cd->u.verity.hdr.hash_area_offset = dmd.u.verity.hash_offset; - cd->u.verity.hdr.hash_type = params.hash_type; - cd->u.verity.hdr.flags = params.flags; - cd->u.verity.hdr.salt_size = params.salt_size; - cd->u.verity.hdr.salt = params.salt; - cd->metadata_device = dmd.u.verity.hash_device; + cd->u.verity.hdr.data_block_size = tgt->u.verity.vp->data_block_size; + cd->u.verity.hdr.hash_block_size = tgt->u.verity.vp->hash_block_size; + cd->u.verity.hdr.hash_area_offset = tgt->u.verity.hash_offset; + cd->u.verity.hdr.fec_area_offset = tgt->u.verity.fec_offset; + cd->u.verity.hdr.hash_type = tgt->u.verity.vp->hash_type; + cd->u.verity.hdr.flags = tgt->u.verity.vp->flags; + cd->u.verity.hdr.salt_size = tgt->u.verity.vp->salt_size; + MOVE_REF(cd->u.verity.hdr.salt, tgt->u.verity.vp->salt); + MOVE_REF(cd->u.verity.hdr.fec_device, tgt->u.verity.vp->fec_device); + cd->u.verity.hdr.fec_roots = tgt->u.verity.vp->fec_roots; + MOVE_REF(cd->u.verity.fec_device, tgt->u.verity.fec_device); + MOVE_REF(cd->metadata_device, tgt->u.verity.hash_device); + MOVE_REF(cd->u.verity.root_hash, tgt->u.verity.root_hash); + } +out: + dm_targets_free(cd, &dmd); + return r; +} + +static int _init_by_name_integrity(struct crypt_device *cd, const char *name) +{ + struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; + int r; + + r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | + DM_ACTIVE_CRYPT_KEY | + DM_ACTIVE_CRYPT_KEYSIZE | + DM_ACTIVE_INTEGRITY_PARAMS, &dmd); + if (r < 0) + return r; + if (!single_segment(&dmd) || tgt->type != DM_INTEGRITY) { + log_dbg(cd, "Unsupported device table detected in %s.", name); + r = -EINVAL; + goto out; + } + if (r > 0) + r = 0; + + if (isINTEGRITY(cd->type)) { + cd->u.integrity.params.tag_size = tgt->u.integrity.tag_size; + cd->u.integrity.params.sector_size = tgt->u.integrity.sector_size; + cd->u.integrity.params.journal_size = tgt->u.integrity.journal_size; + cd->u.integrity.params.journal_watermark = tgt->u.integrity.journal_watermark; + cd->u.integrity.params.journal_commit_time = tgt->u.integrity.journal_commit_time; + cd->u.integrity.params.interleave_sectors = tgt->u.integrity.interleave_sectors; + cd->u.integrity.params.buffer_sectors = tgt->u.integrity.buffer_sectors; + MOVE_REF(cd->u.integrity.params.integrity, tgt->u.integrity.integrity); + MOVE_REF(cd->u.integrity.params.journal_integrity, tgt->u.integrity.journal_integrity); + MOVE_REF(cd->u.integrity.params.journal_crypt, tgt->u.integrity.journal_crypt); + + if (tgt->u.integrity.vk) + cd->u.integrity.params.integrity_key_size = tgt->u.integrity.vk->keylength; + if (tgt->u.integrity.journal_integrity_key) + cd->u.integrity.params.journal_integrity_key_size = tgt->u.integrity.journal_integrity_key->keylength; + if (tgt->u.integrity.journal_crypt_key) + cd->u.integrity.params.integrity_key_size = tgt->u.integrity.journal_crypt_key->keylength; + MOVE_REF(cd->metadata_device, tgt->u.integrity.meta_device); } out: - device_free(dmd.data_device); + dm_targets_free(cd, &dmd); return r; } @@ -896,41 +1411,42 @@ int crypt_init_by_name_and_header(struct crypt_device **cd, { crypt_status_info ci; struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; int r; - log_dbg("Allocating crypt device context by device %s.", name); + if (!cd || !name) + return -EINVAL; + + log_dbg(NULL, "Allocating crypt device context by device %s.", name); ci = crypt_status(NULL, name); if (ci == CRYPT_INVALID) return -ENODEV; if (ci < CRYPT_ACTIVE) { - log_err(NULL, _("Device %s is not active.\n"), name); + log_err(NULL, _("Device %s is not active."), name); return -ENODEV; } r = dm_query_device(NULL, name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd); if (r < 0) - goto out; + return r; *cd = NULL; if (header_device) { r = crypt_init(cd, header_device); } else { - r = crypt_init(cd, device_path(dmd.data_device)); + r = crypt_init(cd, device_path(tgt->data_device)); /* Underlying device disappeared but mapping still active */ - if (!dmd.data_device || r == -ENOTBLK) - log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"), + if (!tgt->data_device || r == -ENOTBLK) + log_verbose(NULL, _("Underlying device for crypt device %s disappeared."), name); /* Underlying device is not readable but crypt mapping exists */ - if (r == -ENOTBLK) { - device_free(dmd.data_device); - dmd.data_device = NULL; + if (r == -ENOTBLK) r = crypt_init(cd, NULL); - } } if (r < 0) @@ -943,38 +1459,46 @@ int crypt_init_by_name_and_header(struct crypt_device **cd, (*cd)->type = strdup(CRYPT_LOOPAES); else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1)) (*cd)->type = strdup(CRYPT_LUKS1); + else if (!strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1)) + (*cd)->type = strdup(CRYPT_LUKS2); else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1)) (*cd)->type = strdup(CRYPT_VERITY); else if (!strncmp(CRYPT_TCRYPT, dmd.uuid, sizeof(CRYPT_TCRYPT)-1)) (*cd)->type = strdup(CRYPT_TCRYPT); + else if (!strncmp(CRYPT_INTEGRITY, dmd.uuid, sizeof(CRYPT_INTEGRITY)-1)) + (*cd)->type = strdup(CRYPT_INTEGRITY); + else if (!strncmp(CRYPT_BITLK, dmd.uuid, sizeof(CRYPT_BITLK)-1)) + (*cd)->type = strdup(CRYPT_BITLK); else - log_dbg("Unknown UUID set, some parameters are not set."); + log_dbg(NULL, "Unknown UUID set, some parameters are not set."); } else - log_dbg("Active device has no UUID set, some parameters are not set."); + log_dbg(NULL, "Active device has no UUID set, some parameters are not set."); if (header_device) { - r = crypt_set_data_device(*cd, device_path(dmd.data_device)); + r = crypt_set_data_device(*cd, device_path(tgt->data_device)); if (r < 0) goto out; } - /* Try to initialise basic parameters from active device */ + /* Try to initialize basic parameters from active device */ - if (dmd.target == DM_CRYPT) + if (tgt->type == DM_CRYPT || tgt->type == DM_LINEAR) r = _init_by_name_crypt(*cd, name); - else if (dmd.target == DM_VERITY) + else if (tgt->type == DM_VERITY) r = _init_by_name_verity(*cd, name); + else if (tgt->type == DM_INTEGRITY) + r = _init_by_name_integrity(*cd, name); out: if (r < 0) { crypt_free(*cd); *cd = NULL; - } else if (!(*cd)->type && name) { + } else if (!(*cd)->type) { /* For anonymous device (no header found) remember initialized name */ (*cd)->u.none.active_name = strdup(name); } - device_free(dmd.data_device); free(CONST_CAST(void*)dmd.uuid); + dm_targets_free(NULL, &dmd); return r; } @@ -983,6 +1507,9 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name) return crypt_init_by_name_and_header(cd, name, NULL); } +/* + * crypt_format() helpers + */ static int _crypt_format_plain(struct crypt_device *cd, const char *cipher, const char *cipher_mode, @@ -990,21 +1517,48 @@ static int _crypt_format_plain(struct crypt_device *cd, size_t volume_key_size, struct crypt_params_plain *params) { + unsigned int sector_size = params ? params->sector_size : SECTOR_SIZE; + uint64_t dev_size; + if (!cipher || !cipher_mode) { - log_err(cd, _("Invalid plain crypt parameters.\n")); + log_err(cd, _("Invalid plain crypt parameters.")); return -EINVAL; } if (volume_key_size > 1024) { - log_err(cd, _("Invalid key size.\n")); + log_err(cd, _("Invalid key size.")); return -EINVAL; } if (uuid) { - log_err(cd, _("UUID is not supported for this crypt type.\n")); + log_err(cd, _("UUID is not supported for this crypt type.")); + return -EINVAL; + } + + if (cd->metadata_device) { + log_err(cd, _("Detached metadata device is not supported for this crypt type.")); + return -EINVAL; + } + + /* For compatibility with old params structure */ + if (!sector_size) + sector_size = SECTOR_SIZE; + + if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE || + NOTPOW2(sector_size)) { + log_err(cd, _("Unsupported encryption sector size.")); return -EINVAL; } + if (sector_size > SECTOR_SIZE && !device_size(cd->device, &dev_size)) { + if (params && params->offset) + dev_size -= (params->offset * SECTOR_SIZE); + if (dev_size % sector_size) { + log_err(cd, _("Device size is not aligned to requested sector size.")); + return -EINVAL; + } + } + if (!(cd->type = strdup(CRYPT_PLAIN))) return -ENOMEM; @@ -1013,9 +1567,12 @@ static int _crypt_format_plain(struct crypt_device *cd, if (!cd->volume_key) return -ENOMEM; + if (asprintf(&cd->u.plain.cipher_spec, "%s-%s", cipher, cipher_mode) < 0) { + cd->u.plain.cipher_spec = NULL; + return -ENOMEM; + } cd->u.plain.cipher = strdup(cipher); - cd->u.plain.cipher_mode = strdup(cipher_mode); - + cd->u.plain.cipher_mode = cd->u.plain.cipher_spec + strlen(cipher) + 1; if (params && params->hash) cd->u.plain.hdr.hash = strdup(params->hash); @@ -1023,8 +1580,9 @@ static int _crypt_format_plain(struct crypt_device *cd, cd->u.plain.hdr.offset = params ? params->offset : 0; cd->u.plain.hdr.skip = params ? params->skip : 0; cd->u.plain.hdr.size = params ? params->size : 0; + cd->u.plain.hdr.sector_size = sector_size; - if (!cd->u.plain.cipher || !cd->u.plain.cipher_mode) + if (!cd->u.plain.cipher) return -ENOMEM; return 0; @@ -1041,9 +1599,19 @@ static int _crypt_format_luks1(struct crypt_device *cd, int r; unsigned long required_alignment = DEFAULT_DISK_ALIGNMENT; unsigned long alignment_offset = 0; + uint64_t dev_size; + + if (!cipher || !cipher_mode) + return -EINVAL; if (!crypt_metadata_device(cd)) { - log_err(cd, _("Can't format LUKS without device.\n")); + log_err(cd, _("Can't format LUKS without device.")); + return -EINVAL; + } + + if (params && cd->data_offset && params->data_alignment && + (cd->data_offset % params->data_alignment)) { + log_err(cd, _("Requested data alignment is not compatible with data offset.")); return -EINVAL; } @@ -1056,50 +1624,312 @@ static int _crypt_format_luks1(struct crypt_device *cd, else cd->volume_key = crypt_generate_volume_key(cd, volume_key_size); - if(!cd->volume_key) + if (!cd->volume_key) return -ENOMEM; + if (verify_pbkdf_params(cd, &cd->pbkdf)) { + r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1); + if (r) + return r; + } + + if (params && params->hash && strcmp(params->hash, cd->pbkdf.hash)) { + free(CONST_CAST(void*)cd->pbkdf.hash); + cd->pbkdf.hash = strdup(params->hash); + if (!cd->pbkdf.hash) + return -ENOMEM; + } + if (params && params->data_device) { - cd->metadata_device = cd->device; + if (!cd->metadata_device) + cd->metadata_device = cd->device; + else + device_free(cd, cd->device); cd->device = NULL; - if (device_alloc(&cd->device, params->data_device) < 0) + if (device_alloc(cd, &cd->device, params->data_device) < 0) return -ENOMEM; + } + + if (params && cd->metadata_device) { + /* For detached header the alignment is used directly as data offset */ + if (!cd->data_offset) + cd->data_offset = params->data_alignment; required_alignment = params->data_alignment * SECTOR_SIZE; } else if (params && params->data_alignment) { required_alignment = params->data_alignment * SECTOR_SIZE; } else - device_topology_alignment(cd->device, + device_topology_alignment(cd, cd->device, &required_alignment, &alignment_offset, DEFAULT_DISK_ALIGNMENT); - r = LUKS_generate_phdr(&cd->u.luks1.hdr, cd->volume_key, cipher, cipher_mode, - (params && params->hash) ? params->hash : "sha1", - uuid, LUKS_STRIPES, - required_alignment / SECTOR_SIZE, - alignment_offset / SECTOR_SIZE, - cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, - cd->metadata_device ? 1 : 0, cd); - if(r < 0) + r = LUKS_check_cipher(cd, volume_key_size, cipher, cipher_mode); + if (r < 0) return r; - /* Wipe first 8 sectors - fs magic numbers etc. */ - r = crypt_wipe(crypt_metadata_device(cd), 0, 8 * SECTOR_SIZE, CRYPT_WIPE_ZERO, 1); - if(r < 0) { - if (r == -EBUSY) - log_err(cd, _("Cannot format device %s which is still in use.\n"), - mdata_device_path(cd)); - else if (r == -EACCES) { - log_err(cd, _("Cannot format device %s, permission denied.\n"), - mdata_device_path(cd)); - r = -EINVAL; - } else - log_err(cd, _("Cannot wipe header on device %s.\n"), - mdata_device_path(cd)); - + r = LUKS_generate_phdr(&cd->u.luks1.hdr, cd->volume_key, cipher, cipher_mode, + cd->pbkdf.hash, uuid, + cd->data_offset * SECTOR_SIZE, + alignment_offset, required_alignment, cd); + if (r < 0) return r; - } + + r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL); + if (r < 0) + return r; + + if (!device_size(crypt_data_device(cd), &dev_size) && + dev_size < (crypt_get_data_offset(cd) * SECTOR_SIZE)) + log_std(cd, _("WARNING: Data offset is outside of currently available data device.\n")); + + if (asprintf(&cd->u.luks1.cipher_spec, "%s-%s", cipher, cipher_mode) < 0) { + cd->u.luks1.cipher_spec = NULL; + return -ENOMEM; + } + + r = LUKS_wipe_header_areas(&cd->u.luks1.hdr, cd); + if (r < 0) { + free(cd->u.luks1.cipher_spec); + log_err(cd, _("Cannot wipe header on device %s."), + mdata_device_path(cd)); + return r; + } r = LUKS_write_phdr(&cd->u.luks1.hdr, cd); + if (r) + free(cd->u.luks1.cipher_spec); + + return r; +} + +static int _crypt_format_luks2(struct crypt_device *cd, + const char *cipher, + const char *cipher_mode, + const char *uuid, + const char *volume_key, + size_t volume_key_size, + struct crypt_params_luks2 *params) +{ + int r, integrity_key_size = 0; + unsigned long required_alignment = DEFAULT_DISK_ALIGNMENT; + unsigned long alignment_offset = 0; + unsigned int sector_size = params ? params->sector_size : SECTOR_SIZE; + const char *integrity = params ? params->integrity : NULL; + uint64_t dev_size; + uint32_t dmc_flags; + + cd->u.luks2.hdr.jobj = NULL; + cd->u.luks2.keyslot_cipher = NULL; + + if (!cipher || !cipher_mode) + return -EINVAL; + + if (!crypt_metadata_device(cd)) { + log_err(cd, _("Can't format LUKS without device.")); + return -EINVAL; + } + + if (params && cd->data_offset && params->data_alignment && + (cd->data_offset % params->data_alignment)) { + log_err(cd, _("Requested data alignment is not compatible with data offset.")); + return -EINVAL; + } + + if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE || + NOTPOW2(sector_size)) { + log_err(cd, _("Unsupported encryption sector size.")); + return -EINVAL; + } + if (sector_size != SECTOR_SIZE && !dm_flags(cd, DM_CRYPT, &dmc_flags) && + !(dmc_flags & DM_SECTOR_SIZE_SUPPORTED)) + log_std(cd, _("WARNING: The device activation will fail, dm-crypt is missing " + "support for requested encryption sector size.\n")); + + if (integrity) { + if (params->integrity_params) { + /* Standalone dm-integrity must not be used */ + if (params->integrity_params->integrity || + params->integrity_params->integrity_key_size) + return -EINVAL; + /* FIXME: journal encryption and MAC is here not yet supported */ + if (params->integrity_params->journal_crypt || + params->integrity_params->journal_integrity) + return -ENOTSUP; + } + if (!INTEGRITY_tag_size(cd, integrity, cipher, cipher_mode)) { + if (!strcmp(integrity, "none")) + integrity = NULL; + else + return -EINVAL; + } + integrity_key_size = INTEGRITY_key_size(cd, integrity); + if ((integrity_key_size < 0) || (integrity_key_size >= (int)volume_key_size)) { + log_err(cd, _("Volume key is too small for encryption with integrity extensions.")); + return -EINVAL; + } + } + + r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL); + if (r < 0) + return r; + + if (!(cd->type = strdup(CRYPT_LUKS2))) + return -ENOMEM; + + if (volume_key) + cd->volume_key = crypt_alloc_volume_key(volume_key_size, + volume_key); + else + cd->volume_key = crypt_generate_volume_key(cd, volume_key_size); + + if (!cd->volume_key) + return -ENOMEM; + + if (params && params->pbkdf) + r = crypt_set_pbkdf_type(cd, params->pbkdf); + else if (verify_pbkdf_params(cd, &cd->pbkdf)) + r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2); + + if (r < 0) + return r; + + if (params && params->data_device) { + if (!cd->metadata_device) + cd->metadata_device = cd->device; + else + device_free(cd, cd->device); + cd->device = NULL; + if (device_alloc(cd, &cd->device, params->data_device) < 0) + return -ENOMEM; + } + + if (params && cd->metadata_device) { + /* For detached header the alignment is used directly as data offset */ + if (!cd->data_offset) + cd->data_offset = params->data_alignment; + required_alignment = params->data_alignment * SECTOR_SIZE; + } else if (params && params->data_alignment) { + required_alignment = params->data_alignment * SECTOR_SIZE; + } else + device_topology_alignment(cd, cd->device, + &required_alignment, + &alignment_offset, DEFAULT_DISK_ALIGNMENT); + + /* FIXME: allow this later also for normal ciphers (check AF_ALG availability. */ + if (integrity && !integrity_key_size) { + r = crypt_cipher_check_kernel(cipher, cipher_mode, integrity, volume_key_size); + if (r < 0) { + log_err(cd, _("Cipher %s-%s (key size %zd bits) is not available."), + cipher, cipher_mode, volume_key_size * 8); + goto out; + } + } + + if ((!integrity || integrity_key_size) && !crypt_cipher_wrapped_key(cipher, cipher_mode) && + !INTEGRITY_tag_size(cd, NULL, cipher, cipher_mode)) { + r = LUKS_check_cipher(cd, volume_key_size - integrity_key_size, + cipher, cipher_mode); + if (r < 0) + goto out; + } + + r = LUKS2_generate_hdr(cd, &cd->u.luks2.hdr, cd->volume_key, + cipher, cipher_mode, + integrity, uuid, + sector_size, + cd->data_offset * SECTOR_SIZE, + alignment_offset, + required_alignment, + cd->metadata_size, cd->keyslots_size); + if (r < 0) + goto out; + + r = device_size(crypt_data_device(cd), &dev_size); + if (r < 0) + goto out; + + if (dev_size < (crypt_get_data_offset(cd) * SECTOR_SIZE)) + log_std(cd, _("WARNING: Data offset is outside of currently available data device.\n")); + + if (cd->metadata_size && (cd->metadata_size != LUKS2_metadata_size(cd->u.luks2.hdr.jobj))) + log_std(cd, _("WARNING: LUKS2 metadata size changed to %" PRIu64 " bytes.\n"), + LUKS2_metadata_size(cd->u.luks2.hdr.jobj)); + + if (cd->keyslots_size && (cd->keyslots_size != LUKS2_keyslots_size(cd->u.luks2.hdr.jobj))) + log_std(cd, _("WARNING: LUKS2 keyslots area size changed to %" PRIu64 " bytes.\n"), + LUKS2_keyslots_size(cd->u.luks2.hdr.jobj)); + + if (!integrity && sector_size > SECTOR_SIZE) { + dev_size -= (crypt_get_data_offset(cd) * SECTOR_SIZE); + if (dev_size % sector_size) { + log_err(cd, _("Device size is not aligned to requested sector size.")); + r = -EINVAL; + goto out; + } + } + + if (params && (params->label || params->subsystem)) { + r = LUKS2_hdr_labels(cd, &cd->u.luks2.hdr, + params->label, params->subsystem, 0); + if (r < 0) + goto out; + } + + r = LUKS2_wipe_header_areas(cd, &cd->u.luks2.hdr); + if (r < 0) { + log_err(cd, _("Cannot wipe header on device %s."), + mdata_device_path(cd)); + if (dev_size < LUKS2_hdr_and_areas_size(cd->u.luks2.hdr.jobj)) + log_err(cd, _("Device %s is too small."), device_path(crypt_metadata_device(cd))); + goto out; + } + + /* Wipe integrity superblock and create integrity superblock */ + if (crypt_get_integrity_tag_size(cd)) { + r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_ZERO, + crypt_get_data_offset(cd) * SECTOR_SIZE, + 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL); + if (r < 0) { + if (r == -EBUSY) + log_err(cd, _("Cannot format device %s in use."), + data_device_path(cd)); + else if (r == -EACCES) { + log_err(cd, _("Cannot format device %s, permission denied."), + data_device_path(cd)); + r = -EINVAL; + } else + log_err(cd, _("Cannot wipe header on device %s."), + data_device_path(cd)); + + goto out; + } + + r = INTEGRITY_format(cd, params ? params->integrity_params : NULL, NULL, NULL); + if (r) + log_err(cd, _("Cannot format integrity for device %s."), + data_device_path(cd)); + } + + if (r < 0) + goto out; + + /* override sequence id check with format */ + r = LUKS2_hdr_write_force(cd, &cd->u.luks2.hdr); + if (r < 0) { + if (r == -EBUSY) + log_err(cd, _("Cannot format device %s in use."), + mdata_device_path(cd)); + else if (r == -EACCES) { + log_err(cd, _("Cannot format device %s, permission denied."), + mdata_device_path(cd)); + r = -EINVAL; + } else + log_err(cd, _("Cannot format device %s."), + mdata_device_path(cd)); + } + +out: + if (r) + LUKS2_hdr_free(cd, &cd->u.luks2.hdr); return r; } @@ -1111,17 +1941,22 @@ static int _crypt_format_loopaes(struct crypt_device *cd, struct crypt_params_loopaes *params) { if (!crypt_metadata_device(cd)) { - log_err(cd, _("Can't format LOOPAES without device.\n")); + log_err(cd, _("Can't format LOOPAES without device.")); return -EINVAL; } if (volume_key_size > 1024) { - log_err(cd, _("Invalid key size.\n")); + log_err(cd, _("Invalid key size.")); return -EINVAL; } if (uuid) { - log_err(cd, _("UUID is not supported for this crypt type.\n")); + log_err(cd, _("UUID is not supported for this crypt type.")); + return -EINVAL; + } + + if (cd->metadata_device) { + log_err(cd, _("Detached metadata device is not supported for this crypt type.")); return -EINVAL; } @@ -1146,38 +1981,51 @@ static int _crypt_format_verity(struct crypt_device *cd, struct crypt_params_verity *params) { int r = 0, hash_size; - uint64_t data_device_size; + uint64_t data_device_size, hash_blocks_size; + struct device *fec_device = NULL; + char *fec_device_path = NULL, *hash_name = NULL, *root_hash = NULL, *salt = NULL; if (!crypt_metadata_device(cd)) { - log_err(cd, _("Can't format VERITY without device.\n")); + log_err(cd, _("Can't format VERITY without device.")); return -EINVAL; } - if (!params || !params->data_device) + if (!params) + return -EINVAL; + + if (!params->data_device && !cd->metadata_device) return -EINVAL; if (params->hash_type > VERITY_MAX_HASH_TYPE) { - log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type); + log_err(cd, _("Unsupported VERITY hash type %d."), params->hash_type); return -EINVAL; } if (VERITY_BLOCK_SIZE_OK(params->data_block_size) || VERITY_BLOCK_SIZE_OK(params->hash_block_size)) { - log_err(cd, _("Unsupported VERITY block size.\n")); + log_err(cd, _("Unsupported VERITY block size.")); + return -EINVAL; + } + + if (MISALIGNED_512(params->hash_area_offset)) { + log_err(cd, _("Unsupported VERITY hash offset.")); return -EINVAL; } - if (params->hash_area_offset % 512) { - log_err(cd, _("Unsupported VERITY hash offset.\n")); + if (MISALIGNED_512(params->fec_area_offset)) { + log_err(cd, _("Unsupported VERITY FEC offset.")); return -EINVAL; } if (!(cd->type = strdup(CRYPT_VERITY))) return -ENOMEM; - r = crypt_set_data_device(cd, params->data_device); - if (r) - return r; + if (params->data_device) { + r = crypt_set_data_device(cd, params->data_device); + if (r) + return r; + } + if (!params->data_size) { r = device_size(cd->device, &data_device_size); if (r < 0) @@ -1187,60 +2035,208 @@ static int _crypt_format_verity(struct crypt_device *cd, } else cd->u.verity.hdr.data_size = params->data_size; + if (device_is_identical(crypt_metadata_device(cd), crypt_data_device(cd)) && + (cd->u.verity.hdr.data_size * params->data_block_size) > params->hash_area_offset) { + log_err(cd, _("Data area overlaps with hash area.")); + return -EINVAL; + } + hash_size = crypt_hash_size(params->hash_name); if (hash_size <= 0) { - log_err(cd, _("Hash algorithm %s not supported.\n"), + log_err(cd, _("Hash algorithm %s not supported."), params->hash_name); return -EINVAL; } cd->u.verity.root_hash_size = hash_size; - cd->u.verity.root_hash = malloc(cd->u.verity.root_hash_size); - if (!cd->u.verity.root_hash) - return -ENOMEM; + if (params->fec_device) { + fec_device_path = strdup(params->fec_device); + if (!fec_device_path) + return -ENOMEM; + r = device_alloc(cd, &fec_device, params->fec_device); + if (r < 0) { + r = -ENOMEM; + goto err; + } + + hash_blocks_size = VERITY_hash_blocks(cd, params) * params->hash_block_size; + if (device_is_identical(crypt_metadata_device(cd), fec_device) && + (params->hash_area_offset + hash_blocks_size) > params->fec_area_offset) { + log_err(cd, _("Hash area overlaps with FEC area.")); + r = -EINVAL; + goto err; + } + + if (device_is_identical(crypt_data_device(cd), fec_device) && + (cd->u.verity.hdr.data_size * params->data_block_size) > params->fec_area_offset) { + log_err(cd, _("Data area overlaps with FEC area.")); + r = -EINVAL; + goto err; + } + } + + root_hash = malloc(cd->u.verity.root_hash_size); + hash_name = strdup(params->hash_name); + salt = malloc(params->salt_size); + + if (!root_hash || !hash_name || !salt) { + r = -ENOMEM; + goto err; + } cd->u.verity.hdr.flags = params->flags; - if (!(cd->u.verity.hdr.hash_name = strdup(params->hash_name))) - return -ENOMEM; + cd->u.verity.root_hash = root_hash; + cd->u.verity.hdr.hash_name = hash_name; cd->u.verity.hdr.data_device = NULL; + cd->u.verity.fec_device = fec_device; + cd->u.verity.hdr.fec_device = fec_device_path; + cd->u.verity.hdr.fec_roots = params->fec_roots; cd->u.verity.hdr.data_block_size = params->data_block_size; cd->u.verity.hdr.hash_block_size = params->hash_block_size; cd->u.verity.hdr.hash_area_offset = params->hash_area_offset; + cd->u.verity.hdr.fec_area_offset = params->fec_area_offset; cd->u.verity.hdr.hash_type = params->hash_type; cd->u.verity.hdr.flags = params->flags; cd->u.verity.hdr.salt_size = params->salt_size; - if (!(cd->u.verity.hdr.salt = malloc(params->salt_size))) - return -ENOMEM; + cd->u.verity.hdr.salt = salt; if (params->salt) - memcpy(CONST_CAST(char*)cd->u.verity.hdr.salt, params->salt, - params->salt_size); + memcpy(salt, params->salt, params->salt_size); else - r = crypt_random_get(cd, CONST_CAST(char*)cd->u.verity.hdr.salt, - params->salt_size, CRYPT_RND_SALT); + r = crypt_random_get(cd, salt, params->salt_size, CRYPT_RND_SALT); if (r) - return r; + goto err; if (params->flags & CRYPT_VERITY_CREATE_HASH) { r = VERITY_create(cd, &cd->u.verity.hdr, cd->u.verity.root_hash, cd->u.verity.root_hash_size); + if (!r && params->fec_device) + r = VERITY_FEC_process(cd, &cd->u.verity.hdr, cd->u.verity.fec_device, 0, NULL); if (r) - return r; + goto err; } if (!(params->flags & CRYPT_VERITY_NO_HEADER)) { - if (uuid) - cd->u.verity.uuid = strdup(uuid); - else { + if (uuid) { + if (!(cd->u.verity.uuid = strdup(uuid))) + r = -ENOMEM; + } else r = VERITY_UUID_generate(cd, &cd->u.verity.uuid); - if (r) - return r; + + if (!r) + r = VERITY_write_sb(cd, cd->u.verity.hdr.hash_area_offset, + cd->u.verity.uuid, + &cd->u.verity.hdr); + } + +err: + if (r) { + device_free(cd, fec_device); + free(root_hash); + free(hash_name); + free(fec_device_path); + free(salt); + } + + return r; +} + +static int _crypt_format_integrity(struct crypt_device *cd, + const char *uuid, + struct crypt_params_integrity *params) +{ + int r; + uint32_t integrity_tag_size; + char *integrity = NULL, *journal_integrity = NULL, *journal_crypt = NULL; + struct volume_key *journal_crypt_key = NULL, *journal_mac_key = NULL; + + if (!params) + return -EINVAL; + + if (uuid) { + log_err(cd, _("UUID is not supported for this crypt type.")); + return -EINVAL; + } + + r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL); + if (r < 0) + return r; + + /* Wipe first 8 sectors - fs magic numbers etc. */ + r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0, + 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL); + if (r < 0) { + log_err(cd, _("Cannot wipe header on device %s."), + mdata_device_path(cd)); + return r; + } + + if (!(cd->type = strdup(CRYPT_INTEGRITY))) + return -ENOMEM; + + if (params->journal_crypt_key) { + journal_crypt_key = crypt_alloc_volume_key(params->journal_crypt_key_size, + params->journal_crypt_key); + if (!journal_crypt_key) + return -ENOMEM; + } + + if (params->journal_integrity_key) { + journal_mac_key = crypt_alloc_volume_key(params->journal_integrity_key_size, + params->journal_integrity_key); + if (!journal_mac_key) { + r = -ENOMEM; + goto err; } + } + + if (params->integrity && !(integrity = strdup(params->integrity))) { + r = -ENOMEM; + goto err; + } + if (params->journal_integrity && !(journal_integrity = strdup(params->journal_integrity))) { + r = -ENOMEM; + goto err; + } + if (params->journal_crypt && !(journal_crypt = strdup(params->journal_crypt))) { + r = -ENOMEM; + goto err; + } - r = VERITY_write_sb(cd, cd->u.verity.hdr.hash_area_offset, - cd->u.verity.uuid, - &cd->u.verity.hdr); + integrity_tag_size = INTEGRITY_hash_tag_size(integrity); + if (integrity_tag_size > 0 && params->tag_size && integrity_tag_size != params->tag_size) + log_std(cd, _("WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"), + params->tag_size, integrity, integrity_tag_size); + + if (params->tag_size) + integrity_tag_size = params->tag_size; + + cd->u.integrity.journal_crypt_key = journal_crypt_key; + cd->u.integrity.journal_mac_key = journal_mac_key; + cd->u.integrity.params.journal_size = params->journal_size; + cd->u.integrity.params.journal_watermark = params->journal_watermark; + cd->u.integrity.params.journal_commit_time = params->journal_commit_time; + cd->u.integrity.params.interleave_sectors = params->interleave_sectors; + cd->u.integrity.params.buffer_sectors = params->buffer_sectors; + cd->u.integrity.params.sector_size = params->sector_size; + cd->u.integrity.params.tag_size = integrity_tag_size; + cd->u.integrity.params.integrity = integrity; + cd->u.integrity.params.journal_integrity = journal_integrity; + cd->u.integrity.params.journal_crypt = journal_crypt; + + r = INTEGRITY_format(cd, params, cd->u.integrity.journal_crypt_key, cd->u.integrity.journal_mac_key); + if (r) + log_err(cd, _("Cannot format integrity for device %s."), + mdata_device_path(cd)); +err: + if (r) { + crypt_free_volume_key(journal_crypt_key); + crypt_free_volume_key(journal_mac_key); + free(integrity); + free(journal_integrity); + free(journal_crypt); } + return r; } @@ -1255,15 +2251,15 @@ int crypt_format(struct crypt_device *cd, { int r; - if (!type) + if (!cd || !type) return -EINVAL; if (cd->type) { - log_dbg("Context already formatted as %s.", cd->type); + log_dbg(cd, "Context already formatted as %s.", cd->type); return -EINVAL; } - log_dbg("Formatting device %s as type %s.", mdata_device_path(cd) ?: "(none)", type); + log_dbg(cd, "Formatting device %s as type %s.", mdata_device_path(cd) ?: "(none)", type); crypt_reset_null_type(cd); @@ -1274,15 +2270,20 @@ int crypt_format(struct crypt_device *cd, if (isPLAIN(type)) r = _crypt_format_plain(cd, cipher, cipher_mode, uuid, volume_key_size, params); - else if (isLUKS(type)) + else if (isLUKS1(type)) r = _crypt_format_luks1(cd, cipher, cipher_mode, uuid, volume_key, volume_key_size, params); + else if (isLUKS2(type)) + r = _crypt_format_luks2(cd, cipher, cipher_mode, + uuid, volume_key, volume_key_size, params); else if (isLOOPAES(type)) r = _crypt_format_loopaes(cd, cipher, uuid, volume_key_size, params); else if (isVERITY(type)) r = _crypt_format_verity(cd, uuid, params); + else if (isINTEGRITY(type)) + r = _crypt_format_integrity(cd, uuid, params); else { - log_err(cd, _("Unknown crypt device type %s requested.\n"), type); + log_err(cd, _("Unknown crypt device type %s requested."), type); r = -EINVAL; } @@ -1295,52 +2296,16 @@ int crypt_format(struct crypt_device *cd, return r; } -int crypt_load(struct crypt_device *cd, - const char *requested_type, - void *params) -{ - int r; - - log_dbg("Trying to load %s crypt type from device %s.", - requested_type ?: "any", mdata_device_path(cd) ?: "(none)"); - - if (!crypt_metadata_device(cd)) - return -EINVAL; - - crypt_reset_null_type(cd); - - if (!requested_type || isLUKS(requested_type)) { - if (cd->type && !isLUKS(cd->type)) { - log_dbg("Context is already initialised to type %s", cd->type); - return -EINVAL; - } - - r = _crypt_load_luks1(cd, 1, 0); - } else if (isVERITY(requested_type)) { - if (cd->type && !isVERITY(cd->type)) { - log_dbg("Context is already initialised to type %s", cd->type); - return -EINVAL; - } - r = _crypt_load_verity(cd, params); - } else if (isTCRYPT(requested_type)) { - if (cd->type && !isTCRYPT(cd->type)) { - log_dbg("Context is already initialised to type %s", cd->type); - return -EINVAL; - } - r = _crypt_load_tcrypt(cd, params); - } else - return -EINVAL; - - return r; -} - int crypt_repair(struct crypt_device *cd, const char *requested_type, void *params __attribute__((unused))) { int r; - log_dbg("Trying to repair %s crypt type from device %s.", + if (!cd) + return -EINVAL; + + log_dbg(cd, "Trying to repair %s crypt type from device %s.", requested_type ?: "any", mdata_device_path(cd) ?: "(none)"); if (!crypt_metadata_device(cd)) @@ -1349,9 +2314,8 @@ int crypt_repair(struct crypt_device *cd, if (requested_type && !isLUKS(requested_type)) return -EINVAL; - /* Load with repair */ - r = _crypt_load_luks1(cd, 1, 1); + r = _crypt_load_luks(cd, requested_type, 1, 1); if (r < 0) return r; @@ -1363,1367 +2327,3723 @@ int crypt_repair(struct crypt_device *cd, return r; } -int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size) +/* compare volume keys */ +static int _compare_volume_keys(struct volume_key *svk, unsigned skeyring_only, struct volume_key *tvk, unsigned tkeyring_only) { - struct crypt_dm_active_device dmd; - int r; + if (!svk && !tvk) + return 0; + else if (!svk || !tvk) + return 1; - /* Device context type must be initialised */ - if (!cd->type) - return -EINVAL; + if (svk->keylength != tvk->keylength) + return 1; - log_dbg("Resizing device %s to %" PRIu64 " sectors.", name, new_size); + if (!skeyring_only && !tkeyring_only) + return memcmp(svk->key, tvk->key, svk->keylength); - r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER | - DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE | - DM_ACTIVE_CRYPT_KEY, &dmd); - if (r < 0) { - log_err(NULL, _("Device %s is not active.\n"), name); + if (svk->key_description && tvk->key_description) + return strcmp(svk->key_description, tvk->key_description); + + return 0; +} + +static int _compare_device_types(struct crypt_device *cd, + const struct crypt_dm_active_device *src, + const struct crypt_dm_active_device *tgt) +{ + if (!tgt->uuid) { + log_dbg(cd, "Missing device uuid in target device."); return -EINVAL; } - if (!dmd.uuid || dmd.target != DM_CRYPT) { - r = -EINVAL; - goto out; + if (isLUKS2(cd->type) && !strncmp("INTEGRITY-", tgt->uuid, strlen("INTEGRITY-"))) { + if (crypt_uuid_cmp(tgt->uuid, src->uuid)) { + log_dbg(cd, "LUKS UUID mismatch."); + return -EINVAL; + } + } else if (isLUKS(cd->type)) { + if (!src->uuid || strncmp(cd->type, tgt->uuid, strlen(cd->type)) || + crypt_uuid_cmp(tgt->uuid, src->uuid)) { + log_dbg(cd, "LUKS UUID mismatch."); + return -EINVAL; + } + } else if (isPLAIN(cd->type) || isLOOPAES(cd->type)) { + if (strncmp(cd->type, tgt->uuid, strlen(cd->type))) { + log_dbg(cd, "Unexpected uuid prefix %s in target device.", tgt->uuid); + return -EINVAL; + } + } else { + log_dbg(cd, "Unsupported device type %s for reload.", cd->type ?: ""); + return -ENOTSUP; } - r = device_block_adjust(cd, dmd.data_device, DEV_OK, - dmd.u.crypt.offset, &new_size, &dmd.flags); - if (r) - goto out; + return 0; +} - if (new_size == dmd.size) { - log_dbg("Device has already requested size %" PRIu64 - " sectors.", dmd.size); - r = 0; - } else { - dmd.size = new_size; - if (isTCRYPT(cd->type)) - r = -ENOTSUP; - else - r = dm_create_device(cd, name, cd->type, &dmd, 1); +static int _compare_crypt_devices(struct crypt_device *cd, + const struct dm_target *src, + const struct dm_target *tgt) +{ + /* for crypt devices keys are mandatory */ + if (!src->u.crypt.vk || !tgt->u.crypt.vk) + return -EINVAL; + + if (_compare_volume_keys(src->u.crypt.vk, 0, tgt->u.crypt.vk, tgt->u.crypt.vk->key_description != NULL)) { + log_dbg(cd, "Keys in context and target device do not match."); + return -EINVAL; } -out: - if (dmd.target == DM_CRYPT) { - crypt_free_volume_key(dmd.u.crypt.vk); - free(CONST_CAST(void*)dmd.u.crypt.cipher); + + /* CIPHER checks */ + if (!src->u.crypt.cipher || !tgt->u.crypt.cipher) + return -EINVAL; + if (strcmp(src->u.crypt.cipher, tgt->u.crypt.cipher)) { + log_dbg(cd, "Cipher specs do not match."); + return -EINVAL; + } + if (crypt_strcmp(src->u.crypt.integrity, tgt->u.crypt.integrity)) { + log_dbg(cd, "Integrity parameters do not match."); + return -EINVAL; } - free(CONST_CAST(void*)dmd.data_device); - free(CONST_CAST(void*)dmd.uuid); - return r; + if (src->u.crypt.offset != tgt->u.crypt.offset || + src->u.crypt.sector_size != tgt->u.crypt.sector_size || + src->u.crypt.iv_offset != tgt->u.crypt.iv_offset || + src->u.crypt.tag_size != tgt->u.crypt.tag_size) { + log_dbg(cd, "Integer parameters do not match."); + return -EINVAL; + } + + if (!device_is_identical(src->data_device, tgt->data_device)) { + log_dbg(cd, "Data devices do not match."); + return -EINVAL; + } + + return 0; } -int crypt_set_uuid(struct crypt_device *cd, const char *uuid) +static int _compare_integrity_devices(struct crypt_device *cd, + const struct dm_target *src, + const struct dm_target *tgt) { - if (!isLUKS(cd->type)) { - log_err(cd, _("This operation is not supported for this device type.\n")); - return -EINVAL; + /* + * some parameters may be implicit (and set in dm-integrity ctor) + * + * journal_size + * journal_watermark + * journal_commit_time + * buffer_sectors + * interleave_sectors + */ + + /* check remaining integer values that makes sense */ + if (src->u.integrity.tag_size != tgt->u.integrity.tag_size || + src->u.integrity.offset != tgt->u.integrity.offset || + src->u.integrity.sector_size != tgt->u.integrity.sector_size) { + log_dbg(cd, "Integer parameters do not match."); + return -EINVAL; } - if (uuid && !strncmp(uuid, cd->u.luks1.hdr.uuid, sizeof(cd->u.luks1.hdr.uuid))) { - log_dbg("UUID is the same as requested (%s) for device %s.", - uuid, mdata_device_path(cd)); - return 0; + if (crypt_strcmp(src->u.integrity.integrity, tgt->u.integrity.integrity) || + crypt_strcmp(src->u.integrity.journal_integrity, tgt->u.integrity.journal_integrity) || + crypt_strcmp(src->u.integrity.journal_crypt, tgt->u.integrity.journal_crypt)) { + log_dbg(cd, "Journal parameters do not match."); + return -EINVAL; } - if (uuid) - log_dbg("Requested new UUID change to %s for %s.", uuid, mdata_device_path(cd)); - else - log_dbg("Requested new UUID refresh for %s.", mdata_device_path(cd)); + /* unfortunately dm-integrity doesn't support keyring */ + if (_compare_volume_keys(src->u.integrity.vk, 0, tgt->u.integrity.vk, 0) || + _compare_volume_keys(src->u.integrity.journal_integrity_key, 0, tgt->u.integrity.journal_integrity_key, 0) || + _compare_volume_keys(src->u.integrity.journal_crypt_key, 0, tgt->u.integrity.journal_crypt_key, 0)) { + log_dbg(cd, "Journal keys do not match."); + return -EINVAL; + } - if (!crypt_confirm(cd, _("Do you really want to change UUID of device?"))) - return -EPERM; + /* unsupported underneath dm-crypt with auth. encryption */ + if (src->u.integrity.meta_device || tgt->u.integrity.meta_device) + return -ENOTSUP; + + if (src->size != tgt->size) { + log_dbg(cd, "Device size parameters do not match."); + return -EINVAL; + } - return LUKS_hdr_uuid_set(&cd->u.luks1.hdr, uuid, cd); + if (!device_is_identical(src->data_device, tgt->data_device)) { + log_dbg(cd, "Data devices do not match."); + return -EINVAL; + } + + return 0; } -int crypt_header_backup(struct crypt_device *cd, - const char *requested_type, - const char *backup_file) +int crypt_compare_dm_devices(struct crypt_device *cd, + const struct crypt_dm_active_device *src, + const struct crypt_dm_active_device *tgt) { int r; + const struct dm_target *s, *t; - if ((requested_type && !isLUKS(requested_type)) || !backup_file) - return -EINVAL; - - if (cd->type && !isLUKS(cd->type)) + if (!src || !tgt) return -EINVAL; - r = init_crypto(cd); - if (r < 0) + r = _compare_device_types(cd, src, tgt); + if (r) return r; - log_dbg("Requested header backup of device %s (%s) to " - "file %s.", mdata_device_path(cd), requested_type, backup_file); + s = &src->segment; + t = &tgt->segment; + + while (s || t) { + if (!s || !t) { + log_dbg(cd, "segments count mismatch."); + return -EINVAL; + } + if (s->type != t->type) { + log_dbg(cd, "segment type mismatch."); + r = -EINVAL; + break; + } + + switch (s->type) { + case DM_CRYPT: + r = _compare_crypt_devices(cd, s, t); + break; + case DM_INTEGRITY: + r = _compare_integrity_devices(cd, s, t); + break; + case DM_LINEAR: + r = (s->u.linear.offset == t->u.linear.offset) ? 0 : -EINVAL; + break; + default: + r = -ENOTSUP; + } + + if (r) + break; + + s = s->next; + t = t->next; + } - r = LUKS_hdr_backup(backup_file, cd); return r; } -int crypt_header_restore(struct crypt_device *cd, - const char *requested_type, - const char *backup_file) +static int _reload_device(struct crypt_device *cd, const char *name, + struct crypt_dm_active_device *sdmd) { - struct luks_phdr hdr; int r; + struct crypt_dm_active_device tdmd; + struct dm_target *src, *tgt = &tdmd.segment; - if (requested_type && !isLUKS(requested_type)) + if (!cd || !cd->type || !name || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH)) return -EINVAL; - if (cd->type && !isLUKS(cd->type)) + r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER | + DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE | + DM_ACTIVE_CRYPT_KEY, &tdmd); + if (r < 0) { + log_err(cd, _("Device %s is not active."), name); return -EINVAL; + } - r = init_crypto(cd); - if (r < 0) - return r; + if (!single_segment(&tdmd) || tgt->type != DM_CRYPT || tgt->u.crypt.tag_size) { + r = -ENOTSUP; + log_err(cd, _("Unsupported parameters on device %s."), name); + goto out; + } - log_dbg("Requested header restore to device %s (%s) from " - "file %s.", mdata_device_path(cd), requested_type, backup_file); + r = crypt_compare_dm_devices(cd, sdmd, &tdmd); + if (r) { + log_err(cd, _("Mismatching parameters on device %s."), name); + goto out; + } - r = LUKS_hdr_restore(backup_file, isLUKS(cd->type) ? &cd->u.luks1.hdr : &hdr, cd); + src = &sdmd->segment; - crypt_memzero(&hdr, sizeof(hdr)); - return r; -} + /* Changing read only flag for active device makes no sense */ + if (tdmd.flags & CRYPT_ACTIVATE_READONLY) + sdmd->flags |= CRYPT_ACTIVATE_READONLY; + else + sdmd->flags &= ~CRYPT_ACTIVATE_READONLY; -void crypt_free(struct crypt_device *cd) -{ - if (cd) { - log_dbg("Releasing crypt device %s context.", mdata_device_path(cd)); + if (sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) { + r = crypt_volume_key_set_description(tgt->u.crypt.vk, src->u.crypt.vk->key_description); + if (r) + goto out; + } else { + crypt_free_volume_key(tgt->u.crypt.vk); + tgt->u.crypt.vk = crypt_alloc_volume_key(src->u.crypt.vk->keylength, src->u.crypt.vk->key); + if (!tgt->u.crypt.vk) { + r = -ENOMEM; + goto out; + } + } - dm_backend_exit(); - crypt_free_volume_key(cd->volume_key); + r = device_block_adjust(cd, src->data_device, DEV_OK, + src->u.crypt.offset, &sdmd->size, NULL); + if (r) + goto out; - device_free(cd->device); - device_free(cd->metadata_device); - - if (isPLAIN(cd->type)) { - free(CONST_CAST(void*)cd->u.plain.hdr.hash); - free(cd->u.plain.cipher); - free(cd->u.plain.cipher_mode); - } else if (isLOOPAES(cd->type)) { - free(CONST_CAST(void*)cd->u.loopaes.hdr.hash); - free(cd->u.loopaes.cipher); - } else if (isVERITY(cd->type)) { - free(CONST_CAST(void*)cd->u.verity.hdr.hash_name); - free(CONST_CAST(void*)cd->u.verity.hdr.salt); - free(cd->u.verity.root_hash); - free(cd->u.verity.uuid); - } else if (!cd->type) { - free(cd->u.none.active_name); - } + tdmd.flags = sdmd->flags; + tgt->size = tdmd.size = sdmd->size; - free(cd->type); - /* Some structures can contain keys (TCRYPT), wipe it */ - crypt_memzero(cd, sizeof(*cd)); - free(cd); - } + r = dm_reload_device(cd, name, &tdmd, 0, 1); +out: + dm_targets_free(cd, &tdmd); + free(CONST_CAST(void*)tdmd.uuid); + + return r; } -int crypt_suspend(struct crypt_device *cd, - const char *name) +static int _reload_device_with_integrity(struct crypt_device *cd, + const char *name, + const char *iname, + const char *ipath, + struct crypt_dm_active_device *sdmd, + struct crypt_dm_active_device *sdmdi) { - crypt_status_info ci; int r; + struct crypt_dm_active_device tdmd, tdmdi = {}; + struct dm_target *src, *srci, *tgt = &tdmd.segment, *tgti = &tdmdi.segment; + struct device *data_device = NULL; - log_dbg("Suspending volume %s.", name); + if (!cd || !cd->type || !name || !iname || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH)) + return -EINVAL; - if (cd->type) { - r = onlyLUKS(cd); - } else { - r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1); - if (r < 0) - log_err(cd, _("This operation is supported only for LUKS device.\n")); + r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER | + DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE | + DM_ACTIVE_CRYPT_KEY, &tdmd); + if (r < 0) { + log_err(cd, _("Device %s is not active."), name); + return -EINVAL; } - if (r < 0) - return r; + if (!single_segment(&tdmd) || tgt->type != DM_CRYPT || !tgt->u.crypt.tag_size) { + r = -ENOTSUP; + log_err(cd, _("Unsupported parameters on device %s."), name); + goto out; + } - ci = crypt_status(NULL, name); - if (ci < CRYPT_ACTIVE) { - log_err(cd, _("Volume %s is not active.\n"), name); - return -EINVAL; + r = dm_query_device(cd, iname, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &tdmdi); + if (r < 0) { + log_err(cd, _("Device %s is not active."), iname); + r = -EINVAL; + goto out; } - dm_backend_init(); + if (!single_segment(&tdmdi) || tgti->type != DM_INTEGRITY) { + r = -ENOTSUP; + log_err(cd, _("Unsupported parameters on device %s."), iname); + goto out; + } - r = dm_status_suspended(cd, name); + r = crypt_compare_dm_devices(cd, sdmdi, &tdmdi); + if (r) { + log_err(cd, _("Mismatching parameters on device %s."), iname); + goto out; + } + + src = &sdmd->segment; + srci = &sdmdi->segment; + + r = device_alloc(cd, &data_device, ipath); if (r < 0) goto out; + r = device_block_adjust(cd, srci->data_device, DEV_OK, + srci->u.integrity.offset, &sdmdi->size, NULL); + if (r) + goto out; + + src->data_device = data_device; + + r = crypt_compare_dm_devices(cd, sdmd, &tdmd); if (r) { - log_err(cd, _("Volume %s is already suspended.\n"), name); - r = -EINVAL; + log_err(cd, _("Crypt devices mismatch.")); goto out; } - r = dm_suspend_and_wipe_key(cd, name); - if (r == -ENOTSUP) - log_err(cd, _("Suspend is not supported for device %s.\n"), name); - else if (r) - log_err(cd, _("Error during suspending device %s.\n"), name); -out: - dm_backend_exit(); - return r; -} + /* Changing read only flag for active device makes no sense */ + if (tdmd.flags & CRYPT_ACTIVATE_READONLY) + sdmd->flags |= CRYPT_ACTIVATE_READONLY; + else + sdmd->flags &= ~CRYPT_ACTIVATE_READONLY; -int crypt_resume_by_passphrase(struct crypt_device *cd, - const char *name, - int keyslot, - const char *passphrase, - size_t passphrase_size) -{ - struct volume_key *vk = NULL; - int r; + if (tdmdi.flags & CRYPT_ACTIVATE_READONLY) + sdmdi->flags |= CRYPT_ACTIVATE_READONLY; + else + sdmdi->flags &= ~CRYPT_ACTIVATE_READONLY; - log_dbg("Resuming volume %s.", name); + if (sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) { + r = crypt_volume_key_set_description(tgt->u.crypt.vk, src->u.crypt.vk->key_description); + if (r) + goto out; + } else { + crypt_free_volume_key(tgt->u.crypt.vk); + tgt->u.crypt.vk = crypt_alloc_volume_key(src->u.crypt.vk->keylength, src->u.crypt.vk->key); + if (!tgt->u.crypt.vk) { + r = -ENOMEM; + goto out; + } + } - r = onlyLUKS(cd); - if (r < 0) - return r; + r = device_block_adjust(cd, src->data_device, DEV_OK, + src->u.crypt.offset, &sdmd->size, NULL); + if (r) + goto out; - r = dm_status_suspended(cd, name); - if (r < 0) - return r; + tdmd.flags = sdmd->flags; + tdmd.size = sdmd->size; - if (!r) { - log_err(cd, _("Volume %s is not suspended.\n"), name); - return -EINVAL; + if ((r = dm_reload_device(cd, iname, sdmdi, 0, 0))) { + log_err(cd, _("Failed to reload device %s."), iname); + goto out; } - if (passphrase) { - r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size, - &cd->u.luks1.hdr, &vk, cd); - } else - r = volume_key_by_terminal_passphrase(cd, keyslot, &vk); + if ((r = dm_reload_device(cd, name, &tdmd, 0, 0))) { + log_err(cd, _("Failed to reload device %s."), name); + goto err_clear; + } - if (r >= 0) { - keyslot = r; - r = dm_resume_and_reinstate_key(cd, name, vk->keylength, vk->key); - if (r == -ENOTSUP) - log_err(cd, _("Resume is not supported for device %s.\n"), name); - else if (r) - log_err(cd, _("Error during resuming device %s.\n"), name); - } else - r = keyslot; + if ((r = dm_suspend_device(cd, name, 0))) { + log_err(cd, _("Failed to suspend device %s."), name); + goto err_clear; + } - crypt_free_volume_key(vk); - return r < 0 ? r : keyslot; + if ((r = dm_suspend_device(cd, iname, 0))) { + log_err(cd, _("Failed to suspend device %s."), iname); + goto err_clear; + } + + if ((r = dm_resume_device(cd, iname, act2dmflags(sdmdi->flags)))) { + log_err(cd, _("Failed to resume device %s."), iname); + goto err_clear; + } + + r = dm_resume_device(cd, name, act2dmflags(tdmd.flags)); + if (!r) + goto out; + + /* + * This is worst case scenario. We have active underlying dm-integrity device with + * new table but dm-crypt resume failed for some reason. Tear everything down and + * burn it for good. + */ + + log_err(cd, _("Fatal error while reloading device %s (on top of device %s)."), name, iname); + + if (dm_error_device(cd, name)) + log_err(cd, _("Failed to switch device %s to dm-error."), name); + if (dm_error_device(cd, iname)) + log_err(cd, _("Failed to switch device %s to dm-error."), iname); + goto out; + +err_clear: + dm_clear_device(cd, name); + dm_clear_device(cd, iname); + + if (dm_status_suspended(cd, name) > 0) + dm_resume_device(cd, name, 0); + if (dm_status_suspended(cd, iname) > 0) + dm_resume_device(cd, iname, 0); +out: + dm_targets_free(cd, &tdmd); + dm_targets_free(cd, &tdmdi); + free(CONST_CAST(void*)tdmdi.uuid); + free(CONST_CAST(void*)tdmd.uuid); + device_free(cd, data_device); + + return r; } -int crypt_resume_by_keyfile_offset(struct crypt_device *cd, - const char *name, - int keyslot, - const char *keyfile, - size_t keyfile_size, - size_t keyfile_offset) +int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size) { - struct volume_key *vk = NULL; - char *passphrase_read = NULL; - size_t passphrase_size_read; + struct crypt_dm_active_device dmdq, dmd = {}; + struct dm_target *tgt = &dmdq.segment; int r; - log_dbg("Resuming volume %s.", name); + /* + * FIXME: Also with LUKS2 we must not allow resize when there's + * explicit size stored in metadata (length != "dynamic") + */ - r = onlyLUKS(cd); - if (r < 0) - return r; + /* Device context type must be initialized */ + if (!cd || !cd->type || !name) + return -EINVAL; - r = dm_status_suspended(cd, name); - if (r < 0) - return r; + log_dbg(cd, "Resizing device %s to %" PRIu64 " sectors.", name, new_size); - if (!r) { - log_err(cd, _("Volume %s is not suspended.\n"), name); + r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmdq); + if (r < 0) { + log_err(cd, _("Device %s is not active."), name); return -EINVAL; } - - if (!keyfile) - return -EINVAL; - - r = key_from_file(cd, _("Enter passphrase: "), &passphrase_read, - &passphrase_size_read, keyfile, keyfile_offset, - keyfile_size); - if (r < 0) + if (!single_segment(&dmdq) || tgt->type != DM_CRYPT) { + log_dbg(cd, "Unsupported device table detected in %s.", name); + r = -EINVAL; goto out; + } - r = LUKS_open_key_with_hdr(keyslot, passphrase_read, - passphrase_size_read, &cd->u.luks1.hdr, &vk, cd); - if (r < 0) + if ((dmdq.flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_key_in_keyring(cd)) { + r = -EPERM; goto out; + } - keyslot = r; - r = dm_resume_and_reinstate_key(cd, name, vk->keylength, vk->key); - if (r) - log_err(cd, _("Error during resuming device %s.\n"), name); -out: - crypt_safe_free(passphrase_read); - crypt_free_volume_key(vk); - return r < 0 ? r : keyslot; -} - -int crypt_resume_by_keyfile(struct crypt_device *cd, - const char *name, - int keyslot, - const char *keyfile, - size_t keyfile_size) -{ - return crypt_resume_by_keyfile_offset(cd, name, keyslot, - keyfile, keyfile_size, 0); -} - -// slot manipulation -int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, - int keyslot, // -1 any - const char *passphrase, // NULL -> terminal - size_t passphrase_size, - const char *new_passphrase, // NULL -> terminal - size_t new_passphrase_size) -{ - struct volume_key *vk = NULL; - char *password = NULL, *new_password = NULL; - size_t passwordLen, new_passwordLen; - int r; + if (crypt_key_in_keyring(cd)) { + if (!isLUKS2(cd->type)) { + r = -EINVAL; + goto out; + } + r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr, + tgt->u.crypt.vk, CRYPT_DEFAULT_SEGMENT); + if (r) + goto out; - log_dbg("Adding new keyslot, existing passphrase %sprovided," - "new passphrase %sprovided.", - passphrase ? "" : "not ", new_passphrase ? "" : "not "); + dmdq.flags |= CRYPT_ACTIVATE_KEYRING_KEY; + } - r = onlyLUKS(cd); - if (r < 0) - return r; + if (crypt_loop_device(crypt_get_device_name(cd))) { + log_dbg(cd, "Trying to resize underlying loop device %s.", + crypt_get_device_name(cd)); + /* Here we always use default size not new_size */ + if (crypt_loop_resize(crypt_get_device_name(cd))) + log_err(cd, _("Cannot resize loop device.")); + } - r = keyslot_verify_or_find_empty(cd, &keyslot); + r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK, + crypt_get_data_offset(cd), &new_size, &dmdq.flags); if (r) - return r; - - if (!LUKS_keyslot_active_count(&cd->u.luks1.hdr)) { - /* No slots used, try to use pre-generated key in header */ - if (cd->volume_key) { - vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); - r = vk ? 0 : -ENOMEM; - } else { - log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n")); - return -EINVAL; - } - } else if (passphrase) { - /* Passphrase provided, use it to unlock existing keyslot */ - r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, passphrase, - passphrase_size, &cd->u.luks1.hdr, &vk, cd); - } else { - /* Passphrase not provided, ask first and use it to unlock existing keyslot */ - r = key_from_terminal(cd, _("Enter any passphrase: "), - &password, &passwordLen, 0); - if (r < 0) - goto out; + goto out; - r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, password, - passwordLen, &cd->u.luks1.hdr, &vk, cd); - crypt_safe_free(password); + if (MISALIGNED(new_size, tgt->u.crypt.sector_size >> SECTOR_SHIFT)) { + log_err(cd, _("Device size is not aligned to requested sector size.")); + r = -EINVAL; + goto out; } - if(r < 0) + if (MISALIGNED(new_size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) { + log_err(cd, _("Device size is not aligned to device logical block size.")); + r = -EINVAL; goto out; - - if (new_passphrase) { - new_password = CONST_CAST(char*)new_passphrase; - new_passwordLen = new_passphrase_size; - } else { - r = key_from_terminal(cd, _("Enter new passphrase for key slot: "), - &new_password, &new_passwordLen, 1); - if(r < 0) - goto out; } - r = LUKS_set_key(keyslot, new_password, new_passwordLen, - &cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd); - if(r < 0) + dmd.uuid = crypt_get_uuid(cd); + dmd.size = new_size; + dmd.flags = dmdq.flags | CRYPT_ACTIVATE_REFRESH; + r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd), + tgt->u.crypt.vk, crypt_get_cipher_spec(cd), + crypt_get_iv_offset(cd), crypt_get_data_offset(cd), + crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd), + crypt_get_sector_size(cd)); + if (r < 0) goto out; - r = 0; + if (new_size == dmdq.size) { + log_dbg(cd, "Device has already requested size %" PRIu64 + " sectors.", dmdq.size); + r = 0; + } else { + if (isTCRYPT(cd->type)) + r = -ENOTSUP; + else if (isLUKS2(cd->type)) + r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0); + if (!r) + r = _reload_device(cd, name, &dmd); + } out: - if (!new_passphrase) - crypt_safe_free(new_password); - crypt_free_volume_key(vk); - return r < 0 ? r : keyslot; + dm_targets_free(cd, &dmd); + dm_targets_free(cd, &dmdq); + + return r; } -int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, - int keyslot_old, - int keyslot_new, - const char *passphrase, - size_t passphrase_size, - const char *new_passphrase, - size_t new_passphrase_size) +int crypt_set_uuid(struct crypt_device *cd, const char *uuid) { - struct volume_key *vk = NULL; + const char *active_uuid; int r; - log_dbg("Changing passphrase from old keyslot %d to new %d.", - keyslot_old, keyslot_new); + log_dbg(cd, "%s device uuid.", uuid ? "Setting new" : "Refreshing"); - r = onlyLUKS(cd); - if (r < 0) + if ((r = onlyLUKS(cd))) return r; - r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size, - &cd->u.luks1.hdr, &vk, cd); - if (r < 0) - goto out; - - if (keyslot_old != CRYPT_ANY_SLOT && keyslot_old != r) { - log_dbg("Keyslot mismatch."); - goto out; - } - keyslot_old = r; + active_uuid = crypt_get_uuid(cd); - if (keyslot_new == CRYPT_ANY_SLOT) { - keyslot_new = LUKS_keyslot_find_empty(&cd->u.luks1.hdr); - if (keyslot_new < 0) - keyslot_new = keyslot_old; + if (uuid && active_uuid && !strncmp(uuid, active_uuid, UUID_STRING_L)) { + log_dbg(cd, "UUID is the same as requested (%s) for device %s.", + uuid, mdata_device_path(cd)); + return 0; } - if (keyslot_old == keyslot_new) { - log_dbg("Key slot %d is going to be overwritten.", keyslot_old); - (void)crypt_keyslot_destroy(cd, keyslot_old); - } + if (uuid) + log_dbg(cd, "Requested new UUID change to %s for %s.", uuid, mdata_device_path(cd)); + else + log_dbg(cd, "Requested new UUID refresh for %s.", mdata_device_path(cd)); - r = LUKS_set_key(keyslot_new, new_passphrase, new_passphrase_size, - &cd->u.luks1.hdr, vk, cd->iteration_time, - &cd->u.luks1.PBKDF2_per_sec, cd); + if (!crypt_confirm(cd, _("Do you really want to change UUID of device?"))) + return -EPERM; - if (keyslot_old == keyslot_new) { - if (r >= 0) - log_verbose(cd, _("Key slot %d changed.\n"), keyslot_new); - } else { - if (r >= 0) { - log_verbose(cd, _("Replaced with key slot %d.\n"), keyslot_new); - r = crypt_keyslot_destroy(cd, keyslot_old); - } - } - if (r < 0) - log_err(cd, _("Failed to swap new key slot.\n")); -out: - crypt_free_volume_key(vk); - return r < 0 ? r : keyslot_new; + if (isLUKS1(cd->type)) + return LUKS_hdr_uuid_set(&cd->u.luks1.hdr, uuid, cd); + else + return LUKS2_hdr_uuid(cd, &cd->u.luks2.hdr, uuid); } -int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, - int keyslot, - const char *keyfile, - size_t keyfile_size, - size_t keyfile_offset, - const char *new_keyfile, - size_t new_keyfile_size, - size_t new_keyfile_offset) +int crypt_set_label(struct crypt_device *cd, const char *label, const char *subsystem) { - struct volume_key *vk = NULL; - char *password = NULL; size_t passwordLen; - char *new_password = NULL; size_t new_passwordLen; int r; - log_dbg("Adding new keyslot, existing keyfile %s, new keyfile %s.", - keyfile ?: "[none]", new_keyfile ?: "[none]"); + log_dbg(cd, "Setting new labels."); - r = onlyLUKS(cd); - if (r < 0) + if ((r = onlyLUKS2(cd))) return r; - r = keyslot_verify_or_find_empty(cd, &keyslot); - if (r) - return r; + return LUKS2_hdr_labels(cd, &cd->u.luks2.hdr, label, subsystem, 1); +} - if (!LUKS_keyslot_active_count(&cd->u.luks1.hdr)) { - /* No slots used, try to use pre-generated key in header */ - if (cd->volume_key) { - vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); - r = vk ? 0 : -ENOMEM; - } else { - log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n")); - return -EINVAL; - } - } else { - /* Read password from file of (if NULL) from terminal */ - if (keyfile) - r = key_from_file(cd, _("Enter any passphrase: "), - &password, &passwordLen, - keyfile, keyfile_offset, keyfile_size); - else - r = key_from_terminal(cd, _("Enter any passphrase: "), - &password, &passwordLen, 0); - if (r < 0) - goto out; +int crypt_header_backup(struct crypt_device *cd, + const char *requested_type, + const char *backup_file) +{ + int r; - r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, password, passwordLen, - &cd->u.luks1.hdr, &vk, cd); - } + if (requested_type && !isLUKS(requested_type)) + return -EINVAL; - if(r < 0) - goto out; + if (!backup_file) + return -EINVAL; - if (new_keyfile) - r = key_from_file(cd, _("Enter new passphrase for key slot: "), - &new_password, &new_passwordLen, new_keyfile, - new_keyfile_offset, new_keyfile_size); - else - r = key_from_terminal(cd, _("Enter new passphrase for key slot: "), - &new_password, &new_passwordLen, 1); + /* Load with repair */ + r = _crypt_load_luks(cd, requested_type, 1, 0); if (r < 0) - goto out; + return r; - r = LUKS_set_key(keyslot, new_password, new_passwordLen, - &cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd); -out: - crypt_safe_free(password); - crypt_safe_free(new_password); - crypt_free_volume_key(vk); - return r < 0 ? r : keyslot; -} + log_dbg(cd, "Requested header backup of device %s (%s) to " + "file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file); -int crypt_keyslot_add_by_keyfile(struct crypt_device *cd, - int keyslot, - const char *keyfile, - size_t keyfile_size, - const char *new_keyfile, - size_t new_keyfile_size) -{ - return crypt_keyslot_add_by_keyfile_offset(cd, keyslot, - keyfile, keyfile_size, 0, - new_keyfile, new_keyfile_size, 0); + if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type))) + r = LUKS_hdr_backup(backup_file, cd); + else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type))) + r = LUKS2_hdr_backup(cd, &cd->u.luks2.hdr, backup_file); + else + r = -EINVAL; + + return r; } -int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, - int keyslot, - const char *volume_key, - size_t volume_key_size, - const char *passphrase, - size_t passphrase_size) +int crypt_header_restore(struct crypt_device *cd, + const char *requested_type, + const char *backup_file) { - struct volume_key *vk = NULL; - int r; - char *new_password = NULL; size_t new_passwordLen; + struct luks_phdr hdr1; + struct luks2_hdr hdr2; + int r, version; + + if (requested_type && !isLUKS(requested_type)) + return -EINVAL; - log_dbg("Adding new keyslot %d using volume key.", keyslot); + if (!cd || (cd->type && !isLUKS(cd->type)) || !backup_file) + return -EINVAL; - r = onlyLUKS(cd); + r = init_crypto(cd); if (r < 0) return r; - if (volume_key) - vk = crypt_alloc_volume_key(volume_key_size, volume_key); - else if (cd->volume_key) - vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); + log_dbg(cd, "Requested header restore to device %s (%s) from " + "file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file); - if (!vk) - return -ENOMEM; - - r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); - if (r < 0) { - log_err(cd, _("Volume key does not match the volume.\n")); - goto out; + version = LUKS2_hdr_version_unlocked(cd, backup_file); + if (!version || + (requested_type && version == 1 && !isLUKS1(requested_type)) || + (requested_type && version == 2 && !isLUKS2(requested_type))) { + log_err(cd, _("Header backup file does not contain compatible LUKS header.")); + return -EINVAL; } - r = keyslot_verify_or_find_empty(cd, &keyslot); - if (r) - goto out; + memset(&hdr2, 0, sizeof(hdr2)); - if (!passphrase) { - r = key_from_terminal(cd, _("Enter new passphrase for key slot: "), - &new_password, &new_passwordLen, 1); - if (r < 0) - goto out; - passphrase = new_password; - passphrase_size = new_passwordLen; - } + if (!cd->type) { + if (version == 1) + r = LUKS_hdr_restore(backup_file, &hdr1, cd); + else + r = LUKS2_hdr_restore(cd, &hdr2, backup_file); - r = LUKS_set_key(keyslot, passphrase, passphrase_size, - &cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd); -out: - crypt_safe_free(new_password); - crypt_free_volume_key(vk); - return (r < 0) ? r : keyslot; + crypt_safe_memzero(&hdr1, sizeof(hdr1)); + crypt_safe_memzero(&hdr2, sizeof(hdr2)); + } else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type))) { + r = LUKS2_hdr_restore(cd, &cd->u.luks2.hdr, backup_file); + if (r) + _luks2_reload(cd); + } else if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type))) + r = LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd); + else + r = -EINVAL; + + if (!r) + r = _crypt_load_luks(cd, version == 1 ? CRYPT_LUKS1 : CRYPT_LUKS2, 1, 1); + + return r; } -int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot) +void crypt_free(struct crypt_device *cd) { - crypt_keyslot_info ki; - int r; + if (!cd) + return; - log_dbg("Destroying keyslot %d.", keyslot); + log_dbg(cd, "Releasing crypt device %s context.", mdata_device_path(cd)); - r = onlyLUKS(cd); - if (r < 0) - return r; + dm_backend_exit(cd); + crypt_free_volume_key(cd->volume_key); - ki = crypt_keyslot_status(cd, keyslot); - if (ki == CRYPT_SLOT_INVALID) { - log_err(cd, _("Key slot %d is invalid.\n"), keyslot); - return -EINVAL; - } + crypt_free_type(cd); - if (ki == CRYPT_SLOT_INACTIVE) { - log_err(cd, _("Key slot %d is not used.\n"), keyslot); - return -EINVAL; - } + device_free(cd, cd->device); + device_free(cd, cd->metadata_device); + + free(CONST_CAST(void*)cd->pbkdf.type); + free(CONST_CAST(void*)cd->pbkdf.hash); - return LUKS_del_key(keyslot, &cd->u.luks1.hdr, cd); + /* Some structures can contain keys (TCRYPT), wipe it */ + crypt_safe_memzero(cd, sizeof(*cd)); + free(cd); } -// activation/deactivation of device mapping -int crypt_activate_by_passphrase(struct crypt_device *cd, - const char *name, - int keyslot, - const char *passphrase, - size_t passphrase_size, - uint32_t flags) +static char *crypt_get_device_key_description(struct crypt_device *cd, const char *name) +{ + char *desc = NULL; + struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; + + if (dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmd) < 0) + return NULL; + + if (single_segment(&dmd) && tgt->type == DM_CRYPT && + (dmd.flags & CRYPT_ACTIVATE_KEYRING_KEY) && tgt->u.crypt.vk->key_description) + desc = strdup(tgt->u.crypt.vk->key_description); + + dm_targets_free(cd, &dmd); + + return desc; +} + +int crypt_suspend(struct crypt_device *cd, + const char *name) { + char *key_desc; crypt_status_info ci; - struct volume_key *vk = NULL; - char *read_passphrase = NULL; - size_t passphraseLen = 0; int r; + uint32_t dmflags = DM_SUSPEND_WIPE_KEY; - log_dbg("%s volume %s [keyslot %d] using %spassphrase.", - name ? "Activating" : "Checking", name ?: "", - keyslot, passphrase ? "" : "[none] "); + /* FIXME: check context uuid matches the dm-crypt device uuid (onlyLUKS branching) */ - if (name) { - ci = crypt_status(NULL, name); - if (ci == CRYPT_INVALID) - return -EINVAL; - else if (ci >= CRYPT_ACTIVE) { - log_err(cd, _("Device %s already exists.\n"), name); - return -EEXIST; - } - } + if (!cd || !name) + return -EINVAL; - /* plain, use hashed passphrase */ - if (isPLAIN(cd->type)) { - if (!name) - return -EINVAL; + log_dbg(cd, "Suspending volume %s.", name); - if (!passphrase) { - r = key_from_terminal(cd, NULL, &read_passphrase, - &passphraseLen, 0); - if (r < 0) - goto out; - passphrase = read_passphrase; - passphrase_size = passphraseLen; - } + if (cd->type) + r = onlyLUKS(cd); + else { + r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1); + if (r < 0) + r = crypt_uuid_type_cmp(cd, CRYPT_LUKS2); + if (r < 0) + log_err(cd, _("This operation is supported only for LUKS device.")); + } - r = process_key(cd, cd->u.plain.hdr.hash, - cd->u.plain.key_size, - passphrase, passphrase_size, &vk); + if (r < 0) + return r; + + ci = crypt_status(NULL, name); + if (ci < CRYPT_ACTIVE) { + log_err(cd, _("Volume %s is not active."), name); + return -EINVAL; + } + + dm_backend_init(cd); + + r = dm_status_suspended(cd, name); + if (r < 0) + goto out; + + if (r) { + log_err(cd, _("Volume %s is already suspended."), name); + r = -EINVAL; + goto out; + } + + key_desc = crypt_get_device_key_description(cd, name); + + /* we can't simply wipe wrapped keys */ + if (crypt_cipher_wrapped_key(crypt_get_cipher(cd), crypt_get_cipher_mode(cd))) + dmflags &= ~DM_SUSPEND_WIPE_KEY; + + r = dm_suspend_device(cd, name, dmflags); + if (r == -ENOTSUP) + log_err(cd, _("Suspend is not supported for device %s."), name); + else if (r) + log_err(cd, _("Error during suspending device %s."), name); + else + crypt_drop_keyring_key_by_description(cd, key_desc, LOGON_KEY); + free(key_desc); +out: + dm_backend_exit(cd); + return r; +} + +int crypt_resume_by_passphrase(struct crypt_device *cd, + const char *name, + int keyslot, + const char *passphrase, + size_t passphrase_size) +{ + struct volume_key *vk = NULL; + int r; + + /* FIXME: check context uuid matches the dm-crypt device uuid */ + + if (!passphrase || !name) + return -EINVAL; + + log_dbg(cd, "Resuming volume %s.", name); + + if ((r = onlyLUKS(cd))) + return r; + + r = dm_status_suspended(cd, name); + if (r < 0) + return r; + + if (!r) { + log_err(cd, _("Volume %s is not suspended."), name); + return -EINVAL; + } + + if (isLUKS1(cd->type)) + r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size, + &cd->u.luks1.hdr, &vk, cd); + else + r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT, passphrase, passphrase_size, &vk); + + if (r < 0) + goto out; + + keyslot = r; + + if (crypt_use_keyring_for_vk(cd)) { + if (!isLUKS2(cd->type)) { + r = -EINVAL; + goto out; + } + r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, + &cd->u.luks2.hdr, vk, keyslot); if (r < 0) goto out; + } - r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags); - keyslot = 0; - } else if (isLUKS(cd->type)) { - /* provided passphrase, do not retry */ - if (passphrase) { - r = LUKS_open_key_with_hdr(keyslot, passphrase, - passphrase_size, &cd->u.luks1.hdr, &vk, cd); - } else - r = volume_key_by_terminal_passphrase(cd, keyslot, &vk); + r = dm_resume_and_reinstate_key(cd, name, vk); - if (r >= 0) { - keyslot = r; - if (name) - r = LUKS1_activate(cd, name, vk, flags); - } - } else - r = -EINVAL; + if (r == -ENOTSUP) + log_err(cd, _("Resume is not supported for device %s."), name); + else if (r) + log_err(cd, _("Error during resuming device %s."), name); out: - crypt_safe_free(read_passphrase); + if (r < 0) + crypt_drop_keyring_key(cd, vk); crypt_free_volume_key(vk); - return r < 0 ? r : keyslot; + return r < 0 ? r : keyslot; } -int crypt_activate_by_keyfile_offset(struct crypt_device *cd, - const char *name, - int keyslot, - const char *keyfile, - size_t keyfile_size, - size_t keyfile_offset, - uint32_t flags) +int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset) { - crypt_status_info ci; struct volume_key *vk = NULL; char *passphrase_read = NULL; size_t passphrase_size_read; - unsigned int key_count = 0; int r; - log_dbg("Activating volume %s [keyslot %d] using keyfile %s.", - name ?: "", keyslot, keyfile ?: "[none]"); - - if (name) { - ci = crypt_status(NULL, name); - if (ci == CRYPT_INVALID) - return -EINVAL; - else if (ci >= CRYPT_ACTIVE) { - log_err(cd, _("Device %s already exists.\n"), name); - return -EEXIST; - } - } + /* FIXME: check context uuid matches the dm-crypt device uuid */ - if (!keyfile) + if (!name || !keyfile) return -EINVAL; - if (isPLAIN(cd->type)) { - if (!name) - return -EINVAL; + log_dbg(cd, "Resuming volume %s.", name); - r = key_from_file(cd, _("Enter passphrase: "), - &passphrase_read, &passphrase_size_read, - keyfile, keyfile_offset, keyfile_size); - if (r < 0) - goto out; + if ((r = onlyLUKS(cd))) + return r; - r = process_key(cd, cd->u.plain.hdr.hash, - cd->u.plain.key_size, - passphrase_read, passphrase_size_read, &vk); - if (r < 0) - goto out; + r = dm_status_suspended(cd, name); + if (r < 0) + return r; - r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags); - } else if (isLUKS(cd->type)) { - r = key_from_file(cd, _("Enter passphrase: "), &passphrase_read, - &passphrase_size_read, keyfile, keyfile_offset, keyfile_size); - if (r < 0) - goto out; - r = LUKS_open_key_with_hdr(keyslot, passphrase_read, - passphrase_size_read, &cd->u.luks1.hdr, &vk, cd); - if (r < 0) - goto out; - keyslot = r; + if (!r) { + log_err(cd, _("Volume %s is not suspended."), name); + return -EINVAL; + } - if (name) { - r = LUKS1_activate(cd, name, vk, flags); - if (r < 0) - goto out; - } - r = keyslot; - } else if (isLOOPAES(cd->type)) { - r = key_from_file(cd, NULL, &passphrase_read, &passphrase_size_read, - keyfile, keyfile_offset, keyfile_size); - if (r < 0) + r = crypt_keyfile_device_read(cd, keyfile, + &passphrase_read, &passphrase_size_read, + keyfile_offset, keyfile_size, 0); + if (r < 0) + goto out; + + if (isLUKS1(cd->type)) + r = LUKS_open_key_with_hdr(keyslot, passphrase_read, passphrase_size_read, + &cd->u.luks1.hdr, &vk, cd); + else + r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT, passphrase_read, passphrase_size_read, &vk); + if (r < 0) + goto out; + keyslot = r; + + if (crypt_use_keyring_for_vk(cd)) { + if (!isLUKS2(cd->type)) { + r = -EINVAL; goto out; - r = LOOPAES_parse_keyfile(cd, &vk, cd->u.loopaes.hdr.hash, &key_count, - passphrase_read, passphrase_size_read); + } + r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, + &cd->u.luks2.hdr, vk, keyslot); if (r < 0) goto out; - if (name) - r = LOOPAES_activate(cd, name, cd->u.loopaes.cipher, - key_count, vk, flags); - } else - r = -EINVAL; + } + r = dm_resume_and_reinstate_key(cd, name, vk); + if (r < 0) + log_err(cd, _("Error during resuming device %s."), name); out: crypt_safe_free(passphrase_read); + if (r < 0) + crypt_drop_keyring_key(cd, vk); crypt_free_volume_key(vk); + return r < 0 ? r : keyslot; +} - return r; +int crypt_resume_by_keyfile(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size) +{ + return crypt_resume_by_keyfile_device_offset(cd, name, keyslot, + keyfile, keyfile_size, 0); } -int crypt_activate_by_keyfile(struct crypt_device *cd, - const char *name, - int keyslot, - const char *keyfile, - size_t keyfile_size, - uint32_t flags) +int crypt_resume_by_keyfile_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + size_t keyfile_offset) { - return crypt_activate_by_keyfile_offset(cd, name, keyslot, keyfile, - keyfile_size, 0, flags); + return crypt_resume_by_keyfile_device_offset(cd, name, keyslot, + keyfile, keyfile_size, keyfile_offset); } -int crypt_activate_by_volume_key(struct crypt_device *cd, +int crypt_resume_by_volume_key(struct crypt_device *cd, const char *name, const char *volume_key, - size_t volume_key_size, - uint32_t flags) + size_t volume_key_size) { - crypt_status_info ci; struct volume_key *vk = NULL; - int r = -EINVAL; + int r; - log_dbg("Activating volume %s by volume key.", name ?: "[none]"); + if (!name || !volume_key) + return -EINVAL; - if (name) { - ci = crypt_status(NULL, name); - if (ci == CRYPT_INVALID) - return -EINVAL; - else if (ci >= CRYPT_ACTIVE) { - log_err(cd, _("Device %s already exists.\n"), name); - return -EEXIST; - } - } + log_dbg(cd, "Resuming volume %s by volume key.", name); - /* use key directly, no hash */ - if (isPLAIN(cd->type)) { - if (!name) - return -EINVAL; + if ((r = onlyLUKS(cd))) + return r; - if (!volume_key || !volume_key_size || volume_key_size != cd->u.plain.key_size) { - log_err(cd, _("Incorrect volume key specified for plain device.\n")); - return -EINVAL; - } + r = dm_status_suspended(cd, name); + if (r < 0) + return r; - vk = crypt_alloc_volume_key(volume_key_size, volume_key); - if (!vk) - return -ENOMEM; + if (!r) { + log_err(cd, _("Volume %s is not suspended."), name); + return -EINVAL; + } - r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags); - } else if (isLUKS(cd->type)) { - /* If key is not provided, try to use internal key */ - if (!volume_key) { - if (!cd->volume_key) { - log_err(cd, _("Volume key does not match the volume.\n")); - return -EINVAL; - } - volume_key_size = cd->volume_key->keylength; - volume_key = cd->volume_key->key; - } + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; - vk = crypt_alloc_volume_key(volume_key_size, volume_key); - if (!vk) - return -ENOMEM; + if (isLUKS1(cd->type)) r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); + else if (isLUKS2(cd->type)) + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + else + r = -EINVAL; + if (r == -EPERM || r == -ENOENT) + log_err(cd, _("Volume key does not match the volume.")); + if (r < 0) + goto out; + r = 0; - if (r == -EPERM) - log_err(cd, _("Volume key does not match the volume.\n")); + if (crypt_use_keyring_for_vk(cd)) { + r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT); + if (!r) + r = crypt_volume_key_load_in_keyring(cd, vk); + } + if (r < 0) + goto out; - if (!r && name) - r = LUKS1_activate(cd, name, vk, flags); - } else if (isVERITY(cd->type)) { - /* volume_key == root hash */ - if (!volume_key || !volume_key_size) { - log_err(cd, _("Incorrect root hash specified for verity device.\n")); - return -EINVAL; - } + r = dm_resume_and_reinstate_key(cd, name, vk); + if (r < 0) + log_err(cd, _("Error during resuming device %s."), name); +out: + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + return r; +} - r = VERITY_activate(cd, name, volume_key, volume_key_size, - &cd->u.verity.hdr, CRYPT_ACTIVATE_READONLY); - - if (r == -EPERM) { - free(cd->u.verity.root_hash); - cd->u.verity.root_hash = NULL; - } if (!r) { - cd->u.verity.root_hash_size = volume_key_size; - if (!cd->u.verity.root_hash) - cd->u.verity.root_hash = malloc(volume_key_size); - if (cd->u.verity.root_hash) - memcpy(cd->u.verity.root_hash, volume_key, volume_key_size); +/* + * Keyslot manipulation + */ +int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, + int keyslot, // -1 any + const char *passphrase, + size_t passphrase_size, + const char *new_passphrase, + size_t new_passphrase_size) +{ + int digest, r, active_slots; + struct luks2_keyslot_params params; + struct volume_key *vk = NULL; + + log_dbg(cd, "Adding new keyslot, existing passphrase %sprovided," + "new passphrase %sprovided.", + passphrase ? "" : "not ", new_passphrase ? "" : "not "); + + if ((r = onlyLUKS(cd))) + return r; + + if (!passphrase || !new_passphrase) + return -EINVAL; + + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r) + return r; + + if (isLUKS1(cd->type)) + active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr); + else + active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + if (active_slots == 0) { + /* No slots used, try to use pre-generated key in header */ + if (cd->volume_key) { + vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); + r = vk ? 0 : -ENOMEM; + } else { + log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.")); + return -EINVAL; } - } else if (isTCRYPT(cd->type)) { - if (!name) - return 0; + } else if (active_slots < 0) + return -EINVAL; + else { + /* Passphrase provided, use it to unlock existing keyslot */ + if (isLUKS1(cd->type)) + r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, passphrase, + passphrase_size, &cd->u.luks1.hdr, &vk, cd); + else + r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, passphrase, + passphrase_size, &vk); + } + + if (r < 0) + goto out; + + if (isLUKS1(cd->type)) + r = LUKS_set_key(keyslot, CONST_CAST(char*)new_passphrase, + new_passphrase_size, &cd->u.luks1.hdr, vk, cd); + else { + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + digest = r; + + if (r >= 0) + r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, ¶ms); + + if (r >= 0) + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); + + if (r >= 0) + r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot, + CONST_CAST(char*)new_passphrase, + new_passphrase_size, vk, ¶ms); + } + + if (r < 0) + goto out; + + r = 0; +out: + crypt_free_volume_key(vk); + if (r < 0) { + _luks2_reload(cd); + return r; + } + return keyslot; +} + +int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, + int keyslot_old, + int keyslot_new, + const char *passphrase, + size_t passphrase_size, + const char *new_passphrase, + size_t new_passphrase_size) +{ + int digest = -1, r; + struct luks2_keyslot_params params; + struct volume_key *vk = NULL; + + if (!passphrase || !new_passphrase) + return -EINVAL; + + log_dbg(cd, "Changing passphrase from old keyslot %d to new %d.", + keyslot_old, keyslot_new); + + if ((r = onlyLUKS(cd))) + return r; + + if (isLUKS1(cd->type)) + r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size, + &cd->u.luks1.hdr, &vk, cd); + else if (isLUKS2(cd->type)) { + r = LUKS2_keyslot_open(cd, keyslot_old, CRYPT_ANY_SEGMENT, passphrase, passphrase_size, &vk); + /* will fail for keyslots w/o digest. fix if supported in a future */ + if (r >= 0) { + digest = LUKS2_digest_by_keyslot(&cd->u.luks2.hdr, r); + if (digest < 0) + r = -EINVAL; + } + } else + r = -EINVAL; + if (r < 0) + goto out; + + if (keyslot_old != CRYPT_ANY_SLOT && keyslot_old != r) { + log_dbg(cd, "Keyslot mismatch."); + goto out; + } + keyslot_old = r; + + if (keyslot_new == CRYPT_ANY_SLOT) { + if (isLUKS1(cd->type)) + keyslot_new = LUKS_keyslot_find_empty(&cd->u.luks1.hdr); + else if (isLUKS2(cd->type)) + keyslot_new = LUKS2_keyslot_find_empty(&cd->u.luks2.hdr); + if (keyslot_new < 0) + keyslot_new = keyslot_old; + } + log_dbg(cd, "Key change, old slot %d, new slot %d.", keyslot_old, keyslot_new); + + if (isLUKS1(cd->type)) { + if (keyslot_old == keyslot_new) { + log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old); + (void)crypt_keyslot_destroy(cd, keyslot_old); + } + r = LUKS_set_key(keyslot_new, new_passphrase, new_passphrase_size, + &cd->u.luks1.hdr, vk, cd); + } else if (isLUKS2(cd->type)) { + r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, ¶ms); + if (r) + goto out; + + if (keyslot_old != keyslot_new) { + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, digest, 1, 0); + if (r < 0) + goto out; + } else { + log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old); + /* FIXME: improve return code so that we can detect area is damaged */ + r = LUKS2_keyslot_wipe(cd, &cd->u.luks2.hdr, keyslot_old, 1); + if (r) { + /* (void)crypt_keyslot_destroy(cd, keyslot_old); */ + r = -EINVAL; + goto out; + } + } + + r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, + keyslot_new, new_passphrase, + new_passphrase_size, vk, ¶ms); + } else + r = -EINVAL; + + if (r >= 0 && keyslot_old != keyslot_new) + r = crypt_keyslot_destroy(cd, keyslot_old); + + if (r < 0) + log_err(cd, _("Failed to swap new key slot.")); +out: + crypt_free_volume_key(vk); + if (r < 0) { + _luks2_reload(cd); + return r; + } + return keyslot_new; +} + +int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset, + const char *new_keyfile, + size_t new_keyfile_size, + uint64_t new_keyfile_offset) +{ + int digest, r, active_slots; + size_t passwordLen, new_passwordLen; + struct luks2_keyslot_params params; + char *password = NULL, *new_password = NULL; + struct volume_key *vk = NULL; + + if (!keyfile || !new_keyfile) + return -EINVAL; + + log_dbg(cd, "Adding new keyslot, existing keyfile %s, new keyfile %s.", + keyfile, new_keyfile); + + if ((r = onlyLUKS(cd))) + return r; + + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r) + return r; + + if (isLUKS1(cd->type)) + active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr); + else + active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + if (active_slots == 0) { + /* No slots used, try to use pre-generated key in header */ + if (cd->volume_key) { + vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); + r = vk ? 0 : -ENOMEM; + } else { + log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.")); + return -EINVAL; + } + } else { + r = crypt_keyfile_device_read(cd, keyfile, + &password, &passwordLen, + keyfile_offset, keyfile_size, 0); + if (r < 0) + goto out; + + if (isLUKS1(cd->type)) + r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, password, passwordLen, + &cd->u.luks1.hdr, &vk, cd); + else + r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, password, passwordLen, &vk); + } + + if (r < 0) + goto out; + + r = crypt_keyfile_device_read(cd, new_keyfile, + &new_password, &new_passwordLen, + new_keyfile_offset, new_keyfile_size, 0); + if (r < 0) + goto out; + + if (isLUKS1(cd->type)) + r = LUKS_set_key(keyslot, new_password, new_passwordLen, + &cd->u.luks1.hdr, vk, cd); + else { + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + digest = r; + + if (r >= 0) + r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, ¶ms); + + if (r >= 0) + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); + + if (r >= 0) + r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot, + new_password, new_passwordLen, vk, ¶ms); + } +out: + crypt_safe_free(password); + crypt_safe_free(new_password); + crypt_free_volume_key(vk); + if (r < 0) { + _luks2_reload(cd); + return r; + } + return keyslot; +} + +int crypt_keyslot_add_by_keyfile(struct crypt_device *cd, + int keyslot, + const char *keyfile, + size_t keyfile_size, + const char *new_keyfile, + size_t new_keyfile_size) +{ + return crypt_keyslot_add_by_keyfile_device_offset(cd, keyslot, + keyfile, keyfile_size, 0, + new_keyfile, new_keyfile_size, 0); +} + +int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd, + int keyslot, + const char *keyfile, + size_t keyfile_size, + size_t keyfile_offset, + const char *new_keyfile, + size_t new_keyfile_size, + size_t new_keyfile_offset) +{ + return crypt_keyslot_add_by_keyfile_device_offset(cd, keyslot, + keyfile, keyfile_size, keyfile_offset, + new_keyfile, new_keyfile_size, new_keyfile_offset); +} + +int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, + int keyslot, + const char *volume_key, + size_t volume_key_size, + const char *passphrase, + size_t passphrase_size) +{ + struct volume_key *vk = NULL; + int r; + + if (!passphrase) + return -EINVAL; + + log_dbg(cd, "Adding new keyslot %d using volume key.", keyslot); + + if ((r = onlyLUKS(cd))) + return r; + + if (isLUKS2(cd->type)) + return crypt_keyslot_add_by_key(cd, keyslot, + volume_key, volume_key_size, passphrase, + passphrase_size, 0); + + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r < 0) + return r; + + if (volume_key) + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + else if (cd->volume_key) + vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); + + if (!vk) + return -ENOMEM; + + r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); + if (r < 0) + log_err(cd, _("Volume key does not match the volume.")); + else + r = LUKS_set_key(keyslot, passphrase, passphrase_size, + &cd->u.luks1.hdr, vk, cd); + + crypt_free_volume_key(vk); + return (r < 0) ? r : keyslot; +} + +int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot) +{ + crypt_keyslot_info ki; + int r; + + log_dbg(cd, "Destroying keyslot %d.", keyslot); + + if ((r = _onlyLUKS(cd, CRYPT_CD_UNRESTRICTED))) + return r; + + ki = crypt_keyslot_status(cd, keyslot); + if (ki == CRYPT_SLOT_INVALID) { + log_err(cd, _("Key slot %d is invalid."), keyslot); + return -EINVAL; + } + + if (isLUKS1(cd->type)) { + if (ki == CRYPT_SLOT_INACTIVE) { + log_err(cd, _("Keyslot %d is not active."), keyslot); + return -EINVAL; + } + return LUKS_del_key(keyslot, &cd->u.luks1.hdr, cd); + } + + return LUKS2_keyslot_wipe(cd, &cd->u.luks2.hdr, keyslot, 0); +} + +static int _check_header_data_overlap(struct crypt_device *cd, const char *name) +{ + if (!name || !isLUKS(cd->type)) + return 0; + + if (!device_is_identical(crypt_data_device(cd), crypt_metadata_device(cd))) + return 0; + + /* FIXME: check real header size */ + if (crypt_get_data_offset(cd) == 0) { + log_err(cd, _("Device header overlaps with data area.")); + return -EINVAL; + } + + return 0; +} + +static int check_devices(struct crypt_device *cd, const char *name, const char *iname, uint32_t *flags) +{ + int r; + + if (!flags || !name) + return -EINVAL; + + if (iname) { + r = dm_status_device(cd, iname); + if (r >= 0 && !(*flags & CRYPT_ACTIVATE_REFRESH)) + return -EBUSY; + if (r < 0 && r != -ENODEV) + return r; + if (r == -ENODEV) + *flags &= ~CRYPT_ACTIVATE_REFRESH; + } + + r = dm_status_device(cd, name); + if (r >= 0 && !(*flags & CRYPT_ACTIVATE_REFRESH)) + return -EBUSY; + if (r < 0 && r != -ENODEV) + return r; + if (r == -ENODEV) + *flags &= ~CRYPT_ACTIVATE_REFRESH; + + return 0; +} + +static int _create_device_with_integrity(struct crypt_device *cd, + const char *type, const char *name, const char *iname, + const char *ipath, struct crypt_dm_active_device *dmd, + struct crypt_dm_active_device *dmdi) +{ + int r; + enum devcheck device_check; + struct dm_target *tgt; + struct device *device = NULL; + + if (!single_segment(dmd)) + return -EINVAL; + + tgt = &dmd->segment; + if (tgt->type != DM_CRYPT) + return -EINVAL; + + device_check = dmd->flags & CRYPT_ACTIVATE_SHARED ? DEV_OK : DEV_EXCL; + + r = INTEGRITY_activate_dmd_device(cd, iname, CRYPT_INTEGRITY, dmdi, 0); + if (r) + return r; + + r = device_alloc(cd, &device, ipath); + if (r < 0) + goto out; + tgt->data_device = device; + + r = device_block_adjust(cd, tgt->data_device, device_check, + tgt->u.crypt.offset, &dmd->size, &dmd->flags); + + if (!r) + r = dm_create_device(cd, name, type, dmd); +out: + if (r < 0) + dm_remove_device(cd, iname, 0); + + device_free(cd, device); + return r; +} + +static int kernel_keyring_support(void) +{ + static unsigned _checked = 0; + + if (!_checked) { + _kernel_keyring_supported = keyring_check(); + _checked = 1; + } + + return _kernel_keyring_supported; +} + +static int dmcrypt_keyring_bug(void) +{ + uint64_t kversion; + + if (kernel_version(&kversion)) + return 1; + return kversion < version(4,15,0,0); +} + +int create_or_reload_device(struct crypt_device *cd, const char *name, + const char *type, struct crypt_dm_active_device *dmd) +{ + int r; + enum devcheck device_check; + struct dm_target *tgt; + + if (!type || !name || !single_segment(dmd)) + return -EINVAL; + + tgt = &dmd->segment; + if (tgt->type != DM_CRYPT) + return -EINVAL; + + /* drop CRYPT_ACTIVATE_REFRESH flag if any device is inactive */ + r = check_devices(cd, name, NULL, &dmd->flags); + if (r) + return r; + + if (dmd->flags & CRYPT_ACTIVATE_REFRESH) + r = _reload_device(cd, name, dmd); + else { + device_check = dmd->flags & CRYPT_ACTIVATE_SHARED ? DEV_OK : DEV_EXCL; + + r = device_block_adjust(cd, tgt->data_device, device_check, + tgt->u.crypt.offset, &dmd->size, &dmd->flags); + if (!r) { + tgt->size = dmd->size; + r = dm_create_device(cd, name, type, dmd); + } + } + + return r; +} + +int create_or_reload_device_with_integrity(struct crypt_device *cd, const char *name, + const char *type, struct crypt_dm_active_device *dmd, + struct crypt_dm_active_device *dmdi) +{ + int r; + const char *iname = NULL; + char *ipath = NULL; + + if (!type || !name || !dmd || !dmdi) + return -EINVAL; + + if (asprintf(&ipath, "%s/%s_dif", dm_get_dir(), name) < 0) + return -ENOMEM; + iname = ipath + strlen(dm_get_dir()) + 1; + + /* drop CRYPT_ACTIVATE_REFRESH flag if any device is inactive */ + r = check_devices(cd, name, iname, &dmd->flags); + if (r) + goto out; + + if (dmd->flags & CRYPT_ACTIVATE_REFRESH) + r = _reload_device_with_integrity(cd, name, iname, ipath, dmd, dmdi); + else + r = _create_device_with_integrity(cd, type, name, iname, ipath, dmd, dmdi); +out: + free(ipath); + + return r; +} + +static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks) +{ + int r; + struct volume_key *vk = vks; + + while (vk) { + r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk)); + if (r < 0) + return r; + vk = crypt_volume_key_next(vk); + } + + return 0; +} + +/* See fixmes in _open_and_activate_luks2 */ +int update_reencryption_flag(struct crypt_device *cd, int enable, bool commit); + +/* TODO: This function should 1:1 with pre-reencryption code */ +static int _open_and_activate(struct crypt_device *cd, + int keyslot, + const char *name, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) +{ + int r; + struct volume_key *vk = NULL; + + r = LUKS2_keyslot_open(cd, keyslot, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, + passphrase, passphrase_size, &vk); + if (r < 0) + return r; + keyslot = r; + + if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && + crypt_use_keyring_for_vk(cd)) { + r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, + &cd->u.luks2.hdr, vk, keyslot); + if (r < 0) + goto out; + flags |= CRYPT_ACTIVATE_KEYRING_KEY; + } + + if (name) + r = LUKS2_activate(cd, name, vk, flags); +out: + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + + return r < 0 ? r : keyslot; +} + +static int _open_all_keys(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const char *passphrase, + size_t passphrase_size, + uint32_t flags, + struct volume_key **vks) +{ + int r, segment; + struct volume_key *_vks = NULL; + crypt_reencrypt_info ri = LUKS2_reenc_status(hdr); + + segment = (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT; + + switch (ri) { + case CRYPT_REENCRYPT_NONE: + r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, &_vks); + break; + case CRYPT_REENCRYPT_CLEAN: + case CRYPT_REENCRYPT_CRASH: + if (segment == CRYPT_ANY_SEGMENT) + r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, + passphrase_size, &_vks); + else + r = LUKS2_keyslot_open_all_segments(cd, keyslot, + keyslot, passphrase, passphrase_size, + &_vks); + break; + default: + r = -EINVAL; + } + + if (keyslot == CRYPT_ANY_SLOT) + keyslot = r; + + if (r >= 0 && (flags & CRYPT_ACTIVATE_KEYRING_KEY)) + r = load_all_keys(cd, hdr, _vks); + + if (r >= 0 && vks) + MOVE_REF(*vks, _vks); + + if (r < 0) + crypt_drop_keyring_key(cd, _vks); + crypt_free_volume_key(_vks); + + return r < 0 ? r : keyslot; +} + +static int _open_and_activate_reencrypt_device(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot, + const char *name, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) +{ + bool dynamic_size; + crypt_reencrypt_info ri; + uint64_t minimal_size, device_size; + struct volume_key *vks = NULL; + int r = 0; + struct crypt_lock_handle *reencrypt_lock = NULL; + + if (crypt_use_keyring_for_vk(cd)) + flags |= CRYPT_ACTIVATE_KEYRING_KEY; + + r = crypt_reencrypt_lock(cd, &reencrypt_lock); + if (r) { + if (r == -EBUSY) + log_err(cd, _("Reencryption in-progress. Cannot activate device.")); + else + log_err(cd, _("Failed to get reencryption lock.")); + return r; + } + + if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) + goto err; + + ri = LUKS2_reenc_status(hdr); + + if (ri == CRYPT_REENCRYPT_CRASH) { + r = LUKS2_reencrypt_locked_recovery_by_passphrase(cd, keyslot, + keyslot, passphrase, passphrase_size, flags, &vks); + if (r < 0) { + log_err(cd, _("LUKS2 reencryption recovery failed.")); + goto err; + } + keyslot = r; + + ri = LUKS2_reenc_status(hdr); + } + + /* recovery finished reencryption or it's already finished */ + if (ri == CRYPT_REENCRYPT_NONE) { + crypt_drop_keyring_key(cd, vks); + crypt_free_volume_key(vks); + crypt_reencrypt_unlock(cd, reencrypt_lock); + return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags); + } + + if (ri > CRYPT_REENCRYPT_CLEAN) { + r = -EINVAL; + goto err; + } + + if (LUKS2_get_data_size(hdr, &minimal_size, &dynamic_size)) + goto err; + + if (!vks) { + r = _open_all_keys(cd, hdr, keyslot, passphrase, passphrase_size, flags, &vks); + if (r >= 0) + keyslot = r; + } + + log_dbg(cd, "Entering clean reencryption state mode."); + + if (r >= 0) + r = luks2_check_device_size(cd, hdr, minimal_size, &device_size, true, dynamic_size); + + if (r >= 0) + r = LUKS2_activate_multi(cd, name, vks, device_size >> SECTOR_SHIFT, flags); +err: + crypt_reencrypt_unlock(cd, reencrypt_lock); + if (r < 0) + crypt_drop_keyring_key(cd, vks); + crypt_free_volume_key(vks); + + return r < 0 ? r : keyslot; +} + +/* + * Activation/deactivation of a device + */ +static int _open_and_activate_luks2(struct crypt_device *cd, + int keyslot, + const char *name, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) +{ + crypt_reencrypt_info ri; + int r; + struct luks2_hdr *hdr = &cd->u.luks2.hdr; + + ri = LUKS2_reenc_status(hdr); + if (ri == CRYPT_REENCRYPT_INVALID) + return -EINVAL; + + if (ri > CRYPT_REENCRYPT_NONE) { + if (name) + r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase, + passphrase_size, flags); + else + r = _open_all_keys(cd, hdr, keyslot, passphrase, + passphrase_size, flags, NULL); + } else + r = _open_and_activate(cd, keyslot, name, passphrase, + passphrase_size, flags); + + return r; +} + +static int _activate_by_passphrase(struct crypt_device *cd, + const char *name, + int keyslot, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) +{ + int r; + struct volume_key *vk = NULL; + + if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)) + return -EINVAL; + + if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name) + return -EINVAL; + + r = _check_header_data_overlap(cd, name); + if (r < 0) + return r; + + if (flags & CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF) + cd->memory_hard_pbkdf_lock_enabled = true; + + /* plain, use hashed passphrase */ + if (isPLAIN(cd->type)) { + r = -EINVAL; + if (!name) + goto out; + + r = process_key(cd, cd->u.plain.hdr.hash, + cd->u.plain.key_size, + passphrase, passphrase_size, &vk); + if (r < 0) + goto out; + + r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags); + keyslot = 0; + } else if (isLUKS1(cd->type)) { + r = LUKS_open_key_with_hdr(keyslot, passphrase, + passphrase_size, &cd->u.luks1.hdr, &vk, cd); + if (r >= 0) { + keyslot = r; + if (name) + r = LUKS1_activate(cd, name, vk, flags); + } + } else if (isLUKS2(cd->type)) { + r = _open_and_activate_luks2(cd, keyslot, name, passphrase, passphrase_size, flags); + keyslot = r; + } else if (isBITLK(cd->type)) { + r = BITLK_activate(cd, name, passphrase, passphrase_size, + &cd->u.bitlk.params, flags); + keyslot = 0; + } else { + log_err(cd, _("Device type is not properly initialized.")); + r = -EINVAL; + } +out: + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + + cd->memory_hard_pbkdf_lock_enabled = false; + + return r < 0 ? r : keyslot; +} + +static int _activate_loopaes(struct crypt_device *cd, + const char *name, + char *buffer, + size_t buffer_size, + uint32_t flags) +{ + int r; + unsigned int key_count = 0; + struct volume_key *vk = NULL; + + r = LOOPAES_parse_keyfile(cd, &vk, cd->u.loopaes.hdr.hash, &key_count, + buffer, buffer_size); + + if (!r && name) + r = LOOPAES_activate(cd, name, cd->u.loopaes.cipher, key_count, + vk, flags); + + crypt_free_volume_key(vk); + + return r; +} + +static int _activate_check_status(struct crypt_device *cd, const char *name, unsigned reload) +{ + crypt_status_info ci; + + if (!name) + return 0; + + ci = crypt_status(cd, name); + if (ci == CRYPT_INVALID) { + log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name); + return -EINVAL; + } else if (ci >= CRYPT_ACTIVE && !reload) { + log_err(cd, _("Device %s already exists."), name); + return -EEXIST; + } + + return 0; +} + +// activation/deactivation of device mapping +int crypt_activate_by_passphrase(struct crypt_device *cd, + const char *name, + int keyslot, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) +{ + int r; + + if (!cd || !passphrase || (!name && (flags & CRYPT_ACTIVATE_REFRESH))) + return -EINVAL; + + log_dbg(cd, "%s volume %s [keyslot %d] using passphrase.", + name ? "Activating" : "Checking", name ?: "passphrase", + keyslot); + + r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH); + if (r < 0) + return r; + + return _activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags); +} + +int crypt_activate_by_keyfile_device_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint64_t keyfile_offset, + uint32_t flags) +{ + char *passphrase_read = NULL; + size_t passphrase_size_read; + int r; + + if (!cd || !keyfile || + ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd))) + return -EINVAL; + + log_dbg(cd, "%s volume %s [keyslot %d] using keyfile %s.", + name ? "Activating" : "Checking", name ?: "passphrase", keyslot, keyfile); + + r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH); + if (r < 0) + return r; + + r = crypt_keyfile_device_read(cd, keyfile, + &passphrase_read, &passphrase_size_read, + keyfile_offset, keyfile_size, 0); + if (r < 0) + goto out; + + if (isLOOPAES(cd->type)) + r = _activate_loopaes(cd, name, passphrase_read, passphrase_size_read, flags); + else + r = _activate_by_passphrase(cd, name, keyslot, passphrase_read, passphrase_size_read, flags); + +out: + crypt_safe_free(passphrase_read); + return r; +} + +int crypt_activate_by_keyfile(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + uint32_t flags) +{ + return crypt_activate_by_keyfile_device_offset(cd, name, keyslot, keyfile, + keyfile_size, 0, flags); +} + +int crypt_activate_by_keyfile_offset(struct crypt_device *cd, + const char *name, + int keyslot, + const char *keyfile, + size_t keyfile_size, + size_t keyfile_offset, + uint32_t flags) +{ + return crypt_activate_by_keyfile_device_offset(cd, name, keyslot, keyfile, + keyfile_size, keyfile_offset, flags); +} +int crypt_activate_by_volume_key(struct crypt_device *cd, + const char *name, + const char *volume_key, + size_t volume_key_size, + uint32_t flags) +{ + struct volume_key *vk = NULL; + int r; + + if (!cd || + ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd))) + return -EINVAL; + + log_dbg(cd, "%s volume %s by volume key.", name ? "Activating" : "Checking", + name ?: ""); + + r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH); + if (r < 0) + return r; + + r = _check_header_data_overlap(cd, name); + if (r < 0) + return r; + + /* use key directly, no hash */ + if (isPLAIN(cd->type)) { + if (!name) + return -EINVAL; + + if (!volume_key || !volume_key_size || volume_key_size != cd->u.plain.key_size) { + log_err(cd, _("Incorrect volume key specified for plain device.")); + return -EINVAL; + } + + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; + + r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags); + } else if (isLUKS1(cd->type)) { + /* If key is not provided, try to use internal key */ + if (!volume_key) { + if (!cd->volume_key) { + log_err(cd, _("Volume key does not match the volume.")); + return -EINVAL; + } + volume_key_size = cd->volume_key->keylength; + volume_key = cd->volume_key->key; + } + + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; + r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); + + if (r == -EPERM) + log_err(cd, _("Volume key does not match the volume.")); + + if (!r && name) + r = LUKS1_activate(cd, name, vk, flags); + } else if (isLUKS2(cd->type)) { + /* If key is not provided, try to use internal key */ + if (!volume_key) { + if (!cd->volume_key) { + log_err(cd, _("Volume key does not match the volume.")); + return -EINVAL; + } + volume_key_size = cd->volume_key->keylength; + volume_key = cd->volume_key->key; + } + + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; + + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + if (r == -EPERM || r == -ENOENT) + log_err(cd, _("Volume key does not match the volume.")); + if (r > 0) + r = 0; + + if (!r && (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && + crypt_use_keyring_for_vk(cd)) { + r = LUKS2_key_description_by_segment(cd, + &cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT); + if (!r) + r = crypt_volume_key_load_in_keyring(cd, vk); + if (!r) + flags |= CRYPT_ACTIVATE_KEYRING_KEY; + } + + if (!r && name) + r = LUKS2_activate(cd, name, vk, flags); + } else if (isVERITY(cd->type)) { + r = crypt_activate_by_signed_key(cd, name, volume_key, volume_key_size, NULL, 0, flags); + } else if (isTCRYPT(cd->type)) { + if (!name) + return 0; r = TCRYPT_activate(cd, name, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, flags); + } else if (isINTEGRITY(cd->type)) { + if (!name) + return 0; + if (volume_key) { + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; + } + r = INTEGRITY_activate(cd, name, &cd->u.integrity.params, vk, + cd->u.integrity.journal_crypt_key, + cd->u.integrity.journal_mac_key, flags, + cd->u.integrity.sb_flags); + } else { + log_err(cd, _("Device type is not properly initialized.")); + r = -EINVAL; + } + + if (r < 0) + crypt_drop_keyring_key(cd, vk); + crypt_free_volume_key(vk); + + return r; +} + +int crypt_activate_by_signed_key(struct crypt_device *cd, + const char *name, + const char *volume_key, + size_t volume_key_size, + const char *signature, + size_t signature_size, + uint32_t flags) +{ + char description[512]; + int r; + + if (!cd || !isVERITY(cd->type)) + return -EINVAL; + + if (!volume_key || !volume_key_size || (!name && signature)) { + log_err(cd, _("Incorrect root hash specified for verity device.")); + return -EINVAL; + } + + log_dbg(cd, "%s volume %s by signed key.", name ? "Activating" : "Checking", name ?: ""); + + if (cd->u.verity.hdr.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE && !signature) { + log_err(cd, _("Root hash signature required.")); + return -EINVAL; + } + + r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH); + if (r < 0) + return r; + + if (signature && !kernel_keyring_support()) { + log_err(cd, _("Kernel keyring missing: required for passing signature to kernel.")); + return -EINVAL; + } + + /* volume_key == root hash */ + free(CONST_CAST(void*)cd->u.verity.root_hash); + cd->u.verity.root_hash = NULL; + + if (signature) { + r = snprintf(description, sizeof(description)-1, "cryptsetup:%s%s%s", + crypt_get_uuid(cd) ?: "", crypt_get_uuid(cd) ? "-" : "", name); + if (r < 0) + return -EINVAL; + + log_dbg(cd, "Adding signature into keyring %s", description); + r = keyring_add_key_in_thread_keyring(USER_KEY, description, signature, signature_size); + if (r) { + log_err(cd, _("Failed to load key in kernel keyring.")); + return r; + } + } + + r = VERITY_activate(cd, name, volume_key, volume_key_size, + signature ? description : NULL, + cd->u.verity.fec_device, + &cd->u.verity.hdr, flags | CRYPT_ACTIVATE_READONLY); + + if (!r) { + cd->u.verity.root_hash_size = volume_key_size; + cd->u.verity.root_hash = malloc(volume_key_size); + if (cd->u.verity.root_hash) + memcpy(CONST_CAST(void*)cd->u.verity.root_hash, volume_key, volume_key_size); + } + + if (signature) + crypt_drop_keyring_key_by_description(cd, description, USER_KEY); + + return r; +} + +int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t flags) +{ + struct crypt_device *fake_cd = NULL; + struct luks2_hdr *hdr2 = NULL; + struct crypt_dm_active_device dmd = {}; + int r; + uint32_t get_flags = DM_ACTIVE_DEVICE | DM_ACTIVE_UUID | DM_ACTIVE_HOLDERS; + + if (!name) + return -EINVAL; + + log_dbg(cd, "Deactivating volume %s.", name); + + if (!cd) { + r = crypt_init_by_name(&fake_cd, name); + if (r < 0) + return r; + cd = fake_cd; + } + + /* skip holders detection and early abort when some flags raised */ + if (flags & (CRYPT_DEACTIVATE_FORCE | CRYPT_DEACTIVATE_DEFERRED)) + get_flags &= ~DM_ACTIVE_HOLDERS; + + switch (crypt_status(cd, name)) { + case CRYPT_ACTIVE: + case CRYPT_BUSY: + r = dm_query_device(cd, name, get_flags, &dmd); + if (r >= 0) { + if (dmd.holders) { + log_err(cd, _("Device %s is still in use."), name); + r = -EBUSY; + break; + } + } + + if (isLUKS2(cd->type)) + hdr2 = crypt_get_hdr(cd, CRYPT_LUKS2); + + if ((dmd.uuid && !strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1)) || hdr2) + r = LUKS2_deactivate(cd, name, hdr2, &dmd, flags); + else if (isTCRYPT(cd->type)) + r = TCRYPT_deactivate(cd, name, flags); + else + r = dm_remove_device(cd, name, flags); + if (r < 0 && crypt_status(cd, name) == CRYPT_BUSY) { + log_err(cd, _("Device %s is still in use."), name); + r = -EBUSY; + } + break; + case CRYPT_INACTIVE: + log_err(cd, _("Device %s is not active."), name); + r = -ENODEV; + break; + default: + log_err(cd, _("Invalid device %s."), name); + r = -EINVAL; + } + + dm_targets_free(cd, &dmd); + free(CONST_CAST(void*)dmd.uuid); + crypt_free(fake_cd); + + return r; +} + +int crypt_deactivate(struct crypt_device *cd, const char *name) +{ + return crypt_deactivate_by_name(cd, name, 0); +} + +int crypt_get_active_device(struct crypt_device *cd, const char *name, + struct crypt_active_device *cad) +{ + int r; + struct crypt_dm_active_device dmd, dmdi = {}; + const char *namei = NULL; + struct dm_target *tgt = &dmd.segment; + uint64_t min_offset = UINT64_MAX; + + if (!cd || !name || !cad) + return -EINVAL; + + r = dm_query_device(cd, name, DM_ACTIVE_DEVICE, &dmd); + if (r < 0) + return r; + + /* For LUKS2 with integrity we need flags from underlying dm-integrity */ + if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && single_segment(&dmd)) { + namei = device_dm_name(tgt->data_device); + if (namei && dm_query_device(cd, namei, 0, &dmdi) >= 0) + dmd.flags |= dmdi.flags; + } + + if (cd && isTCRYPT(cd->type)) { + cad->offset = TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + cad->iv_offset = TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + } else { + while (tgt) { + if (tgt->type == DM_CRYPT && (min_offset > tgt->u.crypt.offset)) { + min_offset = tgt->u.crypt.offset; + cad->iv_offset = tgt->u.crypt.iv_offset; + } else if (tgt->type == DM_INTEGRITY && (min_offset > tgt->u.integrity.offset)) { + min_offset = tgt->u.integrity.offset; + cad->iv_offset = 0; + } else if (tgt->type == DM_LINEAR && (min_offset > tgt->u.linear.offset)) { + min_offset = tgt->u.linear.offset; + cad->iv_offset = 0; + } + tgt = tgt->next; + } + } + + if (min_offset != UINT64_MAX) + cad->offset = min_offset; + + cad->size = dmd.size; + cad->flags = dmd.flags; + + r = 0; + dm_targets_free(cd, &dmd); + dm_targets_free(cd, &dmdi); + + return r; +} + +uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd, const char *name) +{ + struct crypt_dm_active_device dmd; + uint64_t failures = 0; + + if (!name) + return 0; + + /* FIXME: LUKS2 / dm-crypt does not provide this count. */ + if (dm_query_device(cd, name, 0, &dmd) < 0) + return 0; + + if (single_segment(&dmd) && dmd.segment.type == DM_INTEGRITY) + (void)dm_status_integrity_failures(cd, name, &failures); + + dm_targets_free(cd, &dmd); + + return failures; +} + +/* + * Volume key handling + */ +int crypt_volume_key_get(struct crypt_device *cd, + int keyslot, + char *volume_key, + size_t *volume_key_size, + const char *passphrase, + size_t passphrase_size) +{ + struct volume_key *vk = NULL; + int key_len, r = -EINVAL; + + if (!cd || !volume_key || !volume_key_size || (!isTCRYPT(cd->type) && !isVERITY(cd->type) && !passphrase)) + return -EINVAL; + + if (isLUKS2(cd->type) && keyslot != CRYPT_ANY_SLOT) + key_len = LUKS2_get_keyslot_stored_key_size(&cd->u.luks2.hdr, keyslot); + else + key_len = crypt_get_volume_key_size(cd); + + if (key_len < 0) + return -EINVAL; + + if (key_len > (int)*volume_key_size) { + log_err(cd, _("Volume key buffer too small.")); + return -ENOMEM; + } + + if (isPLAIN(cd->type) && cd->u.plain.hdr.hash) { + r = process_key(cd, cd->u.plain.hdr.hash, key_len, + passphrase, passphrase_size, &vk); + if (r < 0) + log_err(cd, _("Cannot retrieve volume key for plain device.")); + } else if (isLUKS1(cd->type)) { + r = LUKS_open_key_with_hdr(keyslot, passphrase, + passphrase_size, &cd->u.luks1.hdr, &vk, cd); + } else if (isLUKS2(cd->type)) { + r = LUKS2_keyslot_open(cd, keyslot, + keyslot == CRYPT_ANY_SLOT ? CRYPT_DEFAULT_SEGMENT : CRYPT_ANY_SEGMENT, + passphrase, passphrase_size, &vk); + } else if (isTCRYPT(cd->type)) { + r = TCRYPT_get_volume_key(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, &vk); + } else if (isVERITY(cd->type)) { + /* volume_key == root hash */ + if (cd->u.verity.root_hash) { + memcpy(volume_key, cd->u.verity.root_hash, cd->u.verity.root_hash_size); + *volume_key_size = cd->u.verity.root_hash_size; + r = 0; + } else + log_err(cd, _("Cannot retrieve root hash for verity device.")); + } else + log_err(cd, _("This operation is not supported for %s crypt device."), cd->type ?: "(none)"); + + if (r >= 0 && vk) { + memcpy(volume_key, vk->key, vk->keylength); + *volume_key_size = vk->keylength; + } + + crypt_free_volume_key(vk); + return r; +} + +int crypt_volume_key_verify(struct crypt_device *cd, + const char *volume_key, + size_t volume_key_size) +{ + struct volume_key *vk; + int r; + + if ((r = _onlyLUKS(cd, CRYPT_CD_UNRESTRICTED))) + return r; + + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + if (!vk) + return -ENOMEM; + + if (isLUKS1(cd->type)) + r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); + else if (isLUKS2(cd->type)) + r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + else + r = -EINVAL; + + + if (r == -EPERM) + log_err(cd, _("Volume key does not match the volume.")); + + crypt_free_volume_key(vk); + + return r >= 0 ? 0 : r; +} + +/* + * RNG and memory locking + */ +void crypt_set_rng_type(struct crypt_device *cd, int rng_type) +{ + if (!cd) + return; + + switch (rng_type) { + case CRYPT_RNG_URANDOM: + case CRYPT_RNG_RANDOM: + log_dbg(cd, "RNG set to %d (%s).", rng_type, rng_type ? "random" : "urandom"); + cd->rng_type = rng_type; + } +} + +int crypt_get_rng_type(struct crypt_device *cd) +{ + if (!cd) + return -EINVAL; + + return cd->rng_type; +} + +int crypt_memory_lock(struct crypt_device *cd, int lock) +{ + return lock ? crypt_memlock_inc(cd) : crypt_memlock_dec(cd); +} + +void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags) +{ + if (cd) + cd->compatibility = flags; +} + +uint32_t crypt_get_compatibility(struct crypt_device *cd) +{ + if (cd) + return cd->compatibility; + + return 0; +} + +/* + * Reporting + */ +crypt_status_info crypt_status(struct crypt_device *cd, const char *name) +{ + int r; + + if (!name) + return CRYPT_INVALID; + + if (!cd) + dm_backend_init(cd); + + r = dm_status_device(cd, name); + + if (!cd) + dm_backend_exit(cd); + + if (r < 0 && r != -ENODEV) + return CRYPT_INVALID; + + if (r == 0) + return CRYPT_ACTIVE; + + if (r > 0) + return CRYPT_BUSY; + + return CRYPT_INACTIVE; +} + +static void hexprint(struct crypt_device *cd, const char *d, int n, const char *sep) +{ + int i; + for(i = 0; i < n; i++) + log_std(cd, "%02hhx%s", (const char)d[i], sep); +} + +static int _luks_dump(struct crypt_device *cd) +{ + int i; + + log_std(cd, "LUKS header information for %s\n\n", mdata_device_path(cd)); + log_std(cd, "Version: \t%" PRIu16 "\n", cd->u.luks1.hdr.version); + log_std(cd, "Cipher name: \t%s\n", cd->u.luks1.hdr.cipherName); + log_std(cd, "Cipher mode: \t%s\n", cd->u.luks1.hdr.cipherMode); + log_std(cd, "Hash spec: \t%s\n", cd->u.luks1.hdr.hashSpec); + log_std(cd, "Payload offset:\t%" PRIu32 "\n", cd->u.luks1.hdr.payloadOffset); + log_std(cd, "MK bits: \t%" PRIu32 "\n", cd->u.luks1.hdr.keyBytes * 8); + log_std(cd, "MK digest: \t"); + hexprint(cd, cd->u.luks1.hdr.mkDigest, LUKS_DIGESTSIZE, " "); + log_std(cd, "\n"); + log_std(cd, "MK salt: \t"); + hexprint(cd, cd->u.luks1.hdr.mkDigestSalt, LUKS_SALTSIZE/2, " "); + log_std(cd, "\n \t"); + hexprint(cd, cd->u.luks1.hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " "); + log_std(cd, "\n"); + log_std(cd, "MK iterations: \t%" PRIu32 "\n", cd->u.luks1.hdr.mkDigestIterations); + log_std(cd, "UUID: \t%s\n\n", cd->u.luks1.hdr.uuid); + for(i = 0; i < LUKS_NUMKEYS; i++) { + if(cd->u.luks1.hdr.keyblock[i].active == LUKS_KEY_ENABLED) { + log_std(cd, "Key Slot %d: ENABLED\n",i); + log_std(cd, "\tIterations: \t%" PRIu32 "\n", + cd->u.luks1.hdr.keyblock[i].passwordIterations); + log_std(cd, "\tSalt: \t"); + hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt, + LUKS_SALTSIZE/2, " "); + log_std(cd, "\n\t \t"); + hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt + + LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " "); + log_std(cd, "\n"); + + log_std(cd, "\tKey material offset:\t%" PRIu32 "\n", + cd->u.luks1.hdr.keyblock[i].keyMaterialOffset); + log_std(cd, "\tAF stripes: \t%" PRIu32 "\n", + cd->u.luks1.hdr.keyblock[i].stripes); + } + else + log_std(cd, "Key Slot %d: DISABLED\n", i); + } + return 0; +} + +static int _verity_dump(struct crypt_device *cd) +{ + log_std(cd, "VERITY header information for %s\n", mdata_device_path(cd)); + log_std(cd, "UUID: \t%s\n", cd->u.verity.uuid ?: ""); + log_std(cd, "Hash type: \t%u\n", cd->u.verity.hdr.hash_type); + log_std(cd, "Data blocks: \t%" PRIu64 "\n", cd->u.verity.hdr.data_size); + log_std(cd, "Data block size: \t%u\n", cd->u.verity.hdr.data_block_size); + log_std(cd, "Hash block size: \t%u\n", cd->u.verity.hdr.hash_block_size); + log_std(cd, "Hash algorithm: \t%s\n", cd->u.verity.hdr.hash_name); + log_std(cd, "Salt: \t"); + if (cd->u.verity.hdr.salt_size) + hexprint(cd, cd->u.verity.hdr.salt, cd->u.verity.hdr.salt_size, ""); + else + log_std(cd, "-"); + log_std(cd, "\n"); + if (cd->u.verity.root_hash) { + log_std(cd, "Root hash: \t"); + hexprint(cd, cd->u.verity.root_hash, cd->u.verity.root_hash_size, ""); + log_std(cd, "\n"); + } + return 0; +} + +int crypt_dump(struct crypt_device *cd) +{ + if (!cd) + return -EINVAL; + if (isLUKS1(cd->type)) + return _luks_dump(cd); + else if (isLUKS2(cd->type)) + return LUKS2_hdr_dump(cd, &cd->u.luks2.hdr); + else if (isVERITY(cd->type)) + return _verity_dump(cd); + else if (isTCRYPT(cd->type)) + return TCRYPT_dump(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + else if (isINTEGRITY(cd->type)) + return INTEGRITY_dump(cd, crypt_data_device(cd), 0); + else if (isBITLK(cd->type)) + return BITLK_dump(cd, crypt_data_device(cd), &cd->u.bitlk.params); + + log_err(cd, _("Dump operation is not supported for this device type.")); + return -EINVAL; +} + +/* internal only */ +const char *crypt_get_cipher_spec(struct crypt_device *cd) +{ + if (!cd) + return NULL; + else if (isLUKS2(cd->type)) + return LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + else if (isLUKS1(cd->type)) + return cd->u.luks1.cipher_spec; + else if (isPLAIN(cd->type)) + return cd->u.plain.cipher_spec; + else if (isLOOPAES(cd->type)) + return cd->u.loopaes.cipher_spec; + else if (isBITLK(cd->type)) + return cd->u.bitlk.cipher_spec; + else if (!cd->type && !_init_by_name_crypt_none(cd)) + return cd->u.none.cipher_spec; + + return NULL; +} + +const char *crypt_get_cipher(struct crypt_device *cd) +{ + if (!cd) + return NULL; + + if (isPLAIN(cd->type)) + return cd->u.plain.cipher; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.cipherName; + + if (isLUKS2(cd->type)) { + if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT), + cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode)) + return NULL; + return cd->u.luks2.cipher; + } + + if (isLOOPAES(cd->type)) + return cd->u.loopaes.cipher; + + if (isTCRYPT(cd->type)) + return cd->u.tcrypt.params.cipher; + + if (isBITLK(cd->type)) + return cd->u.bitlk.params.cipher; + + if (!cd->type && !_init_by_name_crypt_none(cd)) + return cd->u.none.cipher; + + return NULL; +} + +const char *crypt_get_cipher_mode(struct crypt_device *cd) +{ + if (!cd) + return NULL; + + if (isPLAIN(cd->type)) + return cd->u.plain.cipher_mode; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.cipherMode; + + if (isLUKS2(cd->type)) { + if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT), + cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode)) + return NULL; + return cd->u.luks2.cipher_mode; + } + + if (isLOOPAES(cd->type)) + return cd->u.loopaes.cipher_mode; + + if (isTCRYPT(cd->type)) + return cd->u.tcrypt.params.mode; + + if (isBITLK(cd->type)) + return cd->u.bitlk.params.cipher_mode; + + if (!cd->type && !_init_by_name_crypt_none(cd)) + return cd->u.none.cipher_mode; + + return NULL; +} + +/* INTERNAL only */ +const char *crypt_get_integrity(struct crypt_device *cd) +{ + if (isINTEGRITY(cd->type)) + return cd->u.integrity.params.integrity; + + if (isLUKS2(cd->type)) + return LUKS2_get_integrity(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + + return NULL; +} + +/* INTERNAL only */ +int crypt_get_integrity_key_size(struct crypt_device *cd) +{ + if (isINTEGRITY(cd->type)) + return INTEGRITY_key_size(cd, crypt_get_integrity(cd)); + + if (isLUKS2(cd->type)) + return INTEGRITY_key_size(cd, crypt_get_integrity(cd)); + + return 0; +} + +/* INTERNAL only */ +int crypt_get_integrity_tag_size(struct crypt_device *cd) +{ + if (isINTEGRITY(cd->type)) + return cd->u.integrity.params.tag_size; + + if (isLUKS2(cd->type)) + return INTEGRITY_tag_size(cd, crypt_get_integrity(cd), + crypt_get_cipher(cd), + crypt_get_cipher_mode(cd)); + return 0; +} + +int crypt_get_sector_size(struct crypt_device *cd) +{ + if (!cd) + return SECTOR_SIZE; + + if (isPLAIN(cd->type)) + return cd->u.plain.hdr.sector_size; + + if (isINTEGRITY(cd->type)) + return cd->u.integrity.params.sector_size; + + if (isLUKS2(cd->type)) + return LUKS2_get_sector_size(&cd->u.luks2.hdr); + + return SECTOR_SIZE; +} + +const char *crypt_get_uuid(struct crypt_device *cd) +{ + if (!cd) + return NULL; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.uuid; + + if (isLUKS2(cd->type)) + return cd->u.luks2.hdr.uuid; + + if (isVERITY(cd->type)) + return cd->u.verity.uuid; + + if (isBITLK(cd->type)) + return cd->u.bitlk.params.guid; + + return NULL; +} + +const char *crypt_get_device_name(struct crypt_device *cd) +{ + const char *path; + + if (!cd) + return NULL; + + path = device_block_path(cd->device); + if (!path) + path = device_path(cd->device); + + return path; +} + +const char *crypt_get_metadata_device_name(struct crypt_device *cd) +{ + const char *path; + + if (!cd || !cd->metadata_device) + return NULL; + + path = device_block_path(cd->metadata_device); + if (!path) + path = device_path(cd->metadata_device); + + return path; +} + +int crypt_get_volume_key_size(struct crypt_device *cd) +{ + int r; + + if (!cd) + return 0; + + if (isPLAIN(cd->type)) + return cd->u.plain.key_size; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.keyBytes; + + if (isLUKS2(cd->type)) { + r = LUKS2_get_volume_key_size(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + if (r < 0 && cd->volume_key) + r = cd->volume_key->keylength; + return r < 0 ? 0 : r; + } + + if (isLOOPAES(cd->type)) + return cd->u.loopaes.key_size; + + if (isVERITY(cd->type)) + return cd->u.verity.root_hash_size; + + if (isTCRYPT(cd->type)) + return cd->u.tcrypt.params.key_size; + + if (isBITLK(cd->type)) + return cd->u.bitlk.params.key_size / 8; + + if (!cd->type && !_init_by_name_crypt_none(cd)) + return cd->u.none.key_size; + + return 0; +} + +int crypt_keyslot_get_key_size(struct crypt_device *cd, int keyslot) +{ + if (!cd || !isLUKS(cd->type)) + return -EINVAL; + + if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type)) + return -EINVAL; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.keyBytes; + + if (isLUKS2(cd->type)) + return LUKS2_get_keyslot_stored_key_size(&cd->u.luks2.hdr, keyslot); + + return -EINVAL; +} + +int crypt_keyslot_set_encryption(struct crypt_device *cd, + const char *cipher, + size_t key_size) +{ + char *tmp; + + if (!cd || !cipher || ! key_size || !isLUKS2(cd->type)) + return -EINVAL; + + if (LUKS2_keyslot_cipher_incompatible(cd, cipher)) + return -EINVAL; + + tmp = strdup(cipher); + free(cd->u.luks2.keyslot_cipher); + cd->u.luks2.keyslot_cipher = tmp; + if (!cd->u.luks2.keyslot_cipher) + return -ENOMEM; + cd->u.luks2.keyslot_key_size = key_size; + + return 0; +} + +const char *crypt_keyslot_get_encryption(struct crypt_device *cd, int keyslot, size_t *key_size) +{ + const char *cipher; + + if (!cd || !isLUKS(cd->type) || !key_size) + return NULL; + + if (isLUKS1(cd->type)) { + if (keyslot != CRYPT_ANY_SLOT && + LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot) < CRYPT_SLOT_ACTIVE) + return NULL; + *key_size = crypt_get_volume_key_size(cd); + return cd->u.luks1.cipher_spec; + } + + if (keyslot != CRYPT_ANY_SLOT) + return LUKS2_get_keyslot_cipher(&cd->u.luks2.hdr, keyslot, key_size); + + /* Keyslot encryption was set through crypt_keyslot_set_encryption() */ + if (cd->u.luks2.keyslot_cipher) { + *key_size = cd->u.luks2.keyslot_key_size; + return cd->u.luks2.keyslot_cipher; + } + + /* Try to reuse volume encryption parameters */ + cipher = LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + if (!LUKS2_keyslot_cipher_incompatible(cd, cipher)) { + *key_size = crypt_get_volume_key_size(cd); + if (*key_size) + return cipher; + } + + /* Fallback to default LUKS2 keyslot encryption */ + *key_size = DEFAULT_LUKS2_KEYSLOT_KEYBITS / 8; + return DEFAULT_LUKS2_KEYSLOT_CIPHER; +} + +int crypt_keyslot_get_pbkdf(struct crypt_device *cd, int keyslot, struct crypt_pbkdf_type *pbkdf) +{ + if (!cd || !pbkdf || keyslot == CRYPT_ANY_SLOT) + return -EINVAL; + + if (isLUKS1(cd->type)) + return LUKS_keyslot_pbkdf(&cd->u.luks1.hdr, keyslot, pbkdf); + else if (isLUKS2(cd->type)) + return LUKS2_keyslot_pbkdf(&cd->u.luks2.hdr, keyslot, pbkdf); + + return -EINVAL; +} + +int crypt_set_data_offset(struct crypt_device *cd, uint64_t data_offset) +{ + if (!cd) + return -EINVAL; + if (data_offset % (MAX_SECTOR_SIZE >> SECTOR_SHIFT)) { + log_err(cd, _("Data offset is not multiple of %u bytes."), MAX_SECTOR_SIZE); + return -EINVAL; + } + + cd->data_offset = data_offset; + log_dbg(cd, "Data offset set to %" PRIu64 " (512-byte) sectors.", data_offset); + + return 0; +} + +int crypt_set_metadata_size(struct crypt_device *cd, + uint64_t metadata_size, + uint64_t keyslots_size) +{ + if (!cd) + return -EINVAL; + + if (cd->type && !isLUKS2(cd->type)) + return -EINVAL; + + if (metadata_size && LUKS2_check_metadata_area_size(metadata_size)) + return -EINVAL; + + if (keyslots_size && LUKS2_check_keyslots_area_size(keyslots_size)) + return -EINVAL; + + cd->metadata_size = metadata_size; + cd->keyslots_size = keyslots_size; + + return 0; +} + +int crypt_get_metadata_size(struct crypt_device *cd, + uint64_t *metadata_size, + uint64_t *keyslots_size) +{ + uint64_t msize, ksize; + + if (!cd) + return -EINVAL; + + if (!cd->type) { + msize = cd->metadata_size; + ksize = cd->keyslots_size; + } else if (isLUKS1(cd->type)) { + msize = LUKS_ALIGN_KEYSLOTS; + ksize = LUKS_device_sectors(&cd->u.luks1.hdr) * SECTOR_SIZE - msize; + } else if (isLUKS2(cd->type)) { + msize = LUKS2_metadata_size(cd->u.luks2.hdr.jobj); + ksize = LUKS2_keyslots_size(cd->u.luks2.hdr.jobj); } else - log_err(cd, _("Device type is not properly initialised.\n")); + return -EINVAL; + + if (metadata_size) + *metadata_size = msize; + if (keyslots_size) + *keyslots_size = ksize; + + return 0; +} + +uint64_t crypt_get_data_offset(struct crypt_device *cd) +{ + if (!cd) + return 0; + + if (isPLAIN(cd->type)) + return cd->u.plain.hdr.offset; + + if (isLUKS1(cd->type)) + return cd->u.luks1.hdr.payloadOffset; + + if (isLUKS2(cd->type)) + return LUKS2_get_data_offset(&cd->u.luks2.hdr); + + if (isLOOPAES(cd->type)) + return cd->u.loopaes.hdr.offset; + + if (isTCRYPT(cd->type)) + return TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + + if (isBITLK(cd->type)) + return cd->u.bitlk.params.volume_header_size / SECTOR_SIZE; + + return cd->data_offset; +} + +uint64_t crypt_get_iv_offset(struct crypt_device *cd) +{ + if (!cd) + return 0; + + if (isPLAIN(cd->type)) + return cd->u.plain.hdr.skip; + + if (isLOOPAES(cd->type)) + return cd->u.loopaes.hdr.skip; + + if (isTCRYPT(cd->type)) + return TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + + return 0; +} + +crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot) +{ + if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED) < 0) + return CRYPT_SLOT_INVALID; + + if (isLUKS1(cd->type)) + return LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot); + else if(isLUKS2(cd->type)) + return LUKS2_keyslot_info(&cd->u.luks2.hdr, keyslot); + + return CRYPT_SLOT_INVALID; +} + +int crypt_keyslot_max(const char *type) +{ + if (type && isLUKS1(type)) + return LUKS_NUMKEYS; + + if (type && isLUKS2(type)) + return LUKS2_KEYSLOTS_MAX; + + return -EINVAL; +} + +int crypt_keyslot_area(struct crypt_device *cd, + int keyslot, + uint64_t *offset, + uint64_t *length) +{ + if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED) || !offset || !length) + return -EINVAL; + + if (isLUKS2(cd->type)) + return LUKS2_keyslot_area(&cd->u.luks2.hdr, keyslot, offset, length); + + return LUKS_keyslot_area(&cd->u.luks1.hdr, keyslot, offset, length); +} + +crypt_keyslot_priority crypt_keyslot_get_priority(struct crypt_device *cd, int keyslot) +{ + if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED)) + return CRYPT_SLOT_PRIORITY_INVALID; + + if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type)) + return CRYPT_SLOT_PRIORITY_INVALID; + + if (isLUKS2(cd->type)) + return LUKS2_keyslot_priority_get(cd, &cd->u.luks2.hdr, keyslot); + + return CRYPT_SLOT_PRIORITY_NORMAL; +} + +int crypt_keyslot_set_priority(struct crypt_device *cd, int keyslot, crypt_keyslot_priority priority) +{ + int r; + + log_dbg(cd, "Setting keyslot %d to priority %d.", keyslot, priority); - crypt_free_volume_key(vk); + if (priority == CRYPT_SLOT_PRIORITY_INVALID) + return -EINVAL; - return r; + if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type)) + return -EINVAL; + + if ((r = onlyLUKS2(cd))) + return r; + + return LUKS2_keyslot_priority_set(cd, &cd->u.luks2.hdr, keyslot, priority, 1); } -int crypt_deactivate(struct crypt_device *cd, const char *name) +const char *crypt_get_type(struct crypt_device *cd) { - struct crypt_device *fake_cd = NULL; - int r; + return cd ? cd->type : NULL; +} - if (!name) +const char *crypt_get_default_type(void) +{ + return DEFAULT_LUKS_FORMAT; +} + +int crypt_get_verity_info(struct crypt_device *cd, + struct crypt_params_verity *vp) +{ + if (!cd || !isVERITY(cd->type) || !vp) return -EINVAL; - log_dbg("Deactivating volume %s.", name); + vp->data_device = device_path(cd->device); + vp->hash_device = mdata_device_path(cd); + vp->fec_device = device_path(cd->u.verity.fec_device); + vp->fec_area_offset = cd->u.verity.hdr.fec_area_offset; + vp->fec_roots = cd->u.verity.hdr.fec_roots; + vp->hash_name = cd->u.verity.hdr.hash_name; + vp->salt = cd->u.verity.hdr.salt; + vp->salt_size = cd->u.verity.hdr.salt_size; + vp->data_block_size = cd->u.verity.hdr.data_block_size; + vp->hash_block_size = cd->u.verity.hdr.hash_block_size; + vp->data_size = cd->u.verity.hdr.data_size; + vp->hash_area_offset = cd->u.verity.hdr.hash_area_offset; + vp->hash_type = cd->u.verity.hdr.hash_type; + vp->flags = cd->u.verity.hdr.flags & (CRYPT_VERITY_NO_HEADER | CRYPT_VERITY_ROOT_HASH_SIGNATURE); + return 0; +} - if (!cd) { - r = crypt_init_by_name(&fake_cd, name); - if (r < 0) - return r; - cd = fake_cd; - } +int crypt_get_integrity_info(struct crypt_device *cd, + struct crypt_params_integrity *ip) +{ + if (!cd || !ip) + return -EINVAL; - switch (crypt_status(cd, name)) { - case CRYPT_ACTIVE: - case CRYPT_BUSY: - if (isTCRYPT(cd->type)) - r = TCRYPT_deactivate(cd, name); - else - r = dm_remove_device(cd, name, 0, 0); - if (r < 0 && crypt_status(cd, name) == CRYPT_BUSY) { - log_err(cd, _("Device %s is still in use.\n"), name); - r = -EBUSY; - } - break; - case CRYPT_INACTIVE: - log_err(cd, _("Device %s is not active.\n"), name); - r = -ENODEV; - break; - default: - log_err(cd, _("Invalid device %s.\n"), name); - r = -EINVAL; + if (isINTEGRITY(cd->type)) { + ip->journal_size = cd->u.integrity.params.journal_size; + ip->journal_watermark = cd->u.integrity.params.journal_watermark; + ip->journal_commit_time = cd->u.integrity.params.journal_commit_time; + ip->interleave_sectors = cd->u.integrity.params.interleave_sectors; + ip->tag_size = cd->u.integrity.params.tag_size; + ip->sector_size = cd->u.integrity.params.sector_size; + ip->buffer_sectors = cd->u.integrity.params.buffer_sectors; + + ip->integrity = cd->u.integrity.params.integrity; + ip->integrity_key_size = crypt_get_integrity_key_size(cd); + + ip->journal_integrity = cd->u.integrity.params.journal_integrity; + ip->journal_integrity_key_size = cd->u.integrity.params.journal_integrity_key_size; + ip->journal_integrity_key = NULL; + + ip->journal_crypt = cd->u.integrity.params.journal_crypt; + ip->journal_crypt_key_size = cd->u.integrity.params.journal_crypt_key_size; + ip->journal_crypt_key = NULL; + return 0; + } else if (isLUKS2(cd->type)) { + ip->journal_size = 0; // FIXME + ip->journal_watermark = 0; // FIXME + ip->journal_commit_time = 0; // FIXME + ip->interleave_sectors = 0; // FIXME + ip->sector_size = crypt_get_sector_size(cd); + ip->buffer_sectors = 0; // FIXME + + ip->integrity = LUKS2_get_integrity(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); + ip->integrity_key_size = crypt_get_integrity_key_size(cd); + ip->tag_size = INTEGRITY_tag_size(cd, ip->integrity, crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); + + ip->journal_integrity = NULL; + ip->journal_integrity_key_size = 0; + ip->journal_integrity_key = NULL; + + ip->journal_crypt = NULL; + ip->journal_crypt_key_size = 0; + ip->journal_crypt_key = NULL; + return 0; } - crypt_free(fake_cd); - - return r; + return -ENOTSUP; } -int crypt_volume_key_get(struct crypt_device *cd, - int keyslot, - char *volume_key, - size_t *volume_key_size, - const char *passphrase, - size_t passphrase_size) +int crypt_convert(struct crypt_device *cd, + const char *type, + void *params) { - struct volume_key *vk = NULL; - unsigned key_len; - int r = -EINVAL; + struct luks_phdr hdr1; + struct luks2_hdr hdr2; + int r; - if (crypt_fips_mode()) { - log_err(cd, _("Function not available in FIPS mode.\n")); - return -EACCES; - } + if (!type) + return -EINVAL; - key_len = crypt_get_volume_key_size(cd); - if (key_len > *volume_key_size) { - log_err(cd, _("Volume key buffer too small.\n")); - return -ENOMEM; - } + log_dbg(cd, "Converting LUKS device to type %s", type); - if (isPLAIN(cd->type) && cd->u.plain.hdr.hash) { - r = process_key(cd, cd->u.plain.hdr.hash, key_len, - passphrase, passphrase_size, &vk); - if (r < 0) - log_err(cd, _("Cannot retrieve volume key for plain device.\n")); - } else if (isLUKS(cd->type)) { - r = LUKS_open_key_with_hdr(keyslot, passphrase, - passphrase_size, &cd->u.luks1.hdr, &vk, cd); - } else if (isTCRYPT(cd->type)) { - r = TCRYPT_get_volume_key(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, &vk); - } else - log_err(cd, _("This operation is not supported for %s crypt device.\n"), cd->type ?: "(none)"); + if ((r = onlyLUKS(cd))) + return r; - if (r >= 0) { - memcpy(volume_key, vk->key, vk->keylength); - *volume_key_size = vk->keylength; + if (isLUKS1(cd->type) && isLUKS2(type)) + r = LUKS2_luks1_to_luks2(cd, &cd->u.luks1.hdr, &hdr2); + else if (isLUKS2(cd->type) && isLUKS1(type)) + r = LUKS2_luks2_to_luks1(cd, &cd->u.luks2.hdr, &hdr1); + else + return -EINVAL; + + if (r < 0) { + /* in-memory header may be invalid after failed conversion */ + _luks2_reload(cd); + if (r == -EBUSY) + log_err(cd, _("Cannot convert device %s which is still in use."), mdata_device_path(cd)); + return r; } - crypt_free_volume_key(vk); - return r; + crypt_free_type(cd); + + return crypt_load(cd, type, params); } -int crypt_volume_key_verify(struct crypt_device *cd, - const char *volume_key, - size_t volume_key_size) +/* Internal access function to header pointer */ +void *crypt_get_hdr(struct crypt_device *cd, const char *type) { - struct volume_key *vk; - int r; + /* If requested type differs, ignore it */ + if (strcmp(cd->type, type)) + return NULL; - r = onlyLUKS(cd); - if (r < 0) - return r; + if (isPLAIN(cd->type)) + return &cd->u.plain; - vk = crypt_alloc_volume_key(volume_key_size, volume_key); - if (!vk) - return -ENOMEM; + if (isLUKS1(cd->type)) + return &cd->u.luks1.hdr; - r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk); + if (isLUKS2(cd->type)) + return &cd->u.luks2.hdr; - if (r == -EPERM) - log_err(cd, _("Volume key does not match the volume.\n")); + if (isLOOPAES(cd->type)) + return &cd->u.loopaes; - crypt_free_volume_key(vk); + if (isVERITY(cd->type)) + return &cd->u.verity; - return r; + if (isTCRYPT(cd->type)) + return &cd->u.tcrypt; + + return NULL; } -void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec) +/* internal only */ +struct luks2_reenc_context *crypt_get_reenc_context(struct crypt_device *cd) { - log_dbg("Timeout set to %" PRIu64 " miliseconds.", timeout_sec); - cd->timeout = timeout_sec; + return cd->u.luks2.rh; } -void crypt_set_password_retry(struct crypt_device *cd, int tries) +/* internal only */ +void crypt_set_reenc_context(struct crypt_device *cd, struct luks2_reenc_context *rh) { - log_dbg("Password retry count set to %d.", tries); - cd->tries = tries; + cd->u.luks2.rh = rh; } -void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms) +/* + * Token handling + */ +int crypt_activate_by_token(struct crypt_device *cd, + const char *name, int token, void *usrptr, uint32_t flags) { - log_dbg("Iteration time set to %" PRIu64 " miliseconds.", iteration_time_ms); - cd->iteration_time = iteration_time_ms; + int r; + + log_dbg(cd, "%s volume %s using token %d.", + name ? "Activating" : "Checking", name ?: "passphrase", token); + + if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0))) + return r; + + if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)) + return -EINVAL; + + if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name) + return -EINVAL; + + if (token == CRYPT_ANY_TOKEN) + return LUKS2_token_open_and_activate_any(cd, &cd->u.luks2.hdr, name, flags); + + return LUKS2_token_open_and_activate(cd, &cd->u.luks2.hdr, token, name, flags, usrptr); } -void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms) + +int crypt_token_json_get(struct crypt_device *cd, int token, const char **json) { - crypt_set_iteration_time(cd, iteration_time_ms); + int r; + + if (!json) + return -EINVAL; + + log_dbg(cd, "Requesting JSON for token %d.", token); + + if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0))) + return r; + + return LUKS2_token_json_get(cd, &cd->u.luks2.hdr, token, json) ?: token; } -void crypt_set_password_verify(struct crypt_device *cd, int password_verify) +int crypt_token_json_set(struct crypt_device *cd, int token, const char *json) { - log_dbg("Password verification %s.", password_verify ? "enabled" : "disabled"); - cd->password_verify = password_verify ? 1 : 0; + int r; + + log_dbg(cd, "Updating JSON for token %d.", token); + + if ((r = onlyLUKS2(cd))) + return r; + + return LUKS2_token_create(cd, &cd->u.luks2.hdr, token, json, 1); } -void crypt_set_rng_type(struct crypt_device *cd, int rng_type) +crypt_token_info crypt_token_status(struct crypt_device *cd, int token, const char **type) { - switch (rng_type) { - case CRYPT_RNG_URANDOM: - case CRYPT_RNG_RANDOM: - log_dbg("RNG set to %d (%s).", rng_type, rng_type ? "random" : "urandom"); - cd->rng_type = rng_type; - } + if (_onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0)) + return CRYPT_TOKEN_INVALID; + + return LUKS2_token_status(cd, &cd->u.luks2.hdr, token, type); } -int crypt_get_rng_type(struct crypt_device *cd) +int crypt_token_luks2_keyring_get(struct crypt_device *cd, + int token, + struct crypt_token_params_luks2_keyring *params) { - if (!cd) + crypt_token_info token_info; + const char *type; + int r; + + if (!params) return -EINVAL; - return cd->rng_type; -} + log_dbg(cd, "Requesting LUKS2 keyring token %d.", token); -int crypt_memory_lock(struct crypt_device *cd, int lock) -{ - return lock ? crypt_memlock_inc(cd) : crypt_memlock_dec(cd); + if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0))) + return r; + + token_info = LUKS2_token_status(cd, &cd->u.luks2.hdr, token, &type); + switch (token_info) { + case CRYPT_TOKEN_INVALID: + log_dbg(cd, "Token %d is invalid.", token); + return -EINVAL; + case CRYPT_TOKEN_INACTIVE: + log_dbg(cd, "Token %d is inactive.", token); + return -EINVAL; + case CRYPT_TOKEN_INTERNAL: + if (!strcmp(type, LUKS2_TOKEN_KEYRING)) + break; + /* Fall through */ + case CRYPT_TOKEN_INTERNAL_UNKNOWN: + case CRYPT_TOKEN_EXTERNAL: + case CRYPT_TOKEN_EXTERNAL_UNKNOWN: + log_dbg(cd, "Token %d has unexpected type %s.", token, type); + return -EINVAL; + } + + return LUKS2_builtin_token_get(cd, &cd->u.luks2.hdr, token, LUKS2_TOKEN_KEYRING, params); } -// reporting -crypt_status_info crypt_status(struct crypt_device *cd, const char *name) +int crypt_token_luks2_keyring_set(struct crypt_device *cd, + int token, + const struct crypt_token_params_luks2_keyring *params) { int r; - if (!cd) - dm_backend_init(); + if (!params) + return -EINVAL; - r = dm_status_device(cd, name); + log_dbg(cd, "Creating new LUKS2 keyring token (%d).", token); - if (!cd) - dm_backend_exit(); + if ((r = onlyLUKS2(cd))) + return r; - if (r < 0 && r != -ENODEV) - return CRYPT_INVALID; + return LUKS2_builtin_token_create(cd, &cd->u.luks2.hdr, token, LUKS2_TOKEN_KEYRING, params, 1); +} - if (r == 0) - return CRYPT_ACTIVE; +int crypt_token_assign_keyslot(struct crypt_device *cd, int token, int keyslot) +{ + int r; - if (r > 0) - return CRYPT_BUSY; + if ((r = onlyLUKS2(cd))) + return r; - return CRYPT_INACTIVE; + return LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot, token, 1, 1); } -static void hexprint(struct crypt_device *cd, const char *d, int n, const char *sep) +int crypt_token_unassign_keyslot(struct crypt_device *cd, int token, int keyslot) { - int i; - for(i = 0; i < n; i++) - log_std(cd, "%02hhx%s", (const char)d[i], sep); + int r; + + if ((r = onlyLUKS2(cd))) + return r; + + return LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot, token, 0, 1); } -static int _luks_dump(struct crypt_device *cd) +int crypt_token_is_assigned(struct crypt_device *cd, int token, int keyslot) { - int i; + int r; - log_std(cd, "LUKS header information for %s\n\n", mdata_device_path(cd)); - log_std(cd, "Version: \t%" PRIu16 "\n", cd->u.luks1.hdr.version); - log_std(cd, "Cipher name: \t%s\n", cd->u.luks1.hdr.cipherName); - log_std(cd, "Cipher mode: \t%s\n", cd->u.luks1.hdr.cipherMode); - log_std(cd, "Hash spec: \t%s\n", cd->u.luks1.hdr.hashSpec); - log_std(cd, "Payload offset:\t%" PRIu32 "\n", cd->u.luks1.hdr.payloadOffset); - log_std(cd, "MK bits: \t%" PRIu32 "\n", cd->u.luks1.hdr.keyBytes * 8); - log_std(cd, "MK digest: \t"); - hexprint(cd, cd->u.luks1.hdr.mkDigest, LUKS_DIGESTSIZE, " "); - log_std(cd, "\n"); - log_std(cd, "MK salt: \t"); - hexprint(cd, cd->u.luks1.hdr.mkDigestSalt, LUKS_SALTSIZE/2, " "); - log_std(cd, "\n \t"); - hexprint(cd, cd->u.luks1.hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " "); - log_std(cd, "\n"); - log_std(cd, "MK iterations: \t%" PRIu32 "\n", cd->u.luks1.hdr.mkDigestIterations); - log_std(cd, "UUID: \t%s\n\n", cd->u.luks1.hdr.uuid); - for(i = 0; i < LUKS_NUMKEYS; i++) { - if(cd->u.luks1.hdr.keyblock[i].active == LUKS_KEY_ENABLED) { - log_std(cd, "Key Slot %d: ENABLED\n",i); - log_std(cd, "\tIterations: \t%" PRIu32 "\n", - cd->u.luks1.hdr.keyblock[i].passwordIterations); - log_std(cd, "\tSalt: \t"); - hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt, - LUKS_SALTSIZE/2, " "); - log_std(cd, "\n\t \t"); - hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt + - LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " "); - log_std(cd, "\n"); + if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0))) + return r; - log_std(cd, "\tKey material offset:\t%" PRIu32 "\n", - cd->u.luks1.hdr.keyblock[i].keyMaterialOffset); - log_std(cd, "\tAF stripes: \t%" PRIu32 "\n", - cd->u.luks1.hdr.keyblock[i].stripes); - } - else - log_std(cd, "Key Slot %d: DISABLED\n", i); - } - return 0; + return LUKS2_token_is_assigned(cd, &cd->u.luks2.hdr, keyslot, token); } -static int _verity_dump(struct crypt_device *cd) +/* Internal only */ +int crypt_metadata_locking_enabled(void) { - log_std(cd, "VERITY header information for %s\n", mdata_device_path(cd)); - log_std(cd, "UUID: \t%s\n", cd->u.verity.uuid ?: ""); - log_std(cd, "Hash type: \t%u\n", cd->u.verity.hdr.hash_type); - log_std(cd, "Data blocks: \t%" PRIu64 "\n", cd->u.verity.hdr.data_size); - log_std(cd, "Data block size: \t%u\n", cd->u.verity.hdr.data_block_size); - log_std(cd, "Hash block size: \t%u\n", cd->u.verity.hdr.hash_block_size); - log_std(cd, "Hash algorithm: \t%s\n", cd->u.verity.hdr.hash_name); - log_std(cd, "Salt: \t"); - if (cd->u.verity.hdr.salt_size) - hexprint(cd, cd->u.verity.hdr.salt, cd->u.verity.hdr.salt_size, ""); - else - log_std(cd, "-"); - log_std(cd, "\n"); - if (cd->u.verity.root_hash) { - log_std(cd, "Root hash: \t"); - hexprint(cd, cd->u.verity.root_hash, cd->u.verity.root_hash_size, ""); - log_std(cd, "\n"); - } + return _metadata_locking; +} + +int crypt_metadata_locking(struct crypt_device *cd, int enable) +{ + if (enable && !_metadata_locking) + return -EPERM; + + _metadata_locking = enable ? 1 : 0; return 0; } -int crypt_dump(struct crypt_device *cd) +int crypt_persistent_flags_set(struct crypt_device *cd, crypt_flags_type type, uint32_t flags) { - if (isLUKS(cd->type)) - return _luks_dump(cd); - else if (isVERITY(cd->type)) - return _verity_dump(cd); - else if (isTCRYPT(cd->type)) - return TCRYPT_dump(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + int r; + + if ((r = onlyLUKS2(cd))) + return r; + + if (type == CRYPT_FLAGS_ACTIVATION) + return LUKS2_config_set_flags(cd, &cd->u.luks2.hdr, flags); + + if (type == CRYPT_FLAGS_REQUIREMENTS) + return LUKS2_config_set_requirements(cd, &cd->u.luks2.hdr, flags, true); - log_err(cd, _("Dump operation is not supported for this device type.\n")); return -EINVAL; } - -static int _init_by_name_crypt_none(struct crypt_device *cd) +int crypt_persistent_flags_get(struct crypt_device *cd, crypt_flags_type type, uint32_t *flags) { - struct crypt_dm_active_device dmd = {}; int r; - if (cd->type || !cd->u.none.active_name) + if (!flags) return -EINVAL; - r = dm_query_device(cd, cd->u.none.active_name, - DM_ACTIVE_CRYPT_CIPHER | - DM_ACTIVE_CRYPT_KEYSIZE, &dmd); - if (r >= 0) - r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, - cd->u.none.cipher, NULL, - cd->u.none.cipher_mode); + if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0))) + return r; - if (!r) - cd->u.none.key_size = dmd.u.crypt.vk->keylength; + if (type == CRYPT_FLAGS_ACTIVATION) + return LUKS2_config_get_flags(cd, &cd->u.luks2.hdr, flags); - crypt_free_volume_key(dmd.u.crypt.vk); - free(CONST_CAST(void*)dmd.u.crypt.cipher); - return r; + if (type == CRYPT_FLAGS_REQUIREMENTS) + return LUKS2_config_get_requirements(cd, &cd->u.luks2.hdr, flags); + + return -EINVAL; } -const char *crypt_get_cipher(struct crypt_device *cd) +static int update_volume_key_segment_digest(struct crypt_device *cd, struct luks2_hdr *hdr, int digest, int commit) { - if (isPLAIN(cd->type)) - return cd->u.plain.cipher; - - if (isLUKS(cd->type)) - return cd->u.luks1.hdr.cipherName; - - if (isLOOPAES(cd->type)) - return cd->u.loopaes.cipher; - - if (isTCRYPT(cd->type)) - return cd->u.tcrypt.params.cipher; + int r; - if (!cd->type && !_init_by_name_crypt_none(cd)) - return cd->u.none.cipher; + /* Remove any assignments in memory */ + r = LUKS2_digest_segment_assign(cd, hdr, CRYPT_DEFAULT_SEGMENT, CRYPT_ANY_DIGEST, 0, 0); + if (r) + return r; - return NULL; + /* Assign it to the specific digest */ + return LUKS2_digest_segment_assign(cd, hdr, CRYPT_DEFAULT_SEGMENT, digest, 1, commit); } -const char *crypt_get_cipher_mode(struct crypt_device *cd) +static int verify_and_update_segment_digest(struct crypt_device *cd, + struct luks2_hdr *hdr, int keyslot, + const char *volume_key, size_t volume_key_size, + const char *password, size_t password_size) { - if (isPLAIN(cd->type)) - return cd->u.plain.cipher_mode; - - if (isLUKS(cd->type)) - return cd->u.luks1.hdr.cipherMode; + int digest, r; + struct volume_key *vk = NULL; - if (isLOOPAES(cd->type)) - return cd->u.loopaes.cipher_mode; + if (keyslot < 0 || (volume_key && !volume_key_size)) + return -EINVAL; - if (isTCRYPT(cd->type)) - return cd->u.tcrypt.params.mode; + if (volume_key) + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + else { + r = LUKS2_keyslot_open(cd, keyslot, CRYPT_ANY_SEGMENT, password, password_size, &vk); + if (r != keyslot) { + r = -EINVAL; + goto out; + } + } - if (!cd->type && !_init_by_name_crypt_none(cd)) - return cd->u.none.cipher_mode; + if (!vk) + return -ENOMEM; - return NULL; -} + /* check volume_key (param) digest matches keyslot digest */ + r = LUKS2_digest_verify(cd, hdr, vk, keyslot); + if (r < 0) + goto out; + digest = r; -const char *crypt_get_uuid(struct crypt_device *cd) -{ - if (isLUKS(cd->type)) - return cd->u.luks1.hdr.uuid; + /* nothing to do, volume key in keyslot is already assigned to default segment */ + r = LUKS2_digest_verify_by_segment(cd, hdr, CRYPT_DEFAULT_SEGMENT, vk); + if (r >= 0) + goto out; - if (isVERITY(cd->type)) - return cd->u.verity.uuid; + /* FIXME: check new volume key is usable with current default segment */ - return NULL; + r = update_volume_key_segment_digest(cd, &cd->u.luks2.hdr, digest, 1); + if (r) + log_err(cd, _("Failed to assign keyslot %u as the new volume key."), keyslot); +out: + crypt_free_volume_key(vk); + return r < 0 ? r : keyslot; } -const char *crypt_get_device_name(struct crypt_device *cd) + +int crypt_keyslot_add_by_key(struct crypt_device *cd, + int keyslot, + const char *volume_key, + size_t volume_key_size, + const char *passphrase, + size_t passphrase_size, + uint32_t flags) { - const char *path = device_block_path(cd->device); + int digest, r; + struct luks2_keyslot_params params; + struct volume_key *vk = NULL; - if (!path) - path = device_path(cd->device); + if (!passphrase || ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) && + (flags & CRYPT_VOLUME_KEY_SET))) + return -EINVAL; - return path; -} + log_dbg(cd, "Adding new keyslot %d with volume key %sassigned to a crypt segment.", + keyslot, flags & CRYPT_VOLUME_KEY_NO_SEGMENT ? "un" : ""); -int crypt_get_volume_key_size(struct crypt_device *cd) -{ - if (isPLAIN(cd->type)) - return cd->u.plain.key_size; + if ((r = onlyLUKS2(cd))) + return r; - if (isLUKS(cd->type)) - return cd->u.luks1.hdr.keyBytes; + /* new volume key assignment */ + if ((flags & CRYPT_VOLUME_KEY_SET) && crypt_keyslot_status(cd, keyslot) > CRYPT_SLOT_INACTIVE) + return verify_and_update_segment_digest(cd, &cd->u.luks2.hdr, + keyslot, volume_key, volume_key_size, passphrase, passphrase_size); - if (isLOOPAES(cd->type)) - return cd->u.loopaes.key_size; + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r < 0) + return r; - if (isVERITY(cd->type)) - return cd->u.verity.root_hash_size; + if (volume_key) + vk = crypt_alloc_volume_key(volume_key_size, volume_key); + else if (flags & CRYPT_VOLUME_KEY_NO_SEGMENT) + vk = crypt_generate_volume_key(cd, volume_key_size); + else if (cd->volume_key) + vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key); + else + return -EINVAL; - if (isTCRYPT(cd->type)) - return cd->u.tcrypt.params.key_size; + if (!vk) + return -ENOMEM; - if (!cd->type && !_init_by_name_crypt_none(cd)) - return cd->u.none.key_size; + /* if key matches volume key digest tear down new vk flag */ + digest = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk); + if (digest >= 0) + flags &= ~CRYPT_VOLUME_KEY_SET; - return 0; -} + /* if key matches any existing digest, do not create new digest */ + if (digest < 0 && (flags & CRYPT_VOLUME_KEY_DIGEST_REUSE)) + digest = LUKS2_digest_any_matching(cd, &cd->u.luks2.hdr, vk); -uint64_t crypt_get_data_offset(struct crypt_device *cd) -{ - if (isPLAIN(cd->type)) - return cd->u.plain.hdr.offset; + /* no segment flag or new vk flag requires new key digest */ + if (flags & (CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET)) { + if (digest < 0 || !(flags & CRYPT_VOLUME_KEY_DIGEST_REUSE)) + digest = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk); + } - if (isLUKS(cd->type)) - return cd->u.luks1.hdr.payloadOffset; + r = digest; + if (r < 0) { + log_err(cd, _("Volume key does not match the volume.")); + goto out; + } - if (isLOOPAES(cd->type)) - return cd->u.loopaes.hdr.offset; + r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, ¶ms); + if (r < 0) { + log_err(cd, _("Failed to initialize default LUKS2 keyslot parameters.")); + goto out; + } - if (isTCRYPT(cd->type)) - return TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0); + if (r < 0) { + log_err(cd, _("Failed to assign keyslot %d to digest."), keyslot); + goto out; + } - return 0; + r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot, + passphrase, passphrase_size, vk, ¶ms); + + if (r >= 0 && (flags & CRYPT_VOLUME_KEY_SET)) + r = update_volume_key_segment_digest(cd, &cd->u.luks2.hdr, digest, 1); +out: + crypt_free_volume_key(vk); + if (r < 0) { + _luks2_reload(cd); + return r; + } + return keyslot; } -uint64_t crypt_get_iv_offset(struct crypt_device *cd) +/* + * Keyring handling + */ + +int crypt_use_keyring_for_vk(struct crypt_device *cd) { - if (isPLAIN(cd->type)) - return cd->u.plain.hdr.skip; + uint32_t dmc_flags; - if (isLUKS(cd->type)) + /* dm backend must be initialized */ + if (!cd || !isLUKS2(cd->type)) return 0; - if (isLOOPAES(cd->type)) - return cd->u.loopaes.hdr.skip; + if (!_vk_via_keyring || !kernel_keyring_support()) + return 0; - if (isTCRYPT(cd->type)) - return TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); + if (dm_flags(cd, DM_CRYPT, &dmc_flags)) + return dmcrypt_keyring_bug() ? 0 : 1; + + return (dmc_flags & DM_KERNEL_KEYRING_SUPPORTED); +} +int crypt_volume_key_keyring(struct crypt_device *cd, int enable) +{ + _vk_via_keyring = enable ? 1 : 0; return 0; } -crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot) +/* internal only */ +int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk) { - if (onlyLUKS(cd) < 0) - return CRYPT_SLOT_INVALID; + int r; + const char *type_name = key_type_name(LOGON_KEY); + + if (!vk || !cd || !type_name) + return -EINVAL; + + if (!vk->key_description) { + log_dbg(cd, "Invalid key description"); + return -EINVAL; + } + + log_dbg(cd, "Loading key (%zu bytes, type %s) in thread keyring.", vk->keylength, type_name); + + r = keyring_add_key_in_thread_keyring(LOGON_KEY, vk->key_description, vk->key, vk->keylength); + if (r) { + log_dbg(cd, "keyring_add_key_in_thread_keyring failed (error %d)", r); + log_err(cd, _("Failed to load key in kernel keyring.")); + } else + crypt_set_key_in_keyring(cd, 1); - return LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot); + return r; } -int crypt_keyslot_max(const char *type) +/* internal only */ +int crypt_key_in_keyring(struct crypt_device *cd) { - if (type && isLUKS(type)) - return LUKS_NUMKEYS; - - return -EINVAL; + return cd ? cd->key_in_keyring : 0; } -int crypt_keyslot_area(struct crypt_device *cd, - int keyslot, - uint64_t *offset, - uint64_t *length) +/* internal only */ +void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring) { - if (!isLUKS(cd->type)) - return -EINVAL; + if (!cd) + return; - return LUKS_keyslot_area(&cd->u.luks1.hdr, keyslot, offset, length); + cd->key_in_keyring = key_in_keyring; } -const char *crypt_get_type(struct crypt_device *cd) +/* internal only */ +void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype) { - return cd->type; + int r; + const char *type_name = key_type_name(ktype); + + if (!key_description || !type_name) + return; + + log_dbg(cd, "Requesting keyring %s key for revoke and unlink.", type_name); + + r = keyring_revoke_and_unlink_key(ktype, key_description); + if (r) + log_dbg(cd, "keyring_revoke_and_unlink_key failed (error %d)", r); + crypt_set_key_in_keyring(cd, 0); } -int crypt_get_verity_info(struct crypt_device *cd, - struct crypt_params_verity *vp) +/* internal only */ +void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks) { - if (!isVERITY(cd->type) || !vp) - return -EINVAL; + struct volume_key *vk = vks; - vp->data_device = device_path(cd->device); - vp->hash_device = mdata_device_path(cd); - vp->hash_name = cd->u.verity.hdr.hash_name; - vp->salt = cd->u.verity.hdr.salt; - vp->salt_size = cd->u.verity.hdr.salt_size; - vp->data_block_size = cd->u.verity.hdr.data_block_size; - vp->hash_block_size = cd->u.verity.hdr.hash_block_size; - vp->data_size = cd->u.verity.hdr.data_size; - vp->hash_area_offset = cd->u.verity.hdr.hash_area_offset; - vp->hash_type = cd->u.verity.hdr.hash_type; - vp->flags = cd->u.verity.hdr.flags & CRYPT_VERITY_NO_HEADER; - return 0; + while (vk) { + crypt_drop_keyring_key_by_description(cd, vk->key_description, LOGON_KEY); + vk = crypt_volume_key_next(vk); + } } -int crypt_get_active_device(struct crypt_device *cd, const char *name, - struct crypt_active_device *cad) +int crypt_activate_by_keyring(struct crypt_device *cd, + const char *name, + const char *key_description, + int keyslot, + uint32_t flags) { - struct crypt_dm_active_device dmd; + char *passphrase; + size_t passphrase_size; int r; - r = dm_query_device(cd, name, 0, &dmd); + if (!cd || !key_description) + return -EINVAL; + + log_dbg(cd, "%s volume %s [keyslot %d] using passphrase in keyring.", + name ? "Activating" : "Checking", name ?: "passphrase", keyslot); + + if (!kernel_keyring_support()) { + log_err(cd, _("Kernel keyring is not supported by the kernel.")); + return -EINVAL; + } + + r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH); if (r < 0) return r; - if (dmd.target != DM_CRYPT && dmd.target != DM_VERITY) - return -ENOTSUP; + r = keyring_get_passphrase(key_description, &passphrase, &passphrase_size); + if (r < 0) { + log_err(cd, _("Failed to read passphrase from keyring (error %d)."), r); + return -EINVAL; + } - if (cd && isTCRYPT(cd->type)) { - cad->offset = TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); - cad->iv_offset = TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params); - } else { - cad->offset = dmd.u.crypt.offset; - cad->iv_offset = dmd.u.crypt.iv_offset; + r = _activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags); + + crypt_safe_memzero(passphrase, passphrase_size); + free(passphrase); + + return r; +} + +/* + * Workaround for serialization of parallel activation and memory-hard PBKDF + * In specific situation (systemd activation) this causes OOM killer activation. + * For now, let's provide this ugly way to serialize unlocking of devices. + */ +int crypt_serialize_lock(struct crypt_device *cd) +{ + if (!cd->memory_hard_pbkdf_lock_enabled) + return 0; + + log_dbg(cd, "Taking global memory-hard access serialization lock."); + if (crypt_write_lock(cd, "memory-hard-access", true, &cd->pbkdf_memory_hard_lock)) { + log_err(cd, _("Failed to acquire global memory-hard access serialization lock.")); + cd->pbkdf_memory_hard_lock = NULL; + return -EINVAL; } - cad->size = dmd.size; - cad->flags = dmd.flags; return 0; } + +void crypt_serialize_unlock(struct crypt_device *cd) +{ + if (!cd->memory_hard_pbkdf_lock_enabled) + return; + + crypt_unlock_internal(cd, cd->pbkdf_memory_hard_lock); + cd->pbkdf_memory_hard_lock = NULL; +} + +crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd, + struct crypt_params_reencrypt *params) +{ + if (!cd || !isLUKS2(cd->type)) + return CRYPT_REENCRYPT_NONE; + + if (_onlyLUKS2(cd, CRYPT_CD_QUIET, CRYPT_REQUIREMENT_ONLINE_REENCRYPT)) + return CRYPT_REENCRYPT_INVALID; + + return LUKS2_reencrypt_status(cd, params); +} + +static void __attribute__((destructor)) libcryptsetup_exit(void) +{ + crypt_backend_destroy(); + crypt_random_exit(); +} diff --git a/lib/tcrypt/Makefile.am b/lib/tcrypt/Makefile.am deleted file mode 100644 index 88bf520..0000000 --- a/lib/tcrypt/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -moduledir = $(libdir)/cryptsetup - -noinst_LTLIBRARIES = libtcrypt.la - -libtcrypt_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ - -libtcrypt_la_SOURCES = \ - tcrypt.c \ - tcrypt.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - diff --git a/lib/tcrypt/Makefile.in b/lib/tcrypt/Makefile.in deleted file mode 100644 index 842f637..0000000 --- a/lib/tcrypt/Makefile.in +++ /dev/null @@ -1,645 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib/tcrypt -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libtcrypt_la_LIBADD = -am_libtcrypt_la_OBJECTS = libtcrypt_la-tcrypt.lo -libtcrypt_la_OBJECTS = $(am_libtcrypt_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libtcrypt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libtcrypt_la_CFLAGS) \ - $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libtcrypt_la_SOURCES) -DIST_SOURCES = $(libtcrypt_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -moduledir = $(libdir)/cryptsetup -noinst_LTLIBRARIES = libtcrypt.la -libtcrypt_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ -libtcrypt_la_SOURCES = \ - tcrypt.c \ - tcrypt.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/tcrypt/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/tcrypt/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libtcrypt.la: $(libtcrypt_la_OBJECTS) $(libtcrypt_la_DEPENDENCIES) $(EXTRA_libtcrypt_la_DEPENDENCIES) - $(AM_V_CCLD)$(libtcrypt_la_LINK) $(libtcrypt_la_OBJECTS) $(libtcrypt_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcrypt_la-tcrypt.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libtcrypt_la-tcrypt.lo: tcrypt.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcrypt_la_CFLAGS) $(CFLAGS) -MT libtcrypt_la-tcrypt.lo -MD -MP -MF $(DEPDIR)/libtcrypt_la-tcrypt.Tpo -c -o libtcrypt_la-tcrypt.lo `test -f 'tcrypt.c' || echo '$(srcdir)/'`tcrypt.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtcrypt_la-tcrypt.Tpo $(DEPDIR)/libtcrypt_la-tcrypt.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcrypt.c' object='libtcrypt_la-tcrypt.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcrypt_la_CFLAGS) $(CFLAGS) -c -o libtcrypt_la-tcrypt.lo `test -f 'tcrypt.c' || echo '$(srcdir)/'`tcrypt.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c index 03b11ed..859f0ed 100644 --- a/lib/tcrypt/tcrypt.c +++ b/lib/tcrypt/tcrypt.c @@ -1,8 +1,8 @@ /* * TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2015, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "libcryptsetup.h" @@ -31,25 +30,29 @@ #include "internal.h" /* TCRYPT PBKDF variants */ -static struct { +static const struct { unsigned int legacy:1; unsigned int veracrypt:1; const char *name; const char *hash; unsigned int iterations; + uint32_t veracrypt_pim_const; + uint32_t veracrypt_pim_mult; } tcrypt_kdf[] = { - { 0, 0, "pbkdf2", "ripemd160", 2000 }, - { 0, 0, "pbkdf2", "ripemd160", 1000 }, - { 0, 0, "pbkdf2", "sha512", 1000 }, - { 0, 0, "pbkdf2", "whirlpool", 1000 }, - { 1, 0, "pbkdf2", "sha1", 2000 }, - { 0, 1, "pbkdf2", "sha512", 500000 }, - { 0, 1, "pbkdf2", "ripemd160", 655331 }, - { 0, 1, "pbkdf2", "ripemd160", 327661 }, // boot only - { 0, 1, "pbkdf2", "whirlpool", 500000 }, - { 0, 1, "pbkdf2", "sha256", 500000 }, // VeraCrypt 1.0f - { 0, 1, "pbkdf2", "sha256", 200000 }, // boot only - { 0, 0, NULL, NULL, 0 } + { 0, 0, "pbkdf2", "ripemd160", 2000, 0, 0 }, + { 0, 0, "pbkdf2", "ripemd160", 1000, 0, 0 }, + { 0, 0, "pbkdf2", "sha512", 1000, 0, 0 }, + { 0, 0, "pbkdf2", "whirlpool", 1000, 0, 0 }, + { 1, 0, "pbkdf2", "sha1", 2000, 0, 0 }, + { 0, 1, "pbkdf2", "sha512", 500000, 15000, 1000 }, + { 0, 1, "pbkdf2", "whirlpool", 500000, 15000, 1000 }, + { 0, 1, "pbkdf2", "sha256", 500000, 15000, 1000 }, // VeraCrypt 1.0f + { 0, 1, "pbkdf2", "sha256", 200000, 0, 2048 }, // boot only + { 0, 1, "pbkdf2", "ripemd160", 655331, 15000, 1000 }, + { 0, 1, "pbkdf2", "ripemd160", 327661, 0, 2048 }, // boot only + { 0, 1, "pbkdf2", "stribog512",500000, 15000, 1000 }, +// { 0, 1, "pbkdf2", "stribog512",200000, 0, 2048 }, // boot only + { 0, 0, NULL, NULL, 0, 0, 0 } }; struct tcrypt_alg { @@ -96,6 +99,26 @@ static struct tcrypt_algs tcrypt_cipher[] = { {0,2,128,"serpent-twofish","xts-plain64", {{"serpent",64,16, 0,64,0}, {"twofish",64,16,32,96,0}}}, +{0,1,64,"camellia","xts-plain64", + {{"camellia", 64,16,0,32,0}}}, +{0,1,64,"kuznyechik","xts-plain64", + {{"kuznyechik", 64,16,0,32,0}}}, +{0,2,128,"kuznyechik-camellia","xts-plain64", + {{"kuznyechik",64,16, 0,64,0}, + {"camellia", 64,16,32,96,0}}}, +{0,2,128,"twofish-kuznyechik","xts-plain64", + {{"twofish", 64,16, 0,64,0}, + {"kuznyechik",64,16,32,96,0}}}, +{0,2,128,"serpent-camellia","xts-plain64", + {{"serpent", 64,16, 0,64,0}, + {"camellia", 64,16,32,96,0}}}, +{0,2,128,"aes-kuznyechik","xts-plain64", + {{"aes", 64,16, 0,64,0}, + {"kuznyechik",64,16,32,96,0}}}, +{0,3,192,"camellia-serpent-kuznyechik","xts-plain64", + {{"camellia", 64,16, 0, 96,0}, + {"serpent", 64,16,32,128,0}, + {"kuznyechik",64,16,64,160,0}}}, /* LRW mode */ {0,1,48,"aes","lrw-benbi", @@ -178,7 +201,8 @@ static struct tcrypt_algs tcrypt_cipher[] = { {} }; -static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr, +static int TCRYPT_hdr_from_disk(struct crypt_device *cd, + struct tcrypt_phdr *hdr, struct crypt_params_tcrypt *params, int kdf_index, int cipher_index) { @@ -190,14 +214,14 @@ static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr, crc32 = crypt_crc32(~0, (unsigned char*)&hdr->d, size) ^ ~0; if (be16_to_cpu(hdr->d.version) > 3 && crc32 != be32_to_cpu(hdr->d.header_crc32)) { - log_dbg("TCRYPT header CRC32 mismatch."); + log_dbg(cd, "TCRYPT header CRC32 mismatch."); return -EINVAL; } /* Check CRC32 of keys */ crc32 = crypt_crc32(~0, (unsigned char*)hdr->d.keys, sizeof(hdr->d.keys)) ^ ~0; if (crc32 != be32_to_cpu(hdr->d.keys_crc32)) { - log_dbg("TCRYPT keys CRC32 mismatch."); + log_dbg(cd, "TCRYPT keys CRC32 mismatch."); return -EINVAL; } @@ -276,8 +300,8 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, } crypt_cipher_destroy(cipher); - crypt_memzero(iv, bs); - crypt_memzero(iv_old, bs); + crypt_safe_memzero(iv, bs); + crypt_safe_memzero(iv_old, bs); return r; } @@ -314,12 +338,13 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, { char backend_key[TCRYPT_HDR_KEY_LEN]; char iv[TCRYPT_HDR_IV_LEN] = {}; - char mode_name[MAX_CIPHER_LEN]; + char mode_name[MAX_CIPHER_LEN + 1]; struct crypt_cipher *cipher; char *c, *buf = (char*)&hdr->e; int r; /* Remove IV if present */ + mode_name[MAX_CIPHER_LEN] = '\0'; strncpy(mode_name, mode, MAX_CIPHER_LEN); c = strchr(mode_name, '-'); if (c) @@ -343,13 +368,13 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, crypt_cipher_destroy(cipher); } - crypt_memzero(backend_key, sizeof(backend_key)); - crypt_memzero(iv, TCRYPT_HDR_IV_LEN); + crypt_safe_memzero(backend_key, sizeof(backend_key)); + crypt_safe_memzero(iv, TCRYPT_HDR_IV_LEN); return r; } /* - * For chanined ciphers and CBC mode we need "outer" decryption. + * For chained ciphers and CBC mode we need "outer" decryption. * Backend doesn't provide this, so implement it here directly using ECB. */ static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers, @@ -394,8 +419,8 @@ out: if (cipher[j]) crypt_cipher_destroy(cipher[j]); - crypt_memzero(iv, bs); - crypt_memzero(iv_old, bs); + crypt_safe_memzero(iv, bs); + crypt_safe_memzero(iv_old, bs); return r; } @@ -408,7 +433,7 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, for (i = 0; tcrypt_cipher[i].chain_count; i++) { if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy) continue; - log_dbg("TCRYPT: trying cipher %s-%s", + log_dbg(cd, "TCRYPT: trying cipher %s-%s", tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode); memcpy(&hdr2.e, &hdr->e, TCRYPT_HDR_LEN); @@ -425,7 +450,7 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, } if (r < 0) { - log_dbg("TCRYPT: returned error %d, skipped.", r); + log_dbg(cd, "TCRYPT: returned error %d, skipped.", r); if (r == -ENOTSUP) break; r = -ENOENT; @@ -433,14 +458,14 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, } if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) { - log_dbg("TCRYPT: Signature magic detected."); + log_dbg(cd, "TCRYPT: Signature magic detected."); memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN); r = i; break; } if ((flags & CRYPT_TCRYPT_VERA_MODES) && !strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) { - log_dbg("TCRYPT: Signature magic detected (Veracrypt)."); + log_dbg(cd, "TCRYPT: Signature magic detected (Veracrypt)."); memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN); r = i; break; @@ -448,32 +473,36 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, r = -EPERM; } - crypt_memzero(&hdr2, sizeof(hdr2)); + crypt_safe_memzero(&hdr2, sizeof(hdr2)); return r; } static int TCRYPT_pool_keyfile(struct crypt_device *cd, - unsigned char pool[TCRYPT_KEY_POOL_LEN], - const char *keyfile) + unsigned char pool[VCRYPT_KEY_POOL_LEN], + const char *keyfile, int keyfiles_pool_length) { - unsigned char data[TCRYPT_KEYFILE_LEN]; - int i, j, fd, data_size; + unsigned char *data; + int i, j, fd, data_size, r = -EIO; uint32_t crc; - log_dbg("TCRYPT: using keyfile %s.", keyfile); + log_dbg(cd, "TCRYPT: using keyfile %s.", keyfile); + + data = malloc(TCRYPT_KEYFILE_LEN); + if (!data) + return -ENOMEM; + memset(data, 0, TCRYPT_KEYFILE_LEN); fd = open(keyfile, O_RDONLY); if (fd < 0) { - log_err(cd, _("Failed to open key file.\n")); - return -EIO; + log_err(cd, _("Failed to open key file.")); + goto out; } - /* FIXME: add while */ - data_size = read(fd, data, TCRYPT_KEYFILE_LEN); + data_size = read_buffer(fd, data, TCRYPT_KEYFILE_LEN); close(fd); if (data_size < 0) { - log_err(cd, _("Error reading keyfile %s.\n"), keyfile); - return -EIO; + log_err(cd, _("Error reading keyfile %s."), keyfile); + goto out; } for (i = 0, j = 0, crc = ~0U; i < data_size; i++) { @@ -482,42 +511,54 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd, pool[j++] += (unsigned char)(crc >> 16); pool[j++] += (unsigned char)(crc >> 8); pool[j++] += (unsigned char)(crc); - j %= TCRYPT_KEY_POOL_LEN; + j %= keyfiles_pool_length; } + r = 0; +out: + crypt_safe_memzero(&crc, sizeof(crc)); + crypt_safe_memzero(data, TCRYPT_KEYFILE_LEN); + free(data); - crypt_memzero(&crc, sizeof(crc)); - crypt_memzero(data, TCRYPT_KEYFILE_LEN); - - return 0; + return r; } static int TCRYPT_init_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, struct crypt_params_tcrypt *params) { - unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {}; - size_t passphrase_size; + unsigned char pwd[VCRYPT_KEY_POOL_LEN] = {}; + size_t passphrase_size, max_passphrase_size; char *key; - unsigned int i, skipped = 0; - int r = -EPERM; + unsigned int i, skipped = 0, iterations; + int r = -EPERM, keyfiles_pool_length; if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN)) return -ENOMEM; + if (params->flags & CRYPT_TCRYPT_VERA_MODES && + params->passphrase_size > TCRYPT_KEY_POOL_LEN) { + /* Really. Keyfile pool length depends on passphrase size in Veracrypt. */ + max_passphrase_size = VCRYPT_KEY_POOL_LEN; + keyfiles_pool_length = VCRYPT_KEY_POOL_LEN; + } else { + max_passphrase_size = TCRYPT_KEY_POOL_LEN; + keyfiles_pool_length = TCRYPT_KEY_POOL_LEN; + } + if (params->keyfiles_count) - passphrase_size = TCRYPT_KEY_POOL_LEN; + passphrase_size = max_passphrase_size; else passphrase_size = params->passphrase_size; - if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) { - log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded.\n"), - TCRYPT_KEY_POOL_LEN); + if (params->passphrase_size > max_passphrase_size) { + log_err(cd, _("Maximum TCRYPT passphrase length (%zu) exceeded."), + max_passphrase_size); goto out; } /* Calculate pool content from keyfiles */ for (i = 0; i < params->keyfiles_count; i++) { - r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]); + r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i], keyfiles_pool_length); if (r < 0) goto out; } @@ -531,21 +572,30 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, continue; if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt) continue; + if ((params->flags & CRYPT_TCRYPT_VERA_MODES) && params->veracrypt_pim) { + /* Do not try TrueCrypt modes if we have PIM value */ + if (!tcrypt_kdf[i].veracrypt) + continue; + /* adjust iterations to given PIM cmdline parameter */ + iterations = tcrypt_kdf[i].veracrypt_pim_const + + (tcrypt_kdf[i].veracrypt_pim_mult * params->veracrypt_pim); + } else + iterations = tcrypt_kdf[i].iterations; + /* Derive header key */ - log_dbg("TCRYPT: trying KDF: %s-%s-%d.", - tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations); + log_dbg(cd, "TCRYPT: trying KDF: %s-%s-%d%s.", + tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations, + params->veracrypt_pim && tcrypt_kdf[i].veracrypt ? "-PIM" : ""); r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash, (char*)pwd, passphrase_size, hdr->salt, TCRYPT_HDR_SALT_LEN, key, TCRYPT_HDR_KEY_LEN, - tcrypt_kdf[i].iterations); - if (r < 0 && crypt_hash_size(tcrypt_kdf[i].hash) < 0) { - log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping.\n"), + iterations, 0, 0); + if (r < 0) { + log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping."), tcrypt_kdf[i].hash); continue; } - if (r < 0) - break; /* Decrypt header */ r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags); @@ -558,29 +608,29 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, } if ((r < 0 && r != -EPERM && skipped && skipped == i) || r == -ENOTSUP) { - log_err(cd, _("Required kernel crypto interface not available.\n")); + log_err(cd, _("Required kernel crypto interface not available.")); #ifdef ENABLE_AF_ALG - log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.\n")); + log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.")); #endif } if (r < 0) goto out; - r = TCRYPT_hdr_from_disk(hdr, params, i, r); + r = TCRYPT_hdr_from_disk(cd, hdr, params, i, r); if (!r) { - log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d" + log_dbg(cd, "TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d" ", mk_offset %" PRIu64 ", hidden_size %" PRIu64 ", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ? VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC, (int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size, hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size); - log_dbg("TCRYPT: Header cipher %s-%s, key size %zu", + log_dbg(cd, "TCRYPT: Header cipher %s-%s, key size %zu", params->cipher, params->mode, params->key_size); } out: - crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN); + crypt_safe_memzero(pwd, TCRYPT_KEY_POOL_LEN); if (key) - crypt_memzero(key, TCRYPT_HDR_KEY_LEN); + crypt_safe_memzero(key, TCRYPT_HDR_KEY_LEN); free(key); return r; } @@ -589,70 +639,71 @@ int TCRYPT_read_phdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, struct crypt_params_tcrypt *params) { - struct device *base_device, *device = crypt_metadata_device(cd); + struct device *base_device = NULL, *device = crypt_metadata_device(cd); ssize_t hdr_size = sizeof(struct tcrypt_phdr); char *base_device_path; - int devfd = 0, r, bs; + int devfd, r; assert(sizeof(struct tcrypt_phdr) == 512); - log_dbg("Reading TCRYPT header of size %zu bytes from device %s.", + log_dbg(cd, "Reading TCRYPT header of size %zu bytes from device %s.", hdr_size, device_path(device)); - bs = device_block_size(device); - if (bs < 0) - return bs; - if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER && crypt_dev_is_partition(device_path(device))) { base_device_path = crypt_get_base_device(device_path(device)); - log_dbg("Reading TCRYPT system header from device %s.", base_device_path ?: "?"); + log_dbg(cd, "Reading TCRYPT system header from device %s.", base_device_path ?: "?"); if (!base_device_path) return -EINVAL; - r = device_alloc(&base_device, base_device_path); + r = device_alloc(cd, &base_device, base_device_path); + free(base_device_path); if (r < 0) return r; - devfd = device_open(base_device, O_RDONLY); - free(base_device_path); - device_free(base_device); + devfd = device_open(cd, base_device, O_RDONLY); } else - devfd = device_open(device, O_RDONLY); + devfd = device_open(cd, device, O_RDONLY); - if (devfd == -1) { - log_err(cd, _("Cannot open device %s.\n"), device_path(device)); + if (devfd < 0) { + device_free(cd, base_device); + log_err(cd, _("Cannot open device %s."), device_path(device)); return -EINVAL; } r = -EIO; if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) { - if (lseek(devfd, TCRYPT_HDR_SYSTEM_OFFSET, SEEK_SET) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) { + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, + TCRYPT_HDR_SYSTEM_OFFSET) == hdr_size) { r = TCRYPT_init_hdr(cd, hdr, params); } } else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) { if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) { - if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_BCK, SEEK_END) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, + TCRYPT_HDR_HIDDEN_OFFSET_BCK) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); } else { - if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, + TCRYPT_HDR_HIDDEN_OFFSET) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); - if (r && - lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_OLD, SEEK_END) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + if (r && read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, + TCRYPT_HDR_HIDDEN_OFFSET_OLD) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); } } else if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) { - if (lseek(devfd, TCRYPT_HDR_OFFSET_BCK, SEEK_END) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, + TCRYPT_HDR_OFFSET_BCK) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); - } else if (read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + } else if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), hdr, hdr_size, 0) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); - close(devfd); + device_free(cd, base_device); if (r < 0) memset(hdr, 0, sizeof (*hdr)); return r; @@ -679,38 +730,33 @@ int TCRYPT_activate(struct crypt_device *cd, struct crypt_params_tcrypt *params, uint32_t flags) { - char cipher[MAX_CIPHER_LEN], dm_name[PATH_MAX], dm_dev_name[PATH_MAX]; + char dm_name[PATH_MAX], dm_dev_name[PATH_MAX], cipher_spec[MAX_CIPHER_LEN*2+1]; char *part_path; - struct device *device = NULL, *part_device = NULL; unsigned int i; int r; - uint32_t req_flags; + uint32_t req_flags, dmc_flags; struct tcrypt_algs *algs; enum devcheck device_check; + uint64_t offset = crypt_get_data_offset(cd); + struct volume_key *vk = NULL; + struct device *ptr_dev = crypt_data_device(cd), *device = NULL, *part_device = NULL; struct crypt_dm_active_device dmd = { - .target = DM_CRYPT, - .size = 0, - .data_device = crypt_data_device(cd), - .u.crypt = { - .cipher = cipher, - .offset = crypt_get_data_offset(cd), - .iv_offset = crypt_get_iv_offset(cd), - } + .flags = flags }; if (!hdr->d.version) { - log_dbg("TCRYPT: this function is not supported without encrypted header load."); + log_dbg(cd, "TCRYPT: this function is not supported without encrypted header load."); return -ENOTSUP; } if (hdr->d.sector_size && hdr->d.sector_size != SECTOR_SIZE) { - log_err(cd, _("Activation is not supported for %d sector size.\n"), + log_err(cd, _("Activation is not supported for %d sector size."), hdr->d.sector_size); return -ENOTSUP; } if (strstr(params->mode, "-tcrypt")) { - log_err(cd, _("Kernel doesn't support activation for this TCRYPT legacy mode.\n")); + log_err(cd, _("Kernel does not support activation for this TCRYPT legacy mode.")); return -ENOTSUP; } @@ -723,6 +769,9 @@ int TCRYPT_activate(struct crypt_device *cd, if (!algs) return -EINVAL; + if (hdr->d.sector_size == 0) + return -EINVAL; + if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) dmd.size = 0; else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) @@ -731,20 +780,20 @@ int TCRYPT_activate(struct crypt_device *cd, dmd.size = hdr->d.volume_size / hdr->d.sector_size; if (dmd.flags & CRYPT_ACTIVATE_SHARED) - device_check = DEV_SHARED; + device_check = DEV_OK; else device_check = DEV_EXCL; if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) && - !crypt_dev_is_partition(device_path(dmd.data_device))) { - part_path = crypt_get_partition_device(device_path(dmd.data_device), - dmd.u.crypt.offset, dmd.size); + !crypt_dev_is_partition(device_path(crypt_data_device(cd)))) { + part_path = crypt_get_partition_device(device_path(crypt_data_device(cd)), + crypt_get_data_offset(cd), dmd.size); if (part_path) { - if (!device_alloc(&part_device, part_path)) { - log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"), + if (!device_alloc(cd, &part_device, part_path)) { + log_verbose(cd, _("Activating TCRYPT system encryption for partition %s."), part_path); - dmd.data_device = part_device; - dmd.u.crypt.offset = 0; + ptr_dev = part_device; + offset = 0; } free(part_path); } else @@ -752,70 +801,88 @@ int TCRYPT_activate(struct crypt_device *cd, * System encryption use the whole device mapping, there can * be active partitions. */ - device_check = DEV_SHARED; + device_check = DEV_OK; } - r = device_block_adjust(cd, dmd.data_device, device_check, - dmd.u.crypt.offset, &dmd.size, &dmd.flags); + r = device_block_adjust(cd, ptr_dev, device_check, + offset, &dmd.size, &dmd.flags); if (r) - return r; + goto out; - /* Frome here, key size for every cipher must be the same */ - dmd.u.crypt.vk = crypt_alloc_volume_key(algs->cipher[0].key_size + - algs->cipher[0].key_extra_size, NULL); - if (!dmd.u.crypt.vk) - return -ENOMEM; + /* From here, key size for every cipher must be the same */ + vk = crypt_alloc_volume_key(algs->cipher[0].key_size + + algs->cipher[0].key_extra_size, NULL); + if (!vk) { + r = -ENOMEM; + goto out; + } for (i = algs->chain_count; i > 0; i--) { if (i == 1) { - strncpy(dm_name, name, sizeof(dm_name)); + dm_name[sizeof(dm_name)-1] = '\0'; + strncpy(dm_name, name, sizeof(dm_name)-1); dmd.flags = flags; } else { snprintf(dm_name, sizeof(dm_name), "%s_%d", name, i-1); dmd.flags = flags | CRYPT_ACTIVATE_PRIVATE; } - snprintf(cipher, sizeof(cipher), "%s-%s", - algs->cipher[i-1].name, algs->mode); - TCRYPT_copy_key(&algs->cipher[i-1], algs->mode, - dmd.u.crypt.vk->key, hdr->d.keys); + vk->key, hdr->d.keys); if (algs->chain_count != i) { snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d", dm_get_dir(), name, i); - r = device_alloc(&device, dm_dev_name); + r = device_alloc(cd, &device, dm_dev_name); if (r) break; - dmd.data_device = device; - dmd.u.crypt.offset = 0; + ptr_dev = device; + offset = 0; } - log_dbg("Trying to activate TCRYPT device %s using cipher %s.", - dm_name, dmd.u.crypt.cipher); - r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd, 0); + r = snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", algs->cipher[i-1].name, algs->mode); + if (r < 0 || (size_t)r >= sizeof(cipher_spec)) { + r = -ENOMEM; + break; + } - device_free(device); + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, ptr_dev, vk, + cipher_spec, crypt_get_iv_offset(cd), offset, + crypt_get_integrity(cd), + crypt_get_integrity_tag_size(cd), + crypt_get_sector_size(cd)); + if (r) + break; + + log_dbg(cd, "Trying to activate TCRYPT device %s using cipher %s.", + dm_name, dmd.segment.u.crypt.cipher); + r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd); + + dm_targets_free(cd, &dmd); + device_free(cd, device); device = NULL; if (r) break; } - if (r < 0 && !(dm_flags() & req_flags)) { - log_err(cd, _("Kernel doesn't support TCRYPT compatible mapping.\n")); + if (r < 0 && + (dm_flags(cd, DM_CRYPT, &dmc_flags) || ((dmc_flags & req_flags) != req_flags))) { + log_err(cd, _("Kernel does not support TCRYPT compatible mapping.")); r = -ENOTSUP; } - device_free(part_device); - crypt_free_volume_key(dmd.u.crypt.vk); +out: + crypt_free_volume_key(vk); + device_free(cd, device); + device_free(cd, part_device); return r; } static int TCRYPT_remove_one(struct crypt_device *cd, const char *name, - const char *base_uuid, int index) + const char *base_uuid, int index, uint32_t flags) { - struct crypt_dm_active_device dmd = {}; + struct crypt_dm_active_device dmd; char dm_name[PATH_MAX]; int r; @@ -828,15 +895,15 @@ static int TCRYPT_remove_one(struct crypt_device *cd, const char *name, r = dm_query_device(cd, dm_name, DM_ACTIVE_UUID, &dmd); if (!r && !strncmp(dmd.uuid, base_uuid, strlen(base_uuid))) - r = dm_remove_device(cd, dm_name, 0, 0); + r = dm_remove_device(cd, dm_name, flags); free(CONST_CAST(void*)dmd.uuid); return r; } -int TCRYPT_deactivate(struct crypt_device *cd, const char *name) +int TCRYPT_deactivate(struct crypt_device *cd, const char *name, uint32_t flags) { - struct crypt_dm_active_device dmd = {}; + struct crypt_dm_active_device dmd; int r; r = dm_query_device(cd, name, DM_ACTIVE_UUID, &dmd); @@ -845,28 +912,28 @@ int TCRYPT_deactivate(struct crypt_device *cd, const char *name) if (!dmd.uuid) return -EINVAL; - r = dm_remove_device(cd, name, 0, 0); + r = dm_remove_device(cd, name, flags); if (r < 0) goto out; - r = TCRYPT_remove_one(cd, name, dmd.uuid, 1); + r = TCRYPT_remove_one(cd, name, dmd.uuid, 1, flags); if (r < 0) goto out; - r = TCRYPT_remove_one(cd, name, dmd.uuid, 2); - if (r < 0) - goto out; + r = TCRYPT_remove_one(cd, name, dmd.uuid, 2, flags); out: free(CONST_CAST(void*)dmd.uuid); return (r == -ENODEV) ? 0 : r; } static int TCRYPT_status_one(struct crypt_device *cd, const char *name, - const char *base_uuid, int index, - size_t *key_size, char *cipher, - uint64_t *data_offset, struct device **device) + const char *base_uuid, int index, + size_t *key_size, char *cipher, + struct tcrypt_phdr *tcrypt_hdr, + struct device **device) { - struct crypt_dm_active_device dmd = {}; + struct crypt_dm_active_device dmd; + struct dm_target *tgt = &dmd.segment; char dm_name[PATH_MAX], *c; int r; @@ -881,57 +948,63 @@ static int TCRYPT_status_one(struct crypt_device *cd, const char *name, DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_CIPHER | DM_ACTIVE_CRYPT_KEYSIZE, &dmd); - if (r > 0) - r = 0; - if (!r && !strncmp(dmd.uuid, base_uuid, strlen(base_uuid))) { - if ((c = strchr(dmd.u.crypt.cipher, '-'))) + if (r < 0) + return r; + if (!single_segment(&dmd) || tgt->type != DM_CRYPT) { + r = -ENOTSUP; + goto out; + } + + r = 0; + + if (!strncmp(dmd.uuid, base_uuid, strlen(base_uuid))) { + if ((c = strchr(tgt->u.crypt.cipher, '-'))) *c = '\0'; strcat(cipher, "-"); - strncat(cipher, dmd.u.crypt.cipher, MAX_CIPHER_LEN); - *key_size += dmd.u.crypt.vk->keylength; - *data_offset = dmd.u.crypt.offset * SECTOR_SIZE; - device_free(*device); - *device = dmd.data_device; - } else { - device_free(dmd.data_device); + strncat(cipher, tgt->u.crypt.cipher, MAX_CIPHER_LEN); + *key_size += tgt->u.crypt.vk->keylength; + tcrypt_hdr->d.mk_offset = tgt->u.crypt.offset * SECTOR_SIZE; + device_free(cd, *device); + MOVE_REF(*device, tgt->data_device); + } else r = -ENODEV; - } - +out: + dm_targets_free(cd, &dmd); free(CONST_CAST(void*)dmd.uuid); - free(CONST_CAST(void*)dmd.u.crypt.cipher); - crypt_free_volume_key(dmd.u.crypt.vk); return r; } int TCRYPT_init_by_name(struct crypt_device *cd, const char *name, - const struct crypt_dm_active_device *dmd, + const char *uuid, + const struct dm_target *tgt, struct device **device, struct crypt_params_tcrypt *tcrypt_params, struct tcrypt_phdr *tcrypt_hdr) { struct tcrypt_algs *algs; - char cipher[MAX_CIPHER_LEN * 4], mode[MAX_CIPHER_LEN], *tmp; + char cipher[MAX_CIPHER_LEN * 4], mode[MAX_CIPHER_LEN+1], *tmp; size_t key_size; int r; memset(tcrypt_params, 0, sizeof(*tcrypt_params)); memset(tcrypt_hdr, 0, sizeof(*tcrypt_hdr)); tcrypt_hdr->d.sector_size = SECTOR_SIZE; - tcrypt_hdr->d.mk_offset = dmd->u.crypt.offset * SECTOR_SIZE; + tcrypt_hdr->d.mk_offset = tgt->u.crypt.offset * SECTOR_SIZE; - strncpy(cipher, dmd->u.crypt.cipher, MAX_CIPHER_LEN); + strncpy(cipher, tgt->u.crypt.cipher, MAX_CIPHER_LEN); tmp = strchr(cipher, '-'); if (!tmp) return -EINVAL; *tmp = '\0'; + mode[MAX_CIPHER_LEN] = '\0'; strncpy(mode, ++tmp, MAX_CIPHER_LEN); - key_size = dmd->u.crypt.vk->keylength; - r = TCRYPT_status_one(cd, name, dmd->uuid, 1, &key_size, - cipher, &tcrypt_hdr->d.mk_offset, device); + key_size = tgt->u.crypt.vk->keylength; + r = TCRYPT_status_one(cd, name, uuid, 1, &key_size, + cipher, tcrypt_hdr, device); if (!r) - r = TCRYPT_status_one(cd, name, dmd->uuid, 2, &key_size, - cipher, &tcrypt_hdr->d.mk_offset, device); + r = TCRYPT_status_one(cd, name, uuid, 2, &key_size, + cipher, tcrypt_hdr, device); if (r < 0 && r != -ENODEV) return r; diff --git a/lib/tcrypt/tcrypt.h b/lib/tcrypt/tcrypt.h index 21ecba9..a3b6ad0 100644 --- a/lib/tcrypt/tcrypt.h +++ b/lib/tcrypt/tcrypt.h @@ -1,8 +1,8 @@ /* - * TCRYPT (TrueCrypt-compatible) header defitinion + * TCRYPT (TrueCrypt-compatible) header definition * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2014, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,11 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "libcryptsetup.h" - #ifndef _CRYPTSETUP_TCRYPT_H #define _CRYPTSETUP_TCRYPT_H +#include + #define TCRYPT_HDR_SALT_LEN 64 #define TCRYPT_HDR_IV_LEN 16 #define TCRYPT_HDR_LEN 448 @@ -42,6 +42,7 @@ #define TCRYPT_LRW_IKEY_LEN 16 #define TCRYPT_KEY_POOL_LEN 64 +#define VCRYPT_KEY_POOL_LEN 128 #define TCRYPT_KEYFILE_LEN 1048576 #define TCRYPT_HDR_FLAG_SYSTEM (1 << 0) @@ -72,7 +73,10 @@ struct tcrypt_phdr { }; } __attribute__((__packed__)); +struct crypt_device; +struct crypt_params_tcrypt; struct crypt_dm_active_device; +struct dm_target; struct volume_key; struct device; @@ -81,7 +85,8 @@ int TCRYPT_read_phdr(struct crypt_device *cd, struct crypt_params_tcrypt *params); int TCRYPT_init_by_name(struct crypt_device *cd, const char *name, - const struct crypt_dm_active_device *dmd, + const char *uuid, + const struct dm_target *tgt, struct device **device, struct crypt_params_tcrypt *tcrypt_params, struct tcrypt_phdr *tcrypt_hdr); @@ -93,7 +98,8 @@ int TCRYPT_activate(struct crypt_device *cd, uint32_t flags); int TCRYPT_deactivate(struct crypt_device *cd, - const char *name); + const char *name, + uint32_t flags); uint64_t TCRYPT_get_data_offset(struct crypt_device *cd, struct tcrypt_phdr *hdr, diff --git a/lib/utils.c b/lib/utils.c index a5aec70..0cf4378 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1,10 +1,10 @@ /* * utils - miscellaneous device utilities for cryptsetup * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,242 +22,324 @@ */ #include -#include -#include #include #include #include +#include +#include #include "internal.h" -unsigned crypt_getpagesize(void) +size_t crypt_getpagesize(void) { long r = sysconf(_SC_PAGESIZE); - return r < 0 ? DEFAULT_MEM_ALIGNMENT : r; + return r <= 0 ? DEFAULT_MEM_ALIGNMENT : (size_t)r; } -static int get_alignment(int fd) +unsigned crypt_cpusonline(void) { - int alignment = DEFAULT_MEM_ALIGNMENT; - -#ifdef _PC_REC_XFER_ALIGN - alignment = fpathconf(fd, _PC_REC_XFER_ALIGN); - if (alignment < 0) - alignment = DEFAULT_MEM_ALIGNMENT; -#endif - return alignment; + long r = sysconf(_SC_NPROCESSORS_ONLN); + return r < 0 ? 1 : r; } -static void *aligned_malloc(void **base, int size, int alignment) +uint64_t crypt_getphysmemory_kb(void) { -#ifdef HAVE_POSIX_MEMALIGN - return posix_memalign(base, alignment, size) ? NULL : *base; -#else -/* Credits go to Michal's padlock patches for this alignment code */ - char *ptr; - - ptr = malloc(size + alignment); - if(ptr == NULL) return NULL; - - *base = ptr; - if(alignment > 1 && ((long)ptr & (alignment - 1))) { - ptr += alignment - ((long)(ptr) & (alignment - 1)); - } - return ptr; -#endif -} - -ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count) -{ - void *hangover_buf, *hangover_buf_base = NULL; - void *buf, *buf_base = NULL; - int r, hangover, solid, alignment; - ssize_t ret = -1; - - if (fd == -1 || !orig_buf || bsize <= 0) - return -1; + long pagesize, phys_pages; + uint64_t phys_memory_kb; - hangover = count % bsize; - solid = count - hangover; - alignment = get_alignment(fd); + pagesize = sysconf(_SC_PAGESIZE); + phys_pages = sysconf(_SC_PHYS_PAGES); - if ((long)orig_buf & (alignment - 1)) { - buf = aligned_malloc(&buf_base, count, alignment); - if (!buf) - goto out; - memcpy(buf, orig_buf, count); - } else - buf = orig_buf; + if (pagesize < 0 || phys_pages < 0) + return 0; - r = write(fd, buf, solid); - if (r < 0 || r != solid) - goto out; + phys_memory_kb = pagesize / 1024; + phys_memory_kb *= phys_pages; - if (hangover) { - hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment); - if (!hangover_buf) - goto out; + return phys_memory_kb; +} - r = read(fd, hangover_buf, bsize); - if (r < 0 || r < hangover) - goto out; +/* MEMLOCK */ +#define DEFAULT_PROCESS_PRIORITY -18 - if (r < bsize) - bsize = r; +static int _priority; +static int _memlock_count = 0; - r = lseek(fd, -bsize, SEEK_CUR); - if (r < 0) - goto out; - memcpy(hangover_buf, (char*)buf + solid, hangover); +// return 1 if memory is locked +int crypt_memlock_inc(struct crypt_device *ctx) +{ + if (!_memlock_count++) { + log_dbg(ctx, "Locking memory."); + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + log_dbg(ctx, "Cannot lock memory with mlockall."); + _memlock_count--; + return 0; + } + errno = 0; + if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno) + log_err(ctx, _("Cannot get process priority.")); + else + if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY)) + log_dbg(ctx, "setpriority %d failed: %s", + DEFAULT_PROCESS_PRIORITY, strerror(errno)); + } + return _memlock_count ? 1 : 0; +} - r = write(fd, hangover_buf, bsize); - if (r < 0 || r < hangover) - goto out; +int crypt_memlock_dec(struct crypt_device *ctx) +{ + if (_memlock_count && (!--_memlock_count)) { + log_dbg(ctx, "Unlocking memory."); + if (munlockall() == -1) + log_err(ctx, _("Cannot unlock memory.")); + if (setpriority(PRIO_PROCESS, 0, _priority)) + log_dbg(ctx, "setpriority %d failed: %s", _priority, strerror(errno)); } - ret = count; -out: - free(hangover_buf_base); - if (buf != orig_buf) - free(buf_base); - return ret; + return _memlock_count ? 1 : 0; } -ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count) { - void *hangover_buf, *hangover_buf_base = NULL; - void *buf, *buf_base = NULL; - int r, hangover, solid, alignment; - ssize_t ret = -1; +/* Keyfile processing */ - if (fd == -1 || !orig_buf || bsize <= 0) +/* + * A simple call to lseek(3) might not be possible for some inputs (e.g. + * reading from a pipe), so this function instead reads of up to BUFSIZ bytes + * at a time until the specified number of bytes. It returns -1 on read error + * or when it reaches EOF before the requested number of bytes have been + * discarded. + */ +static int keyfile_seek(int fd, uint64_t bytes) +{ + char tmp[BUFSIZ]; + size_t next_read; + ssize_t bytes_r; + off64_t r; + + r = lseek64(fd, bytes, SEEK_CUR); + if (r > 0) + return 0; + if (r < 0 && errno != ESPIPE) return -1; - hangover = count % bsize; - solid = count - hangover; - alignment = get_alignment(fd); + while (bytes > 0) { + /* figure out how much to read */ + next_read = bytes > sizeof(tmp) ? sizeof(tmp) : (size_t)bytes; + + bytes_r = read(fd, tmp, next_read); + if (bytes_r < 0) { + if (errno == EINTR) + continue; - if ((long)orig_buf & (alignment - 1)) { - buf = aligned_malloc(&buf_base, count, alignment); - if (!buf) + crypt_safe_memzero(tmp, sizeof(tmp)); + /* read error */ return -1; - } else - buf = orig_buf; + } + + if (bytes_r == 0) + /* EOF */ + break; - r = read(fd, buf, solid); - if(r < 0 || r != solid) - goto out; + bytes -= bytes_r; + } - if (hangover) { - hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment); - if (!hangover_buf) - goto out; - r = read(fd, hangover_buf, bsize); - if (r < 0 || r < hangover) - goto out; + crypt_safe_memzero(tmp, sizeof(tmp)); + return bytes == 0 ? 0 : -1; +} - memcpy((char *)buf + solid, hangover_buf, hangover); +int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile, + char **key, size_t *key_size_read, + uint64_t keyfile_offset, size_t key_size, + uint32_t flags) +{ + int fd, regular_file, char_to_read = 0, char_read = 0, unlimited_read = 0; + int r = -EINVAL, newline; + char *pass = NULL; + size_t buflen, i; + uint64_t file_read_size; + struct stat st; + + if (!key || !key_size_read) + return -EINVAL; + + *key = NULL; + *key_size_read = 0; + + fd = keyfile ? open(keyfile, O_RDONLY) : STDIN_FILENO; + if (fd < 0) { + log_err(cd, _("Failed to open key file.")); + return -EINVAL; } - ret = count; -out: - free(hangover_buf_base); - if (buf != orig_buf) { - memcpy(orig_buf, buf, count); - free(buf_base); + + if (isatty(fd)) { + log_err(cd, _("Cannot read keyfile from a terminal.")); + r = -EINVAL; + goto out_err; } - return ret; -} -/* - * Combines llseek with blockwise write. write_blockwise can already deal with short writes - * but we also need a function to deal with short writes at the start. But this information - * is implicitly included in the read/write offset, which can not be set to non-aligned - * boundaries. Hence, we combine llseek with write. - */ -ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset) { - char *frontPadBuf; - void *frontPadBuf_base = NULL; - int r, frontHang; - size_t innerCount = 0; - ssize_t ret = -1; - - if (fd == -1 || !buf || bsize <= 0) - return -1; + /* If not requested otherwise, we limit input to prevent memory exhaustion */ + if (key_size == 0) { + key_size = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1; + unlimited_read = 1; + /* use 4k for buffer (page divisor but avoid huge pages) */ + buflen = 4096 - sizeof(size_t); // sizeof(struct safe_allocation); + } else + buflen = key_size; - frontHang = offset % bsize; + regular_file = 0; + if (keyfile) { + if (stat(keyfile, &st) < 0) { + log_err(cd, _("Failed to stat key file.")); + goto out_err; + } + if (S_ISREG(st.st_mode)) { + regular_file = 1; + file_read_size = (uint64_t)st.st_size; + + if (keyfile_offset > file_read_size) { + log_err(cd, _("Cannot seek to requested keyfile offset.")); + goto out_err; + } + file_read_size -= keyfile_offset; + + /* known keyfile size, alloc it in one step */ + if (file_read_size >= (uint64_t)key_size) + buflen = key_size; + else if (file_read_size) + buflen = file_read_size; + } + } - if (lseek(fd, offset - frontHang, SEEK_SET) < 0) - goto out; + pass = crypt_safe_alloc(buflen); + if (!pass) { + log_err(cd, _("Out of memory while reading passphrase.")); + goto out_err; + } - if (frontHang) { - frontPadBuf = aligned_malloc(&frontPadBuf_base, - bsize, get_alignment(fd)); - if (!frontPadBuf) - goto out; + /* Discard keyfile_offset bytes on input */ + if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) { + log_err(cd, _("Cannot seek to requested keyfile offset.")); + goto out_err; + } - r = read(fd, frontPadBuf, bsize); - if (r < 0 || r != bsize) - goto out; + for (i = 0, newline = 0; i < key_size; i += char_read) { + if (i == buflen) { + buflen += 4096; + pass = crypt_safe_realloc(pass, buflen); + if (!pass) { + log_err(cd, _("Out of memory while reading passphrase.")); + r = -ENOMEM; + goto out_err; + } + } - innerCount = bsize - frontHang; - if (innerCount > count) - innerCount = count; + if (flags & CRYPT_KEYFILE_STOP_EOL) { + /* If we should stop on newline, we must read the input + * one character at the time. Otherwise we might end up + * having read some bytes after the newline, which we + * promised not to do. + */ + char_to_read = 1; + } else { + /* char_to_read = min(key_size - i, buflen - i) */ + char_to_read = key_size < buflen ? + key_size - i : buflen - i; + } + char_read = read_buffer(fd, &pass[i], char_to_read); + if (char_read < 0) { + log_err(cd, _("Error reading passphrase.")); + r = -EPIPE; + goto out_err; + } - memcpy(frontPadBuf + frontHang, buf, innerCount); + if (char_read == 0) + break; + /* Stop on newline only if not requested read from keyfile */ + if ((flags & CRYPT_KEYFILE_STOP_EOL) && pass[i] == '\n') { + newline = 1; + pass[i] = '\0'; + break; + } + } - if (lseek(fd, offset - frontHang, SEEK_SET) < 0) - goto out; + /* Fail if piped input dies reading nothing */ + if (!i && !regular_file && !newline) { + log_err(cd, _("Nothing to read on input.")); + r = -EPIPE; + goto out_err; + } - r = write(fd, frontPadBuf, bsize); - if (r < 0 || r != bsize) - goto out; + /* Fail if we exceeded internal default (no specified size) */ + if (unlimited_read && i == key_size) { + log_err(cd, _("Maximum keyfile size exceeded.")); + goto out_err; + } - buf += innerCount; - count -= innerCount; + if (!unlimited_read && i != key_size) { + log_err(cd, _("Cannot read requested amount of data.")); + goto out_err; } - ret = count ? write_blockwise(fd, bsize, buf, count) : 0; - if (ret >= 0) - ret += innerCount; -out: - free(frontPadBuf_base); + *key = pass; + *key_size_read = i; + r = 0; +out_err: + if (fd != STDIN_FILENO) + close(fd); - return ret; + if (r) + crypt_safe_free(pass); + return r; } -/* MEMLOCK */ -#define DEFAULT_PROCESS_PRIORITY -18 - -static int _priority; -static int _memlock_count = 0; +int crypt_keyfile_read(struct crypt_device *cd, const char *keyfile, + char **key, size_t *key_size_read, + size_t keyfile_offset, size_t keyfile_size_max, + uint32_t flags) +{ + return crypt_keyfile_device_read(cd, keyfile, key, key_size_read, + keyfile_offset, keyfile_size_max, flags); +} -// return 1 if memory is locked -int crypt_memlock_inc(struct crypt_device *ctx) +int kernel_version(uint64_t *kversion) { - if (!_memlock_count++) { - log_dbg("Locking memory."); - if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { - log_dbg("Cannot lock memory with mlockall."); - _memlock_count--; - return 0; - } - errno = 0; - if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno) - log_err(ctx, _("Cannot get process priority.\n")); - else - if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY)) - log_dbg("setpriority %d failed: %s", - DEFAULT_PROCESS_PRIORITY, strerror(errno)); + struct utsname uts; + uint16_t maj, min, patch, rel; + int r = -EINVAL; + + if (uname(&uts) < 0) + return r; + + if (sscanf(uts.release, "%" SCNu16 ".%" SCNu16 ".%" SCNu16 "-%" SCNu16, + &maj, &min, &patch, &rel) == 4) + r = 0; + else if (sscanf(uts.release, "%" SCNu16 ".%" SCNu16 ".%" SCNu16, + &maj, &min, &patch) == 3) { + rel = 0; + r = 0; } - return _memlock_count ? 1 : 0; + + if (!r) + *kversion = version(maj, min, patch, rel); + + return r; } -int crypt_memlock_dec(struct crypt_device *ctx) +bool crypt_string_in(const char *str, char **list, size_t list_size) { - if (_memlock_count && (!--_memlock_count)) { - log_dbg("Unlocking memory."); - if (munlockall() == -1) - log_err(ctx, _("Cannot unlock memory.\n")); - if (setpriority(PRIO_PROCESS, 0, _priority)) - log_dbg("setpriority %d failed: %s", _priority, strerror(errno)); - } - return _memlock_count ? 1 : 0; + size_t i; + + for (i = 0; *list && i < list_size; i++, list++) + if (!strcmp(str, *list)) + return true; + + return false; +} + +/* compare two strings (allows NULL values) */ +int crypt_strcmp(const char *a, const char *b) +{ + if (!a && !b) + return 0; + else if (!a || !b) + return 1; + return strcmp(a, b); } diff --git a/lib/utils_benchmark.c b/lib/utils_benchmark.c index 1e4469b..f5c677a 100644 --- a/lib/utils_benchmark.c +++ b/lib/utils_benchmark.c @@ -1,8 +1,8 @@ /* - * libcryptsetup - cryptsetup library, cipher bechmark + * libcryptsetup - cryptsetup library, cipher benchmark * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2013, Milan Broz + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,165 +21,9 @@ #include #include -#include #include "internal.h" -/* - * This is not simulating storage, so using disk block causes extreme overhead. - * Let's use some fixed block size where results are more reliable... - */ -#define CIPHER_BLOCK_BYTES 65536 - -/* - * If the measured value is lower, encrypted buffer is probably too small - * and calculated values are not reliable. - */ -#define CIPHER_TIME_MIN_MS 0.001 - -/* - * The whole test depends on Linux kernel usermode crypto API for now. - * (The same implementations are used in dm-crypt though.) - */ - -struct cipher_perf { - char name[32]; - char mode[32]; - char *key; - size_t key_length; - char *iv; - size_t iv_length; - size_t buffer_size; -}; - -static int time_ms(struct timespec *start, struct timespec *end, double *ms) -{ - double start_ms, end_ms; - - start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000); - end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000); - - *ms = end_ms - start_ms; - return 0; -} - -static int cipher_perf_one(struct cipher_perf *cp, char *buf, - size_t buf_size, int enc) -{ - struct crypt_cipher *cipher = NULL; - size_t done = 0, block = CIPHER_BLOCK_BYTES; - int r; - - if (buf_size < block) - block = buf_size; - - r = crypt_cipher_init(&cipher, cp->name, cp->mode, cp->key, cp->key_length); - if (r < 0) { - log_dbg("Cannot initialise cipher %s, mode %s.", cp->name, cp->mode); - return r; - } - - while (done < buf_size) { - if ((done + block) > buf_size) - block = buf_size - done; - - if (enc) - r = crypt_cipher_encrypt(cipher, &buf[done], &buf[done], - block, cp->iv, cp->iv_length); - else - r = crypt_cipher_decrypt(cipher, &buf[done], &buf[done], - block, cp->iv, cp->iv_length); - if (r < 0) - break; - - done += block; - } - - crypt_cipher_destroy(cipher); - - return r; -} -static int cipher_measure(struct cipher_perf *cp, char *buf, - size_t buf_size, int encrypt, double *ms) -{ - struct timespec start, end; - int r; - - /* - * Using getrusage would be better here but the precision - * is not adequate, so better stick with CLOCK_MONOTONIC - */ - if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) - return -EINVAL; - - r = cipher_perf_one(cp, buf, buf_size, encrypt); - if (r < 0) - return r; - - if (clock_gettime(CLOCK_MONOTONIC, &end) < 0) - return -EINVAL; - - r = time_ms(&start, &end, ms); - if (r < 0) - return r; - - if (*ms < CIPHER_TIME_MIN_MS) { - log_dbg("Measured cipher runtime (%1.6f) is too low.", *ms); - return -ERANGE; - } - - return 0; -} - -static double speed_mbs(unsigned long bytes, double ms) -{ - double speed = bytes, s = ms / 1000.; - - return speed / (1024 * 1024) / s; -} - -static int cipher_perf(struct cipher_perf *cp, - double *encryption_mbs, double *decryption_mbs) -{ - double ms_enc, ms_dec, ms; - int r, repeat_enc, repeat_dec; - void *buf = NULL; - - if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size)) - return -ENOMEM; - - ms_enc = 0.0; - repeat_enc = 1; - while (ms_enc < 1000.0) { - r = cipher_measure(cp, buf, cp->buffer_size, 1, &ms); - if (r < 0) { - free(buf); - return r; - } - ms_enc += ms; - repeat_enc++; - } - - ms_dec = 0.0; - repeat_dec = 1; - while (ms_dec < 1000.0) { - r = cipher_measure(cp, buf, cp->buffer_size, 0, &ms); - if (r < 0) { - free(buf); - return r; - } - ms_dec += ms; - repeat_dec++; - } - - free(buf); - - *encryption_mbs = speed_mbs(cp->buffer_size * repeat_enc, ms_enc); - *decryption_mbs = speed_mbs(cp->buffer_size * repeat_dec, ms_dec); - - return 0; -} - int crypt_benchmark(struct crypt_device *cd, const char *cipher, const char *cipher_mode, @@ -189,15 +33,11 @@ int crypt_benchmark(struct crypt_device *cd, double *encryption_mbs, double *decryption_mbs) { - struct cipher_perf cp = { - .key_length = volume_key_size, - .iv_length = iv_size, - .buffer_size = buffer_size, - }; - char *c; + void *buffer = NULL; + char *iv = NULL, *key = NULL, mode[MAX_CIPHER_LEN], *c; int r; - if (!cipher || !cipher_mode || !volume_key_size) + if (!cipher || !cipher_mode || !volume_key_size || !encryption_mbs || !decryption_mbs) return -EINVAL; r = init_crypto(cd); @@ -205,58 +45,171 @@ int crypt_benchmark(struct crypt_device *cd, return r; r = -ENOMEM; + if (posix_memalign(&buffer, crypt_getpagesize(), buffer_size)) + goto out; + + r = crypt_cipher_ivsize(cipher, cipher_mode); + if (r >= 0 && iv_size != (size_t)r) { + log_dbg(cd, "IV length for benchmark adjusted to %i bytes (requested %zu).", r, iv_size); + iv_size = r; + } + if (iv_size) { - cp.iv = malloc(iv_size); - if (!cp.iv) + iv = malloc(iv_size); + if (!iv) goto out; - crypt_random_get(cd, cp.iv, iv_size, CRYPT_RND_NORMAL); + crypt_random_get(cd, iv, iv_size, CRYPT_RND_NORMAL); } - cp.key = malloc(volume_key_size); - if (!cp.key) + key = malloc(volume_key_size); + if (!key) goto out; - crypt_random_get(cd, cp.key, volume_key_size, CRYPT_RND_NORMAL); - strncpy(cp.name, cipher, sizeof(cp.name)-1); - strncpy(cp.mode, cipher_mode, sizeof(cp.mode)-1); + crypt_random_get(cd, key, volume_key_size, CRYPT_RND_NORMAL); + strncpy(mode, cipher_mode, sizeof(mode)-1); /* Ignore IV generator */ - if ((c = strchr(cp.mode, '-'))) + if ((c = strchr(mode, '-'))) *c = '\0'; - r = cipher_perf(&cp, encryption_mbs, decryption_mbs); + r = crypt_cipher_perf_kernel(cipher, cipher_mode, buffer, buffer_size, key, volume_key_size, + iv, iv_size, encryption_mbs, decryption_mbs); + + if (r == -ERANGE) + log_dbg(cd, "Measured cipher runtime is too low."); + else if (r) + log_dbg(cd, "Cannot initialize cipher %s, mode %s, key size %zu, IV size %zu.", + cipher, cipher_mode, volume_key_size, iv_size); out: - free(cp.key); - free(cp.iv); + free(buffer); + free(key); + free(iv); + return r; } -int crypt_benchmark_kdf(struct crypt_device *cd, - const char *kdf, - const char *hash, +int crypt_benchmark_pbkdf(struct crypt_device *cd, + struct crypt_pbkdf_type *pbkdf, const char *password, size_t password_size, const char *salt, size_t salt_size, - uint64_t *iterations_sec) + size_t volume_key_size, + int (*progress)(uint32_t time_ms, void *usrptr), + void *usrptr) { int r; + const char *kdf_opt; - if (!iterations_sec) + if (!pbkdf || (!password && password_size)) return -EINVAL; r = init_crypto(cd); if (r < 0) return r; - if (!strncmp(kdf, "pbkdf2", 6)) - r = crypt_pbkdf_check(kdf, hash, password, password_size, - salt, salt_size, iterations_sec); - else - r = -EINVAL; + kdf_opt = !strcmp(pbkdf->type, CRYPT_KDF_PBKDF2) ? pbkdf->hash : ""; + + log_dbg(cd, "Running %s(%s) benchmark.", pbkdf->type, kdf_opt); + + r = crypt_pbkdf_perf(pbkdf->type, pbkdf->hash, password, password_size, + salt, salt_size, volume_key_size, pbkdf->time_ms, + pbkdf->max_memory_kb, pbkdf->parallel_threads, + &pbkdf->iterations, &pbkdf->max_memory_kb, progress, usrptr); if (!r) - log_dbg("KDF %s, hash %s: %" PRIu64 " iterations per second.", - kdf, hash, *iterations_sec); + log_dbg(cd, "Benchmark returns %s(%s) %u iterations, %u memory, %u threads (for %zu-bits key).", + pbkdf->type, kdf_opt, pbkdf->iterations, pbkdf->max_memory_kb, + pbkdf->parallel_threads, volume_key_size * 8); + return r; +} + +struct benchmark_usrptr { + struct crypt_device *cd; + struct crypt_pbkdf_type *pbkdf; +}; + +static int benchmark_callback(uint32_t time_ms, void *usrptr) +{ + struct benchmark_usrptr *u = usrptr; + + log_dbg(u->cd, "PBKDF benchmark: memory cost = %u, iterations = %u, " + "threads = %u (took %u ms)", u->pbkdf->max_memory_kb, + u->pbkdf->iterations, u->pbkdf->parallel_threads, time_ms); + + return 0; +} + +/* + * Used in internal places to benchmark crypt_device context PBKDF. + * Once requested parameters are benchmarked, iterations attribute is set, + * and the benchmarked values can be reused. + * Note that memory cost can be changed after benchmark (if used). + * NOTE: You need to check that you are benchmarking for the same key size. + */ +int crypt_benchmark_pbkdf_internal(struct crypt_device *cd, + struct crypt_pbkdf_type *pbkdf, + size_t volume_key_size) +{ + struct crypt_pbkdf_limits pbkdf_limits; + double PBKDF2_tmp; + uint32_t ms_tmp; + int r = -EINVAL; + struct benchmark_usrptr u = { + .cd = cd, + .pbkdf = pbkdf + }; + + r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits); + if (r) + return r; + + if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) { + if (pbkdf->iterations) { + log_dbg(cd, "Reusing PBKDF values (no benchmark flag is set)."); + return 0; + } + log_err(cd, _("PBKDF benchmark disabled but iterations not set.")); + return -EINVAL; + } + + /* For PBKDF2 run benchmark always. Also note it depends on volume_key_size! */ + if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) { + /* + * For PBKDF2 it is enough to run benchmark for only 1 second + * and interpolate final iterations value from it. + */ + ms_tmp = pbkdf->time_ms; + pbkdf->time_ms = 1000; + pbkdf->parallel_threads = 0; /* N/A in PBKDF2 */ + pbkdf->max_memory_kb = 0; /* N/A in PBKDF2 */ + + r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, "bar", 3, + volume_key_size, &benchmark_callback, &u); + pbkdf->time_ms = ms_tmp; + if (r < 0) { + log_err(cd, _("Not compatible PBKDF2 options (using hash algorithm %s)."), + pbkdf->hash); + return r; + } + + PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.); + if (PBKDF2_tmp > (double)UINT32_MAX) + return -EINVAL; + pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, pbkdf_limits.min_iterations); + } else { + /* Already benchmarked */ + if (pbkdf->iterations) { + log_dbg(cd, "Reusing PBKDF values."); + return 0; + } + + r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, + "0123456789abcdef0123456789abcdef", 32, + volume_key_size, &benchmark_callback, &u); + if (r < 0) + log_err(cd, _("Not compatible PBKDF options.")); + } + return r; } diff --git a/lib/utils_blkid.c b/lib/utils_blkid.c new file mode 100644 index 0000000..0e3e7fd --- /dev/null +++ b/lib/utils_blkid.c @@ -0,0 +1,323 @@ +/* + * blkid probe utilities + * + * Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include "utils_blkid.h" +#include "utils_io.h" + +#ifdef HAVE_BLKID +#include +/* make bad checksums flag optional */ +#ifndef BLKID_SUBLKS_BADCSUM +#define BLKID_SUBLKS_BADCSUM 0 +#endif +struct blkid_handle { + int fd; + blkid_probe pr; +}; +#ifndef HAVE_BLKID_WIPE +static size_t crypt_getpagesize(void) +{ + long r = sysconf(_SC_PAGESIZE); + return r <= 0 ? 4096 : (size_t)r; +} +#endif +#endif + +void blk_set_chains_for_wipes(struct blkid_handle *h) +{ +#ifdef HAVE_BLKID + blkid_probe_enable_partitions(h->pr, 1); + blkid_probe_set_partitions_flags(h->pr, 0 +#ifdef HAVE_BLKID_WIPE + | BLKID_PARTS_MAGIC +#endif + ); + + blkid_probe_enable_superblocks(h->pr, 1); + blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_LABEL | + BLKID_SUBLKS_UUID | + BLKID_SUBLKS_TYPE | + BLKID_SUBLKS_USAGE | + BLKID_SUBLKS_VERSION | + BLKID_SUBLKS_MAGIC | + BLKID_SUBLKS_BADCSUM); +#endif +} + +void blk_set_chains_for_full_print(struct blkid_handle *h) +{ + blk_set_chains_for_wipes(h); +} + +void blk_set_chains_for_fast_detection(struct blkid_handle *h) +{ +#ifdef HAVE_BLKID + blkid_probe_enable_partitions(h->pr, 1); + blkid_probe_set_partitions_flags(h->pr, 0); + + blkid_probe_enable_superblocks(h->pr, 1); + blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_TYPE); +#endif +} + +int blk_init_by_path(struct blkid_handle **h, const char *path) +{ + int r = -ENOTSUP; +#ifdef HAVE_BLKID + struct blkid_handle *tmp = malloc(sizeof(*tmp)); + if (!tmp) + return -ENOMEM; + + tmp->fd = -1; + + tmp->pr = blkid_new_probe_from_filename(path); + if (!tmp->pr) { + free(tmp); + return -EINVAL; + } + + *h = tmp; + + r = 0; +#endif + return r; +} + +int blk_init_by_fd(struct blkid_handle **h, int fd) +{ + int r = -ENOTSUP; +#ifdef HAVE_BLKID + struct blkid_handle *tmp = malloc(sizeof(*tmp)); + if (!tmp) + return -ENOMEM; + + tmp->pr = blkid_new_probe(); + if (!tmp->pr) { + free(tmp); + return -EINVAL; + } + + if (blkid_probe_set_device(tmp->pr, fd, 0, 0)) { + blkid_free_probe(tmp->pr); + free(tmp); + return -EINVAL; + } + + tmp->fd = fd; + + *h = tmp; + + r = 0; +#endif + return r; +} + +int blk_superblocks_filter_luks(struct blkid_handle *h) +{ + int r = -ENOTSUP; +#ifdef HAVE_BLKID + char luks[] = "crypto_LUKS"; + char *luks_filter[] = { + luks, + NULL + }; + r = blkid_probe_filter_superblocks_type(h->pr, BLKID_FLTR_NOTIN, luks_filter); +#endif + return r; +} + +blk_probe_status blk_probe(struct blkid_handle *h) +{ + blk_probe_status pr = PRB_FAIL; +#ifdef HAVE_BLKID + int r = blkid_do_probe(h->pr); + + if (r == 0) + pr = PRB_OK; + else if (r == 1) + pr = PRB_EMPTY; +#endif + return pr; +} + +blk_probe_status blk_safeprobe(struct blkid_handle *h) +{ + int r = -1; +#ifdef HAVE_BLKID + r = blkid_do_safeprobe(h->pr); +#endif + switch (r) { + case -2: + return PRB_AMBIGUOUS; + case 1: + return PRB_EMPTY; + case 0: + return PRB_OK; + default: + return PRB_FAIL; + } +} + +int blk_is_partition(struct blkid_handle *h) +{ + int r = 0; +#ifdef HAVE_BLKID + r = blkid_probe_has_value(h->pr, "PTTYPE"); +#endif + return r; +} + +int blk_is_superblock(struct blkid_handle *h) +{ + int r = 0; +#ifdef HAVE_BLKID + r = blkid_probe_has_value(h->pr, "TYPE"); +#endif + return r; +} + +const char *blk_get_partition_type(struct blkid_handle *h) +{ + const char *value = NULL; +#ifdef HAVE_BLKID + (void) blkid_probe_lookup_value(h->pr, "PTTYPE", &value, NULL); +#endif + return value; +} + +const char *blk_get_superblock_type(struct blkid_handle *h) +{ + const char *value = NULL; +#ifdef HAVE_BLKID + (void) blkid_probe_lookup_value(h->pr, "TYPE", &value, NULL); +#endif + return value; +} + +void blk_free(struct blkid_handle *h) +{ +#ifdef HAVE_BLKID + if (!h) + return; + + if (h->pr) + blkid_free_probe(h->pr); + + free(h); +#endif +} + +#ifdef HAVE_BLKID +#ifndef HAVE_BLKID_WIPE +static int blk_step_back(struct blkid_handle *h) +{ +#ifdef HAVE_BLKID_STEP_BACK + return blkid_probe_step_back(h->pr); +#else + blkid_reset_probe(h->pr); + blkid_probe_set_device(h->pr, h->fd, 0, 0); + return 0; +#endif +} +#endif /* not HAVE_BLKID_WIPE */ +#endif /* HAVE_BLKID */ + +int blk_do_wipe(struct blkid_handle *h) +{ +#ifdef HAVE_BLKID +#ifdef HAVE_BLKID_WIPE + return blkid_do_wipe(h->pr, 0); +#else + const char *offset; + off_t offset_val; + void *buf; + ssize_t ret; + size_t alignment, len, bsize = blkid_probe_get_sectorsize(h->pr); + + if (h->fd < 0 || !bsize) + return -EINVAL; + + if (blk_is_partition(h)) { + if (blkid_probe_lookup_value(h->pr, "PTMAGIC_OFFSET", &offset, NULL)) + return -EINVAL; + if (blkid_probe_lookup_value(h->pr, "PTMAGIC", NULL, &len)) + return -EINVAL; + } else if (blk_is_superblock(h)) { + if (blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL)) + return -EINVAL; + if (blkid_probe_lookup_value(h->pr, "SBMAGIC", NULL, &len)) + return -EINVAL; + } else + return 0; + + alignment = crypt_getpagesize(); + + if (posix_memalign(&buf, alignment, len)) + return -EINVAL; + memset(buf, 0, len); + + offset_val = strtoll(offset, NULL, 10); + + /* TODO: missing crypt_wipe_fd() */ + ret = write_lseek_blockwise(h->fd, bsize, alignment, buf, len, offset_val); + free(buf); + if (ret < 0) + return -EIO; + + if ((size_t)ret == len) { + blk_step_back(h); + return 0; + } + + return -EIO; +#endif +#else /* HAVE_BLKID */ + return -ENOTSUP; +#endif +} + +int blk_supported(void) +{ + int r = 0; +#ifdef HAVE_BLKID + r = 1; +#endif + return r; +} + +off_t blk_get_offset(struct blkid_handle *h) +{ + off_t offset_value = -1; +#ifdef HAVE_BLKID + const char *offset; + if (blk_is_superblock(h)) { + if (!blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL)) + offset_value = strtoll(offset, NULL, 10); + } else if (blk_is_partition(h) && !blkid_probe_lookup_value(h->pr, "PTMAGIC_OFFSET", &offset, NULL)) + offset_value = strtoll(offset, NULL, 10); +#endif + return offset_value; +} diff --git a/lib/utils_blkid.h b/lib/utils_blkid.h new file mode 100644 index 0000000..ca50da7 --- /dev/null +++ b/lib/utils_blkid.h @@ -0,0 +1,64 @@ +/* + * blkid probe utilities + * + * Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _UTILS_BLKID_H +#define _UTILS_BLKID_H + +struct blkid_handle; + +typedef enum { PRB_OK = 0, PRB_EMPTY, PRB_AMBIGUOUS, PRB_FAIL } blk_probe_status; + +int blk_init_by_path(struct blkid_handle **h, const char *path); + +void blk_free(struct blkid_handle *h); + +/* + * WARNING: This will reset file description offset as if + * lseek(devfd, 0, SEEK_SET) was called! + */ +int blk_init_by_fd(struct blkid_handle **h, int fd); + +void blk_set_chains_for_wipes(struct blkid_handle *h); + +void blk_set_chains_for_full_print(struct blkid_handle *h); + +void blk_set_chains_for_fast_detection(struct blkid_handle *h); + +int blk_superblocks_filter_luks(struct blkid_handle *h); + +blk_probe_status blk_safeprobe(struct blkid_handle *h); + +blk_probe_status blk_probe(struct blkid_handle *h); + +int blk_is_partition(struct blkid_handle *h); + +int blk_is_superblock(struct blkid_handle *h); + +const char *blk_get_partition_type(struct blkid_handle *h); + +const char *blk_get_superblock_type(struct blkid_handle *h); + +int blk_do_wipe(struct blkid_handle *h); + +int blk_supported(void); + +off_t blk_get_offset(struct blkid_handle *h); + +#endif diff --git a/lib/utils_crypt.c b/lib/utils_crypt.c index 5cfe477..17dc6d8 100644 --- a/lib/utils_crypt.c +++ b/lib/utils_crypt.c @@ -1,9 +1,9 @@ /* * utils_crypt - cipher utilities for cryptsetup * - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,37 +21,23 @@ */ #include -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include "libcryptsetup.h" -#include "nls.h" #include "utils_crypt.h" -#define log_dbg(x) crypt_log(NULL, CRYPT_LOG_DEBUG, x) -#define log_err(cd, x) crypt_log(cd, CRYPT_LOG_ERROR, x) - -struct safe_allocation { - size_t size; - char data[0]; -}; - int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, char *cipher_mode) { + if (!s || !cipher || !cipher_mode) + return -EINVAL; + if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s", cipher, cipher_mode) == 2) { if (!strcmp(cipher_mode, "plain")) - strncpy(cipher_mode, "cbc-plain", 10); + strcpy(cipher_mode, "cbc-plain"); if (key_nums) { char *tmp = strchr(cipher, ':'); *key_nums = tmp ? atoi(++tmp) : 1; @@ -63,16 +49,16 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, } /* Short version for "empty" cipher */ - if (!strcmp(s, "null")) { - strncpy(cipher, "cipher_null", MAX_CIPHER_LEN); - strncpy(cipher_mode, "ecb", 9); + if (!strcmp(s, "null") || !strcmp(s, "cipher_null")) { + strcpy(cipher, "cipher_null"); + strcpy(cipher_mode, "ecb"); if (key_nums) *key_nums = 0; return 0; } if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]", cipher) == 1) { - strncpy(cipher_mode, "cbc-plain", 10); + strcpy(cipher_mode, "cbc-plain"); if (key_nums) *key_nums = 1; return 0; @@ -81,383 +67,86 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, return -EINVAL; } -/* - * Replacement for memset(s, 0, n) on stack that can be optimized out - * Also used in safe allocations for explicit memory wipe. - */ -void crypt_memzero(void *s, size_t n) -{ - volatile uint8_t *p = (volatile uint8_t *)s; - - while(n--) - *p++ = 0; -} - -/* safe allocations */ -void *crypt_safe_alloc(size_t size) -{ - struct safe_allocation *alloc; - - if (!size) - return NULL; - - alloc = malloc(size + offsetof(struct safe_allocation, data)); - if (!alloc) - return NULL; - - alloc->size = size; - crypt_memzero(&alloc->data, size); - - /* coverity[leaked_storage] */ - return &alloc->data; -} - -void crypt_safe_free(void *data) -{ - struct safe_allocation *alloc; - - if (!data) - return; - - alloc = (struct safe_allocation *) - ((char *)data - offsetof(struct safe_allocation, data)); - - crypt_memzero(data, alloc->size); - - alloc->size = 0x55aa55aa; - free(alloc); -} - -void *crypt_safe_realloc(void *data, size_t size) -{ - struct safe_allocation *alloc; - void *new_data; - - new_data = crypt_safe_alloc(size); - - if (new_data && data) { - - alloc = (struct safe_allocation *) - ((char *)data - offsetof(struct safe_allocation, data)); - - if (size > alloc->size) - size = alloc->size; - - memcpy(new_data, data, size); - } - - crypt_safe_free(data); - return new_data; -} - -/* Password reading helpers */ -static int untimed_read(int fd, char *pass, size_t maxlen) -{ - ssize_t i; - - i = read(fd, pass, maxlen); - if (i > 0) { - pass[i-1] = '\0'; - i = 0; - } else if (i == 0) { /* EOF */ - *pass = 0; - i = -1; - } - return i; -} - -static int timed_read(int fd, char *pass, size_t maxlen, long timeout) -{ - struct timeval t; - fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */ - int failed = -1; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - t.tv_sec = timeout; - t.tv_usec = 0; - - if (select(fd+1, &fds, NULL, NULL, &t) > 0) - failed = untimed_read(fd, pass, maxlen); - - return failed; -} - -static int interactive_pass(const char *prompt, char *pass, size_t maxlen, - long timeout) +int crypt_parse_hash_integrity_mode(const char *s, char *integrity) { - struct termios orig, tmp; - int failed = -1; - int infd, outfd; - - if (maxlen < 1) - return failed; - - /* Read and write to /dev/tty if available */ - infd = open("/dev/tty", O_RDWR); - if (infd == -1) { - infd = STDIN_FILENO; - outfd = STDERR_FILENO; - } else - outfd = infd; + char mode[MAX_CIPHER_LEN], hash[MAX_CIPHER_LEN]; + int r; - if (tcgetattr(infd, &orig)) - goto out_err; - - memcpy(&tmp, &orig, sizeof(tmp)); - tmp.c_lflag &= ~ECHO; - - if (prompt && write(outfd, prompt, strlen(prompt)) < 0) - goto out_err; + if (!s || !integrity || strchr(s, '(') || strchr(s, ')')) + return -EINVAL; - tcsetattr(infd, TCSAFLUSH, &tmp); - if (timeout) - failed = timed_read(infd, pass, maxlen, timeout); + r = sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s", mode, hash); + if (r == 2) + r = snprintf(integrity, MAX_CIPHER_LEN, "%s(%s)", mode, hash); + else if (r == 1) + r = snprintf(integrity, MAX_CIPHER_LEN, "%s", mode); else - failed = untimed_read(infd, pass, maxlen); - tcsetattr(infd, TCSAFLUSH, &orig); + return -EINVAL; -out_err: - if (!failed && write(outfd, "\n", 1)) {}; + if (r < 0 || r == MAX_CIPHER_LEN) + return -EINVAL; - if (infd != STDIN_FILENO) - close(infd); - return failed; + return 0; } -static int crypt_get_key_tty(const char *prompt, - char **key, size_t *key_size, - int timeout, int verify, - struct crypt_device *cd) +int crypt_parse_integrity_mode(const char *s, char *integrity, + int *integrity_key_size) { - int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX; - int r = -EINVAL; - char *pass = NULL, *pass_verify = NULL; - - log_dbg("Interactive passphrase entry requested."); + int ks = 0, r = 0; - pass = crypt_safe_alloc(key_size_max + 1); - if (!pass) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - return -ENOMEM; - } - - if (interactive_pass(prompt, pass, key_size_max, timeout)) { - log_err(cd, _("Error reading passphrase from terminal.\n")); - goto out_err; - } - pass[key_size_max] = '\0'; - - if (verify) { - pass_verify = crypt_safe_alloc(key_size_max); - if (!pass_verify) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - r = -ENOMEM; - goto out_err; - } + if (!s || !integrity) + return -EINVAL; - if (interactive_pass(_("Verify passphrase: "), - pass_verify, key_size_max, timeout)) { - log_err(cd, _("Error reading passphrase from terminal.\n")); - goto out_err; - } + // FIXME: do not hardcode it here + + /* AEAD modes */ + if (!strcmp(s, "aead") || + !strcmp(s, "poly1305") || + !strcmp(s, "none")) { + strncpy(integrity, s, MAX_CIPHER_LEN); + ks = 0; + } else if (!strcmp(s, "hmac-sha1")) { + strncpy(integrity, "hmac(sha1)", MAX_CIPHER_LEN); + ks = 20; + } else if (!strcmp(s, "hmac-sha256")) { + strncpy(integrity, "hmac(sha256)", MAX_CIPHER_LEN); + ks = 32; + } else if (!strcmp(s, "hmac-sha512")) { + ks = 64; + strncpy(integrity, "hmac(sha512)", MAX_CIPHER_LEN); + } else if (!strcmp(s, "cmac-aes")) { + ks = 16; + strncpy(integrity, "cmac(aes)", MAX_CIPHER_LEN); + } else + r = -EINVAL; - if (strncmp(pass, pass_verify, key_size_max)) { - log_err(cd, _("Passphrases do not match.\n")); - r = -EPERM; - goto out_err; - } - } + if (integrity_key_size) + *integrity_key_size = ks; - *key = pass; - *key_size = strlen(pass); - r = 0; -out_err: - crypt_safe_free(pass_verify); - if (r) - crypt_safe_free(pass); return r; } -/* - * A simple call to lseek(3) might not be possible for some inputs (e.g. - * reading from a pipe), so this function instead reads of up to BUFSIZ bytes - * at a time until the specified number of bytes. It returns -1 on read error - * or when it reaches EOF before the requested number of bytes have been - * discarded. - */ -static int keyfile_seek(int fd, size_t bytes) +int crypt_parse_pbkdf(const char *s, const char **pbkdf) { - char tmp[BUFSIZ]; - size_t next_read; - ssize_t bytes_r; - off_t r; + const char *tmp = NULL; - r = lseek(fd, bytes, SEEK_CUR); - if (r > 0) - return 0; - if (r < 0 && errno != ESPIPE) - return -1; - - while (bytes > 0) { - /* figure out how much to read */ - next_read = bytes > sizeof(tmp) ? sizeof(tmp) : bytes; - - bytes_r = read(fd, tmp, next_read); - if (bytes_r < 0) { - if (errno == EINTR) - continue; - - /* read error */ - return -1; - } - - if (bytes_r == 0) - /* EOF */ - break; - - bytes -= bytes_r; - } - - return bytes == 0 ? 0 : -1; -} - -/* - * Note: --key-file=- is interpreted as a read from a binary file (stdin) - * key_size_max == 0 means detect maximum according to input type (tty/file) - * timeout and verify options only applies to tty input - */ -int crypt_get_key(const char *prompt, - char **key, size_t *key_size, - size_t keyfile_offset, size_t keyfile_size_max, - const char *key_file, int timeout, int verify, - struct crypt_device *cd) -{ - int fd, regular_file, read_stdin, char_read, unlimited_read = 0; - int r = -EINVAL; - char *pass = NULL; - size_t buflen, i, file_read_size; - struct stat st; - - *key = NULL; - *key_size = 0; - - /* Passphrase read from stdin? */ - read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0; - - if (read_stdin && isatty(STDIN_FILENO)) { - if (keyfile_offset) { - log_err(cd, _("Cannot use offset with terminal input.\n")); - return -EINVAL; - } - return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd); - } - - if (read_stdin) - log_dbg("STDIN descriptor passphrase entry requested."); - else - log_dbg("File descriptor passphrase entry requested."); - - /* If not requsted otherwise, we limit input to prevent memory exhaustion */ - if (keyfile_size_max == 0) { - keyfile_size_max = DEFAULT_KEYFILE_SIZE_MAXKB * 1024; - unlimited_read = 1; - } - - fd = read_stdin ? STDIN_FILENO : open(key_file, O_RDONLY); - if (fd < 0) { - log_err(cd, _("Failed to open key file.\n")); + if (!s) return -EINVAL; - } - - /* use 4k for buffer (page divisor but avoid huge pages) */ - buflen = 4096 - sizeof(struct safe_allocation); - regular_file = 0; - if(!read_stdin) { - if(stat(key_file, &st) < 0) { - log_err(cd, _("Failed to stat key file.\n")); - goto out_err; - } - if(S_ISREG(st.st_mode)) { - regular_file = 1; - file_read_size = (size_t)st.st_size; - if (keyfile_offset > file_read_size) { - log_err(cd, _("Cannot seek to requested keyfile offset.\n")); - goto out_err; - } - file_read_size -= keyfile_offset; + if (!strcasecmp(s, CRYPT_KDF_PBKDF2)) + tmp = CRYPT_KDF_PBKDF2; + else if (!strcasecmp(s, CRYPT_KDF_ARGON2I)) + tmp = CRYPT_KDF_ARGON2I; + else if (!strcasecmp(s, CRYPT_KDF_ARGON2ID)) + tmp = CRYPT_KDF_ARGON2ID; - /* known keyfile size, alloc it in one step */ - if (file_read_size >= keyfile_size_max) - buflen = keyfile_size_max; - else if (file_read_size) - buflen = file_read_size; - } - } - - pass = crypt_safe_alloc(buflen); - if (!pass) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - goto out_err; - } - - /* Discard keyfile_offset bytes on input */ - if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) { - log_err(cd, _("Cannot seek to requested keyfile offset.\n")); - goto out_err; - } - - for(i = 0; i < keyfile_size_max; i++) { - if(i == buflen) { - buflen += 4096; - pass = crypt_safe_realloc(pass, buflen); - if (!pass) { - log_err(cd, _("Out of memory while reading passphrase.\n")); - r = -ENOMEM; - goto out_err; - } - } - - char_read = read(fd, &pass[i], 1); - if (char_read < 0) { - log_err(cd, _("Error reading passphrase.\n")); - goto out_err; - } - - /* Stop on newline only if not requested read from keyfile */ - if(char_read == 0 || (!key_file && pass[i] == '\n')) - break; - } - - /* Fail if piped input dies reading nothing */ - if(!i && !regular_file) { - log_dbg("Nothing read on input."); - r = -EPIPE; - goto out_err; - } - - /* Fail if we exceeded internal default (no specified size) */ - if (unlimited_read && i == keyfile_size_max) { - log_err(cd, _("Maximum keyfile size exceeded.\n")); - goto out_err; - } - - if (!unlimited_read && i != keyfile_size_max) { - log_err(cd, _("Cannot read requested amount of data.\n")); - goto out_err; - } + if (!tmp) + return -EINVAL; - *key = pass; - *key_size = i; - r = 0; -out_err: - if(fd != STDIN_FILENO) - close(fd); + if (pbkdf) + *pbkdf = tmp; - if (r) - crypt_safe_free(pass); - return r; + return 0; } ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc) @@ -485,68 +174,3 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc) *result = bytes; return i; } - -/* - * Device size string parsing, suffixes: - * s|S - 512 bytes sectors - * k |K |m |M |g |G |t |T - 1024 base - * kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base - * kb |KB |mM |MB |gB |GB |tB |TB - 1000 base - */ -int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size) -{ - char *endp = NULL; - size_t len; - uint64_t mult_base, mult, tmp; - - *size = strtoull(s, &endp, 10); - if (!isdigit(s[0]) || - (errno == ERANGE && *size == ULLONG_MAX) || - (errno != 0 && *size == 0)) - return -EINVAL; - - if (!endp || !*endp) - return 0; - - len = strlen(endp); - /* Allow "B" and "iB" suffixes */ - if (len > 3 || - (len == 3 && (endp[1] != 'i' || endp[2] != 'B')) || - (len == 2 && endp[1] != 'B')) - return -EINVAL; - - if (len == 1 || len == 3) - mult_base = 1024; - else - mult_base = 1000; - - mult = 1; - switch (endp[0]) { - case 's': - case 'S': mult = 512; - break; - case 't': - case 'T': mult *= mult_base; - /* Fall through */ - case 'g': - case 'G': mult *= mult_base; - /* Fall through */ - case 'm': - case 'M': mult *= mult_base; - /* Fall through */ - case 'k': - case 'K': mult *= mult_base; - break; - default: - return -EINVAL; - } - - tmp = *size * mult; - if ((tmp / *size) != mult) { - log_dbg("Device size overflow."); - return -EINVAL; - } - - *size = tmp; - return 0; -} diff --git a/lib/utils_crypt.h b/lib/utils_crypt.h index 3da4842..32b77cb 100644 --- a/lib/utils_crypt.h +++ b/lib/utils_crypt.h @@ -1,9 +1,9 @@ /* * utils_crypt - cipher utilities for cryptsetup * - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,25 +29,13 @@ #define MAX_CIPHER_LEN_STR "31" #define MAX_KEYFILES 32 -struct crypt_device; - int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, char *cipher_mode); - -int crypt_get_key(const char *prompt, - char **key, size_t *key_size, - size_t keyfile_offset, size_t keyfile_size_max, - const char *key_file, - int timeout, int verify, - struct crypt_device *cd); - -void *crypt_safe_alloc(size_t size); -void crypt_safe_free(void *data); -void *crypt_safe_realloc(void *data, size_t size); - -void crypt_memzero(void *s, size_t n); +int crypt_parse_hash_integrity_mode(const char *s, char *integrity); +int crypt_parse_integrity_mode(const char *s, char *integrity, + int *integrity_key_size); +int crypt_parse_pbkdf(const char *s, const char **pbkdf); ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc); -int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size); #endif /* _UTILS_CRYPT_H */ diff --git a/lib/utils_device.c b/lib/utils_device.c index 46c2a0f..75449c0 100644 --- a/lib/utils_device.c +++ b/lib/utils_device.c @@ -1,10 +1,10 @@ /* * device backend utilities * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2015, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,16 +21,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include -#include #include #include #include #include #include #include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif +#ifdef HAVE_SYS_STATVFS_H +# include +#endif #include "internal.h" +#include "utils_device_locking.h" struct device { char *path; @@ -38,31 +45,61 @@ struct device { char *file_path; int loop_fd; - int o_direct:1; - int init_done:1; + int ro_dev_fd; + int dev_fd; + int dev_fd_excl; + + struct crypt_lock_handle *lh; + + unsigned int o_direct:1; + unsigned int init_done:1; /* path is bdev or loop already initialized */ + + /* cached values */ + size_t alignment; + size_t block_size; }; -static int device_block_size_fd(int fd, size_t *min_size) +static size_t device_fs_block_size_fd(int fd) +{ + size_t page_size = crypt_getpagesize(); + +#ifdef HAVE_SYS_STATVFS_H + struct statvfs buf; + + /* + * NOTE: some filesystems (NFS) returns bogus blocksize (1MB). + * Page-size io should always work and avoids increasing IO beyond aligned LUKS header. + */ + if (!fstatvfs(fd, &buf) && buf.f_bsize && buf.f_bsize <= page_size) + return (size_t)buf.f_bsize; +#endif + return page_size; +} + +static size_t device_block_size_fd(int fd, size_t *min_size) { struct stat st; - int bsize = 0, r = -EINVAL; + size_t bsize; + int arg; if (fstat(fd, &st) < 0) - return -EINVAL; + return 0; if (S_ISREG(st.st_mode)) - r = (int)crypt_getpagesize(); - else if (ioctl(fd, BLKSSZGET, &bsize) >= 0) - r = bsize; - else - r = -EINVAL; + bsize = device_fs_block_size_fd(fd); + else { + if (ioctl(fd, BLKSSZGET, &arg) < 0) + bsize = crypt_getpagesize(); + else + bsize = (size_t)arg; + } - if (r < 0 || !min_size) - return r; + if (!min_size) + return bsize; if (S_ISREG(st.st_mode)) { /* file can be empty as well */ - if (st.st_size > bsize) + if (st.st_size > (ssize_t)bsize) *min_size = bsize; else *min_size = st.st_size; @@ -74,15 +111,28 @@ static int device_block_size_fd(int fd, size_t *min_size) return bsize; } +static size_t device_alignment_fd(int devfd) +{ + long alignment = DEFAULT_MEM_ALIGNMENT; + +#ifdef _PC_REC_XFER_ALIGN + alignment = fpathconf(devfd, _PC_REC_XFER_ALIGN); + if (alignment < 0) + alignment = DEFAULT_MEM_ALIGNMENT; +#endif + return (size_t)alignment; +} + static int device_read_test(int devfd) { char buffer[512]; - int blocksize, r = -EIO; - size_t minsize = 0; + int r = -EIO; + size_t minsize = 0, blocksize, alignment; blocksize = device_block_size_fd(devfd, &minsize); + alignment = device_alignment_fd(devfd); - if (blocksize < 0) + if (!blocksize || !alignment) return -EINVAL; if (minsize == 0) @@ -91,30 +141,31 @@ static int device_read_test(int devfd) if (minsize > sizeof(buffer)) minsize = sizeof(buffer); - if (read_blockwise(devfd, blocksize, buffer, minsize) == (ssize_t)minsize) + if (read_blockwise(devfd, blocksize, alignment, buffer, minsize) == (ssize_t)minsize) r = 0; - crypt_memzero(buffer, sizeof(buffer)); + crypt_safe_memzero(buffer, sizeof(buffer)); return r; } /* * The direct-io is always preferred. The header is usually mapped to the same * device and can be accessed when the rest of device is mapped to data device. - * Using dirct-io encsures that we do not mess with data in cache. + * Using direct-io ensures that we do not mess with data in cache. * (But proper alignment should prevent this in the first place.) * The read test is needed to detect broken configurations (seen with remote * block devices) that allow open with direct-io but then fails on read. */ -static int device_ready(struct device *device, int check_directio) +static int device_ready(struct crypt_device *cd, struct device *device) { int devfd = -1, r = 0; struct stat st; + size_t tmp_size; - device->o_direct = 0; - if (check_directio) { - log_dbg("Trying to open and read device %s with direct-io.", + if (device->o_direct) { + log_dbg(cd, "Trying to open and read device %s with direct-io.", device_path(device)); + device->o_direct = 0; devfd = open(device_path(device), O_RDONLY | O_DIRECT); if (devfd >= 0) { if (device_read_test(devfd) == 0) { @@ -127,13 +178,13 @@ static int device_ready(struct device *device, int check_directio) } if (devfd < 0) { - log_dbg("Trying to open device %s without direct-io.", + log_dbg(cd, "Trying to open device %s without direct-io.", device_path(device)); devfd = open(device_path(device), O_RDONLY); } if (devfd < 0) { - log_err(NULL, _("Device %s doesn't exist or access denied.\n"), + log_err(cd, _("Device %s does not exist or access denied."), device_path(device)); return -EINVAL; } @@ -142,31 +193,175 @@ static int device_ready(struct device *device, int check_directio) r = -EINVAL; else if (!S_ISBLK(st.st_mode)) r = S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL; + if (r == -EINVAL) { + log_err(cd, _("Device %s is not compatible."), + device_path(device)); + close(devfd); + return r; + } + + /* Allow only increase (loop device) */ + tmp_size = device_alignment_fd(devfd); + if (tmp_size > device->alignment) + device->alignment = tmp_size; + + tmp_size = device_block_size_fd(devfd, NULL); + if (tmp_size > device->block_size) + device->block_size = tmp_size; close(devfd); return r; } -int device_open(struct device *device, int flags) +static int _open_locked(struct crypt_device *cd, struct device *device, int flags) { - int devfd; + int fd; + + log_dbg(cd, "Opening locked device %s", device_path(device)); + + if ((flags & O_ACCMODE) != O_RDONLY && device_locked_readonly(device->lh)) { + log_dbg(cd, "Cannot open locked device %s in write mode. Read lock held.", device_path(device)); + return -EAGAIN; + } + + fd = open(device_path(device), flags); + if (fd < 0) + return -errno; + + if (device_locked_verify(cd, fd, device->lh)) { + /* fd doesn't correspond to a locked resource */ + close(fd); + log_dbg(cd, "Failed to verify lock resource for device %s.", device_path(device)); + return -EINVAL; + } + + return fd; +} + +/* + * Common wrapper for device sync. + */ +void device_sync(struct crypt_device *cd, struct device *device) +{ + if (!device || device->dev_fd < 0) + return; + + if (fsync(device->dev_fd) == -1) + log_dbg(cd, "Cannot sync device %s.", device_path(device)); +} + +/* + * in non-locked mode returns always fd or -1 + * + * in locked mode: + * opened fd or one of: + * -EAGAIN : requested write mode while device being locked in via shared lock + * -EINVAL : invalid lock fd state + * -1 : all other errors + */ +static int device_open_internal(struct crypt_device *cd, struct device *device, int flags) +{ + int access, devfd; - flags |= O_SYNC; if (device->o_direct) flags |= O_DIRECT; - devfd = open(device_path(device), flags); + access = flags & O_ACCMODE; + if (access == O_WRONLY) + access = O_RDWR; + + if (access == O_RDONLY && device->ro_dev_fd >= 0) { + log_dbg(cd, "Reusing open r%c fd on device %s", 'o', device_path(device)); + return device->ro_dev_fd; + } else if (access == O_RDWR && device->dev_fd >= 0) { + log_dbg(cd, "Reusing open r%c fd on device %s", 'w', device_path(device)); + return device->dev_fd; + } + + if (device_locked(device->lh)) + devfd = _open_locked(cd, device, flags); + else + devfd = open(device_path(device), flags); + + if (devfd < 0) { + log_dbg(cd, "Cannot open device %s%s.", + device_path(device), + access != O_RDONLY ? " for write" : ""); + return devfd; + } - if (devfd < 0) - log_dbg("Cannot open device %s.", device_path(device)); + if (access == O_RDONLY) + device->ro_dev_fd = devfd; + else + device->dev_fd = devfd; return devfd; } -int device_alloc(struct device **device, const char *path) +int device_open(struct crypt_device *cd, struct device *device, int flags) +{ + assert(!device_locked(device->lh)); + return device_open_internal(cd, device, flags); +} + +int device_open_excl(struct crypt_device *cd, struct device *device, int flags) +{ + const char *path; + struct stat st; + + if (!device) + return -EINVAL; + + assert(!device_locked(device->lh)); + + if (device->dev_fd_excl < 0) { + path = device_path(device); + if (stat(path, &st)) + return -EINVAL; + if (!S_ISBLK(st.st_mode)) + log_dbg(cd, "%s is not a block device. Can't open in exclusive mode.", + path); + else { + /* open(2) with O_EXCL (w/o O_CREAT) on regular file is undefined behaviour according to man page */ + /* coverity[toctou] */ + device->dev_fd_excl = open(path, O_RDONLY | O_EXCL); + if (device->dev_fd_excl < 0) + return errno == EBUSY ? -EBUSY : device->dev_fd_excl; + if (fstat(device->dev_fd_excl, &st) || !S_ISBLK(st.st_mode)) { + log_dbg(cd, "%s is not a block device. Can't open in exclusive mode.", + path); + close(device->dev_fd_excl); + device->dev_fd_excl = -1; + } else + log_dbg(cd, "Device %s is blocked for exclusive open.", path); + } + } + + return device_open_internal(cd, device, flags); +} + +void device_release_excl(struct crypt_device *cd, struct device *device) +{ + if (device && device->dev_fd_excl >= 0) { + if (close(device->dev_fd_excl)) + log_dbg(cd, "Failed to release exclusive handle on device %s.", + device_path(device)); + else + log_dbg(cd, "Closed exclusive fd for %s.", device_path(device)); + device->dev_fd_excl = -1; + } +} + +int device_open_locked(struct crypt_device *cd, struct device *device, int flags) +{ + assert(!crypt_metadata_locking_enabled() || device_locked(device->lh)); + return device_open_internal(cd, device, flags); +} + +/* Avoid any read from device, expects direct-io to work. */ +int device_alloc_no_check(struct device **device, const char *path) { struct device *dev; - int r; if (!path) { *device = NULL; @@ -184,32 +379,60 @@ int device_alloc(struct device **device, const char *path) return -ENOMEM; } dev->loop_fd = -1; + dev->ro_dev_fd = -1; + dev->dev_fd = -1; + dev->dev_fd_excl = -1; + dev->o_direct = 1; - r = device_ready(dev, 1); - if (!r) { - dev->init_done = 1; - } else if (r == -ENOTBLK) { - /* alloc loop later */ - } else if (r < 0) { - free(dev->path); - free(dev); - return -ENOTBLK; + *device = dev; + return 0; +} + +int device_alloc(struct crypt_device *cd, struct device **device, const char *path) +{ + struct device *dev; + int r; + + r = device_alloc_no_check(&dev, path); + if (r < 0) + return r; + + if (dev) { + r = device_ready(cd, dev); + if (!r) { + dev->init_done = 1; + } else if (r == -ENOTBLK) { + /* alloc loop later */ + } else if (r < 0) { + free(dev->path); + free(dev); + return -ENOTBLK; + } } *device = dev; return 0; } -void device_free(struct device *device) +void device_free(struct crypt_device *cd, struct device *device) { if (!device) return; + device_close(cd, device); + + if (device->dev_fd_excl != -1) { + log_dbg(cd, "Closed exclusive fd for %s.", device_path(device)); + close(device->dev_fd_excl); + } + if (device->loop_fd != -1) { - log_dbg("Closed loop %s (%s).", device->path, device->file_path); + log_dbg(cd, "Closed loop %s (%s).", device->path, device->file_path); close(device->loop_fd); } + assert(!device_locked(device->lh)); + free(device->file_path); free(device->path); free(device); @@ -224,6 +447,21 @@ const char *device_block_path(const struct device *device) return device->path; } +/* Get device-mapper name of device (if possible) */ +const char *device_dm_name(const struct device *device) +{ + const char *dmdir = dm_get_dir(); + size_t dmdir_len = strlen(dmdir); + + if (!device || !device->init_done) + return NULL; + + if (strncmp(device->path, dmdir, dmdir_len)) + return NULL; + + return &device->path[dmdir_len+1]; +} + /* Get path to device / file */ const char *device_path(const struct device *device) { @@ -243,10 +481,11 @@ const char *device_path(const struct device *device) #define BLKALIGNOFF _IO(0x12,122) #endif -void device_topology_alignment(struct device *device, - unsigned long *required_alignment, /* bytes */ - unsigned long *alignment_offset, /* bytes */ - unsigned long default_alignment) +void device_topology_alignment(struct crypt_device *cd, + struct device *device, + unsigned long *required_alignment, /* bytes */ + unsigned long *alignment_offset, /* bytes */ + unsigned long default_alignment) { int dev_alignment_offset = 0; unsigned int min_io_size = 0, opt_io_size = 0; @@ -265,7 +504,7 @@ void device_topology_alignment(struct device *device, /* minimum io size */ if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) { - log_dbg("Topology info for %s not supported, using default offset %lu bytes.", + log_dbg(cd, "Topology info for %s not supported, using default offset %lu bytes.", device->path, default_alignment); goto out; } @@ -281,40 +520,41 @@ void device_topology_alignment(struct device *device, temp_alignment = (unsigned long)min_io_size; - if (temp_alignment < (unsigned long)opt_io_size) + /* Ignore bogus opt-io that could break alignment */ + if ((temp_alignment < (unsigned long)opt_io_size) && + !((unsigned long)opt_io_size % temp_alignment)) temp_alignment = (unsigned long)opt_io_size; /* If calculated alignment is multiple of default, keep default */ if (temp_alignment && (default_alignment % temp_alignment)) *required_alignment = temp_alignment; - log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.", + log_dbg(cd, "Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.", min_io_size, opt_io_size, *alignment_offset, *required_alignment); out: (void)close(fd); } -int device_block_size(struct device *device) +size_t device_block_size(struct crypt_device *cd, struct device *device) { - int fd, r = -EINVAL; + int fd; if (!device) return 0; - if (device->file_path) - return (int)crypt_getpagesize(); - - fd = open(device->path, O_RDONLY); - if(fd < 0) - return -EINVAL; + if (device->block_size) + return device->block_size; - r = device_block_size_fd(fd, NULL); + fd = open(device->file_path ?: device->path, O_RDONLY); + if (fd >= 0) { + device->block_size = device_block_size_fd(fd, NULL); + close(fd); + } - if (r <= 0) - log_dbg("Cannot get block size for device %s.", device_path(device)); + if (!device->block_size) + log_dbg(cd, "Cannot get block size for device %s.", device_path(device)); - close(fd); - return r; + return device->block_size; } int device_read_ahead(struct device *device, uint32_t *read_ahead) @@ -360,18 +600,72 @@ out: return r; } -static int device_info(struct device *device, - enum devcheck device_check, - int *readonly, uint64_t *size) +/* For a file, allocate the required space */ +int device_fallocate(struct device *device, uint64_t size) { struct stat st; - int fd, r = -EINVAL, flags = 0; + int devfd, r = -EINVAL; + + devfd = open(device_path(device), O_RDWR); + if (devfd == -1) + return -EINVAL; - *readonly = 0; - *size = 0; + if (!fstat(devfd, &st) && S_ISREG(st.st_mode) && + ((uint64_t)st.st_size >= size || !posix_fallocate(devfd, 0, size))) { + r = 0; + if (device->file_path && crypt_loop_resize(device->path)) + r = -EINVAL; + } + + close(devfd); + return r; +} + +int device_check_size(struct crypt_device *cd, + struct device *device, + uint64_t req_offset, int falloc) +{ + uint64_t dev_size; - if (stat(device->path, &st) < 0) + if (device_size(device, &dev_size)) { + log_dbg(cd, "Cannot get device size for device %s.", device_path(device)); + return -EIO; + } + + log_dbg(cd, "Device size %" PRIu64 ", offset %" PRIu64 ".", dev_size, req_offset); + + if (req_offset > dev_size) { + /* If it is header file, increase its size */ + if (falloc && !device_fallocate(device, req_offset)) + return 0; + + log_err(cd, _("Device %s is too small. Need at least %" PRIu64 " bytes."), + device_path(device), req_offset); return -EINVAL; + } + + return 0; +} + +static int device_info(struct crypt_device *cd, + struct device *device, + enum devcheck device_check, + int *readonly, uint64_t *size) +{ + struct stat st; + int fd = -1, r, flags = 0, real_readonly; + uint64_t real_size; + + if (!device) + return -ENOTBLK; + + real_readonly = 0; + real_size = 0; + + if (stat(device->path, &st) < 0) { + r = -EINVAL; + goto out; + } /* never wipe header on mounted device */ if (device_check == DEV_EXCL && S_ISBLK(st.st_mode)) @@ -381,64 +675,93 @@ static int device_info(struct device *device, /* coverity[toctou] */ fd = open(device->path, O_RDWR | flags); if (fd == -1 && errno == EROFS) { - *readonly = 1; + real_readonly = 1; fd = open(device->path, O_RDONLY | flags); } - if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY) - return -EBUSY; + if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY) { + r = -EBUSY; + goto out; + } - if (fd == -1) - return -EINVAL; + if (fd == -1) { + r = errno ? -errno : -EINVAL; + goto out; + } + r = 0; if (S_ISREG(st.st_mode)) { //FIXME: add readonly check - *size = (uint64_t)st.st_size; - *size >>= SECTOR_SHIFT; + real_size = (uint64_t)st.st_size; + real_size >>= SECTOR_SHIFT; } else { /* If the device can be opened read-write, i.e. readonly is still 0, then * check whether BKROGET says that it is read-only. E.g. read-only loop - * devices may be openend read-write but are read-only according to BLKROGET + * devices may be opened read-write but are read-only according to BLKROGET */ - if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0) + if (real_readonly == 0 && (r = ioctl(fd, BLKROGET, &real_readonly)) < 0) goto out; - if (ioctl(fd, BLKGETSIZE64, size) >= 0) { - *size >>= SECTOR_SHIFT; - r = 0; + r = ioctl(fd, BLKGETSIZE64, &real_size); + if (r >= 0) { + real_size >>= SECTOR_SHIFT; goto out; } } - r = -EINVAL; out: - close(fd); + if (fd != -1) + close(fd); + + switch (r) { + case 0: + if (readonly) + *readonly = real_readonly; + if (size) + *size = real_size; + break; + case -EBUSY: + log_err(cd, _("Cannot use device %s which is in use " + "(already mapped or mounted)."), device_path(device)); + break; + case -EACCES: + log_err(cd, _("Cannot use device %s, permission denied."), device_path(device)); + break; + default: + log_err(cd, _("Cannot get info about device %s."), device_path(device)); + r = -EINVAL; + } + return r; } +int device_check_access(struct crypt_device *cd, + struct device *device, + enum devcheck device_check) +{ + return device_info(cd, device, device_check, NULL, NULL); +} + static int device_internal_prepare(struct crypt_device *cd, struct device *device) { - char *loop_device, *file_path = NULL; + char *loop_device = NULL, *file_path = NULL; int r, loop_fd, readonly = 0; if (device->init_done) return 0; - log_dbg("Allocating a free loop device."); - loop_device = crypt_loop_get_device(); - if (!loop_device) { - if (getuid() || geteuid()) - log_err(cd, _("Cannot use a loopback device, " - "running as non-root user.\n")); - else - log_err(cd, _("Cannot find a free loopback device.\n")); + if (getuid() || geteuid()) { + log_err(cd, _("Cannot use a loopback device, " + "running as non-root user.")); return -ENOTSUP; } - /* Keep the loop open, dettached on last close. */ - loop_fd = crypt_loop_attach(loop_device, device->path, 0, 1, &readonly); + log_dbg(cd, "Allocating a free loop device."); + + /* Keep the loop open, detached on last close. */ + loop_fd = crypt_loop_attach(&loop_device, device->path, 0, 1, &readonly); if (loop_fd == -1) { log_err(cd, _("Attaching loopback device failed " - "(loop device with autoclear flag is required).\n")); + "(loop device with autoclear flag is required).")); free(loop_device); return -EINVAL; } @@ -446,7 +769,7 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic file_path = device->path; device->path = loop_device; - r = device_ready(device, device->o_direct); + r = device_ready(cd, device); if (r < 0) { device->path = file_path; crypt_loop_detach(loop_device); @@ -478,28 +801,20 @@ int device_block_adjust(struct crypt_device *cd, if (r) return r; - r = device_info(device, device_check, &real_readonly, &real_size); - if (r < 0) { - if (r == -EBUSY) - log_err(cd, _("Cannot use device %s which is in use " - "(already mapped or mounted).\n"), - device->path); - else - log_err(cd, _("Cannot get info about device %s.\n"), - device->path); + r = device_info(cd, device, device_check, &real_readonly, &real_size); + if (r) return r; - } if (device_offset >= real_size) { - log_err(cd, _("Requested offset is beyond real size of device %s.\n"), - device->path); + log_err(cd, _("Requested offset is beyond real size of device %s."), + device_path(device)); return -EINVAL; } if (size && !*size) { *size = real_size; if (!*size) { - log_err(cd, _("Device %s has zero size.\n"), device->path); + log_err(cd, _("Device %s has zero size."), device_path(device)); return -ENOTBLK; } *size -= device_offset; @@ -507,10 +822,10 @@ int device_block_adjust(struct crypt_device *cd, /* in case of size is set by parameter */ if (size && ((real_size - device_offset) < *size)) { - log_dbg("Device %s: offset = %" PRIu64 " requested size = %" PRIu64 + log_dbg(cd, "Device %s: offset = %" PRIu64 " requested size = %" PRIu64 ", backing device size = %" PRIu64, device->path, device_offset, *size, real_size); - log_err(cd, _("Device %s is too small.\n"), device->path); + log_err(cd, _("Device %s is too small."), device_path(device)); return -EINVAL; } @@ -518,13 +833,156 @@ int device_block_adjust(struct crypt_device *cd, *flags |= CRYPT_ACTIVATE_READONLY; if (size) - log_dbg("Calculated device size is %" PRIu64" sectors (%s), offset %" PRIu64 ".", + log_dbg(cd, "Calculated device size is %" PRIu64" sectors (%s), offset %" PRIu64 ".", *size, real_readonly ? "RO" : "RW", device_offset); return 0; } -size_t size_round_up(size_t size, unsigned int block) +size_t size_round_up(size_t size, size_t block) { size_t s = (size + (block - 1)) / block; return s * block; } + +void device_disable_direct_io(struct device *device) +{ + device->o_direct = 0; +} + +int device_direct_io(const struct device *device) +{ + return device->o_direct; +} + +static dev_t device_devno(const struct device *device) +{ + struct stat st; + + if (stat(device->path, &st) || !S_ISBLK(st.st_mode)) + return 0; + + return st.st_rdev; +} + +int device_is_identical(struct device *device1, struct device *device2) +{ + if (!device1 || !device2) + return 0; + + if (device1 == device2) + return 1; + + if (device1->init_done && device2->init_done) + return (device_devno(device1) == device_devno(device2)); + else if (device1->init_done || device2->init_done) + return 0; + + if (!strcmp(device_path(device1), device_path(device2))) + return 1; + + return 0; +} + +int device_is_rotational(struct device *device) +{ + struct stat st; + + if (stat(device_path(device), &st) < 0) + return -EINVAL; + + if (!S_ISBLK(st.st_mode)) + return 0; + + return crypt_dev_is_rotational(major(st.st_rdev), minor(st.st_rdev)); +} + +size_t device_alignment(struct device *device) +{ + int devfd; + + if (!device->alignment) { + devfd = open(device_path(device), O_RDONLY); + if (devfd != -1) { + device->alignment = device_alignment_fd(devfd); + close(devfd); + } + } + + return device->alignment; +} + +void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h) +{ + device->lh = h; +} + +struct crypt_lock_handle *device_get_lock_handle(struct device *device) +{ + return device->lh; +} + +int device_read_lock(struct crypt_device *cd, struct device *device) +{ + if (!crypt_metadata_locking_enabled()) + return 0; + + if (device_read_lock_internal(cd, device)) + return -EBUSY; + + return 0; +} + +int device_write_lock(struct crypt_device *cd, struct device *device) +{ + if (!crypt_metadata_locking_enabled()) + return 0; + + assert(!device_locked(device->lh) || !device_locked_readonly(device->lh)); + + return device_write_lock_internal(cd, device); +} + +void device_read_unlock(struct crypt_device *cd, struct device *device) +{ + if (!crypt_metadata_locking_enabled()) + return; + + assert(device_locked(device->lh)); + + device_unlock_internal(cd, device); +} + +void device_write_unlock(struct crypt_device *cd, struct device *device) +{ + if (!crypt_metadata_locking_enabled()) + return; + + assert(device_locked(device->lh) && !device_locked_readonly(device->lh)); + + device_unlock_internal(cd, device); +} + +bool device_is_locked(struct device *device) +{ + return device ? device_locked(device->lh) : 0; +} + +void device_close(struct crypt_device *cd, struct device *device) +{ + if (!device) + return; + + if (device->ro_dev_fd != -1) { + log_dbg(cd, "Closing read only fd for %s.", device_path(device)); + if (close(device->ro_dev_fd)) + log_dbg(cd, "Failed to close read only fd for %s.", device_path(device)); + device->ro_dev_fd = -1; + } + + if (device->dev_fd != -1) { + log_dbg(cd, "Closing read write fd for %s.", device_path(device)); + if (close(device->dev_fd)) + log_dbg(cd, "Failed to close read write fd for %s.", device_path(device)); + device->dev_fd = -1; + } +} diff --git a/lib/utils_device_locking.c b/lib/utils_device_locking.c new file mode 100644 index 0000000..dac8315 --- /dev/null +++ b/lib/utils_device_locking.c @@ -0,0 +1,521 @@ +/* + * Metadata on-disk locking for processes serialization + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif +#include +#include + +#include "internal.h" +#include "utils_device_locking.h" + +#define same_inode(buf1, buf2) \ + ((buf1).st_ino == (buf2).st_ino && \ + (buf1).st_dev == (buf2).st_dev) + +enum lock_type { + DEV_LOCK_READ = 0, + DEV_LOCK_WRITE +}; + +enum lock_mode { + DEV_LOCK_FILE = 0, + DEV_LOCK_BDEV, + DEV_LOCK_NAME +}; + +struct crypt_lock_handle { + unsigned refcnt; + int flock_fd; + enum lock_type type; + enum lock_mode mode; + union { + struct { + dev_t devno; + } bdev; + struct { + char *name; + } name; + } u; +}; + +static int resource_by_name(char *res, size_t res_size, const char *name, bool fullpath) +{ + int r; + + if (fullpath) + r = snprintf(res, res_size, "%s/LN_%s", DEFAULT_LUKS2_LOCK_PATH, name); + else + r = snprintf(res, res_size, "LN_%s", name); + + return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0; +} + +static int resource_by_devno(char *res, size_t res_size, dev_t devno, unsigned fullpath) +{ + int r; + + if (fullpath) + r = snprintf(res, res_size, "%s/L_%d:%d", DEFAULT_LUKS2_LOCK_PATH, major(devno), minor(devno)); + else + r = snprintf(res, res_size, "L_%d:%d", major(devno), minor(devno)); + + return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0; +} + +static int open_lock_dir(struct crypt_device *cd, const char *dir, const char *base) +{ + int dirfd, lockdfd; + + dirfd = open(dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (dirfd < 0) { + log_dbg(cd, "Failed to open directory %s: (%d: %s).", dir, errno, strerror(errno)); + if (errno == ENOTDIR || errno == ENOENT) + log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."), dir, base); + return -EINVAL; + } + + lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC); + if (lockdfd < 0) { + if (errno == ENOENT) { + log_std(cd, _("WARNING: Locking directory %s/%s is missing!\n"), dir, base); + + /* success or failure w/ errno == EEXIST either way just try to open the 'base' directory again */ + if (mkdirat(dirfd, base, DEFAULT_LUKS2_LOCK_DIR_PERMS) && errno != EEXIST) + log_dbg(cd, "Failed to create directory %s in %s (%d: %s).", base, dir, errno, strerror(errno)); + else + lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC); + } else { + log_dbg(cd, "Failed to open directory %s/%s: (%d: %s)", dir, base, errno, strerror(errno)); + if (errno == ENOTDIR || errno == ELOOP) + log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."), dir, base, base); + } + } + + close(dirfd); + return lockdfd >= 0 ? lockdfd : -EINVAL; +} + +static int open_resource(struct crypt_device *cd, const char *res) +{ + int err, lockdir_fd, r; + char dir[] = DEFAULT_LUKS2_LOCK_PATH, + base[] = DEFAULT_LUKS2_LOCK_PATH; + + lockdir_fd = open_lock_dir(cd, dirname(dir), basename(base)); + if (lockdir_fd < 0) + return -EINVAL; + + log_dbg(cd, "Opening lock resource file %s/%s", DEFAULT_LUKS2_LOCK_PATH, res); + r = openat(lockdir_fd, res, O_CREAT | O_NOFOLLOW | O_RDWR | O_CLOEXEC, 0777); + err = errno; + + close(lockdir_fd); + + return r < 0 ? -err : r; +} + +static int acquire_lock_handle(struct crypt_device *cd, struct device *device, struct crypt_lock_handle *h) +{ + char res[PATH_MAX]; + int dev_fd, fd; + struct stat st; + + dev_fd = open(device_path(device), O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (dev_fd < 0) + return -EINVAL; + + if (fstat(dev_fd, &st)) { + close(dev_fd); + return -EINVAL; + } + + if (S_ISBLK(st.st_mode)) { + if (resource_by_devno(res, sizeof(res), st.st_rdev, 0)) { + close(dev_fd); + return -EINVAL; + } + + fd = open_resource(cd, res); + close(dev_fd); + if (fd < 0) + return fd; + + h->flock_fd = fd; + h->u.bdev.devno = st.st_rdev; + h->mode = DEV_LOCK_BDEV; + } else if (S_ISREG(st.st_mode)) { + // FIXME: workaround for nfsv4 + fd = open(device_path(device), O_RDWR | O_NONBLOCK | O_CLOEXEC); + if (fd < 0) + h->flock_fd = dev_fd; + else { + h->flock_fd = fd; + close(dev_fd); + } + h->mode = DEV_LOCK_FILE; + } else { + /* Wrong device type */ + close(dev_fd); + return -EINVAL; + } + + return 0; +} + +static int acquire_lock_handle_by_name(struct crypt_device *cd, const char *name, struct crypt_lock_handle *h) +{ + char res[PATH_MAX]; + int fd; + + h->u.name.name = strdup(name); + if (!h->u.name.name) + return -ENOMEM; + + if (resource_by_name(res, sizeof(res), name, false)) { + free(h->u.name.name); + return -EINVAL; + } + + fd = open_resource(cd, res); + if (fd < 0) { + free(h->u.name.name); + return fd; + } + + h->flock_fd = fd; + h->mode = DEV_LOCK_NAME; + + return 0; +} + +static void release_lock_handle(struct crypt_device *cd, struct crypt_lock_handle *h) +{ + char res[PATH_MAX]; + struct stat buf_a, buf_b; + + if ((h->mode == DEV_LOCK_NAME) && /* was it name lock */ + !flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */ + !resource_by_name(res, sizeof(res), h->u.name.name, true) && /* acquire lock resource name */ + !fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */ + !stat(res, &buf_b) && /* does path file still exist? */ + same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */ + /* coverity[toctou] */ + if (unlink(res)) /* yes? unlink the file */ + log_dbg(cd, "Failed to unlink resource file: %s", res); + } + + if ((h->mode == DEV_LOCK_BDEV) && /* was it block device */ + !flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */ + !resource_by_devno(res, sizeof(res), h->u.bdev.devno, 1) && /* acquire lock resource name */ + !fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */ + !stat(res, &buf_b) && /* does path file still exist? */ + same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */ + /* coverity[toctou] */ + if (unlink(res)) /* yes? unlink the file */ + log_dbg(cd, "Failed to unlink resource file: %s", res); + } + + if (h->mode == DEV_LOCK_NAME) + free(h->u.name.name); + + if (close(h->flock_fd)) + log_dbg(cd, "Failed to close lock resource fd (%d).", h->flock_fd); +} + +int device_locked(struct crypt_lock_handle *h) +{ + return (h && (h->type == DEV_LOCK_READ || h->type == DEV_LOCK_WRITE)); +} + +int device_locked_readonly(struct crypt_lock_handle *h) +{ + return (h && h->type == DEV_LOCK_READ); +} + +static int verify_lock_handle(const char *device_path, struct crypt_lock_handle *h) +{ + char res[PATH_MAX]; + struct stat lck_st, res_st; + + /* we locked a regular file, check during device_open() instead. No reason to check now */ + if (h->mode == DEV_LOCK_FILE) + return 0; + + if (h->mode == DEV_LOCK_NAME) { + if (resource_by_name(res, sizeof(res), h->u.name.name, true)) + return -EINVAL; + } else if (h->mode == DEV_LOCK_BDEV) { + if (resource_by_devno(res, sizeof(res), h->u.bdev.devno, true)) + return -EINVAL; + } else + return -EINVAL; + + if (fstat(h->flock_fd, &lck_st)) + return -EINVAL; + + return (stat(res, &res_st) || !same_inode(lck_st, res_st)) ? -EAGAIN : 0; +} + +static unsigned device_lock_inc(struct crypt_lock_handle *h) +{ + return ++h->refcnt; +} + +static unsigned device_lock_dec(struct crypt_lock_handle *h) +{ + assert(h->refcnt); + + return --h->refcnt; +} + +static int acquire_and_verify(struct crypt_device *cd, struct device *device, const char *resource, int flock_op, struct crypt_lock_handle **lock) +{ + int r; + struct crypt_lock_handle *h; + + if (device && resource) + return -EINVAL; + + if (!(h = malloc(sizeof(*h)))) + return -ENOMEM; + + do { + r = device ? acquire_lock_handle(cd, device, h) : acquire_lock_handle_by_name(cd, resource, h); + if (r < 0) + break; + + if (flock(h->flock_fd, flock_op)) { + log_dbg(cd, "Flock on fd %d failed with errno %d.", h->flock_fd, errno); + r = (errno == EWOULDBLOCK) ? -EBUSY : -EINVAL; + release_lock_handle(cd, h); + break; + } + + log_dbg(cd, "Verifying lock handle for %s.", device ? device_path(device) : resource); + + /* + * check whether another libcryptsetup process removed resource file before this + * one managed to flock() it. See release_lock_handle() for details + */ + r = verify_lock_handle(device_path(device), h); + if (r < 0) { + if (flock(h->flock_fd, LOCK_UN)) + log_dbg(cd, "flock on fd %d failed.", h->flock_fd); + release_lock_handle(cd, h); + log_dbg(cd, "Lock handle verification failed."); + } + } while (r == -EAGAIN); + + if (r < 0) { + free(h); + return r; + } + + *lock = h; + + return 0; +} + +int device_read_lock_internal(struct crypt_device *cd, struct device *device) +{ + int r; + struct crypt_lock_handle *h; + + if (!device) + return -EINVAL; + + h = device_get_lock_handle(device); + + if (device_locked(h)) { + device_lock_inc(h); + log_dbg(cd, "Device %s READ lock (or higher) already held.", device_path(device)); + return 0; + } + + log_dbg(cd, "Acquiring read lock for device %s.", device_path(device)); + + r = acquire_and_verify(cd, device, NULL, LOCK_SH, &h); + if (r < 0) + return r; + + h->type = DEV_LOCK_READ; + h->refcnt = 1; + device_set_lock_handle(device, h); + + log_dbg(cd, "Device %s READ lock taken.", device_path(device)); + + return 0; +} + +int device_write_lock_internal(struct crypt_device *cd, struct device *device) +{ + int r; + struct crypt_lock_handle *h; + + if (!device) + return -EINVAL; + + h = device_get_lock_handle(device); + + if (device_locked(h)) { + log_dbg(cd, "Device %s WRITE lock already held.", device_path(device)); + return device_lock_inc(h); + } + + log_dbg(cd, "Acquiring write lock for device %s.", device_path(device)); + + r = acquire_and_verify(cd, device, NULL, LOCK_EX, &h); + if (r < 0) + return r; + + h->type = DEV_LOCK_WRITE; + h->refcnt = 1; + device_set_lock_handle(device, h); + + log_dbg(cd, "Device %s WRITE lock taken.", device_path(device)); + + return 1; +} + +int crypt_read_lock(struct crypt_device *cd, const char *resource, bool blocking, struct crypt_lock_handle **lock) +{ + int r; + struct crypt_lock_handle *h; + + if (!resource) + return -EINVAL; + + log_dbg(cd, "Acquiring %sblocking read lock for resource %s.", blocking ? "" : "non", resource); + + r = acquire_and_verify(cd, NULL, resource, LOCK_SH | (blocking ? 0 : LOCK_NB), &h); + if (r < 0) + return r; + + h->type = DEV_LOCK_READ; + h->refcnt = 1; + + log_dbg(cd, "READ lock for resource %s taken.", resource); + + *lock = h; + + return 0; +} + +int crypt_write_lock(struct crypt_device *cd, const char *resource, bool blocking, struct crypt_lock_handle **lock) +{ + int r; + struct crypt_lock_handle *h; + + if (!resource) + return -EINVAL; + + log_dbg(cd, "Acquiring %sblocking write lock for resource %s.", blocking ? "" : "non", resource); + + r = acquire_and_verify(cd, NULL, resource, LOCK_EX | (blocking ? 0 : LOCK_NB), &h); + if (r < 0) + return r; + + h->type = DEV_LOCK_WRITE; + h->refcnt = 1; + + log_dbg(cd, "WRITE lock for resource %s taken.", resource); + + *lock = h; + + return 0; +} + +static void unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h) +{ + if (flock(h->flock_fd, LOCK_UN)) + log_dbg(cd, "flock on fd %d failed.", h->flock_fd); + release_lock_handle(cd, h); + free(h); +} + +void crypt_unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h) +{ + if (!h) + return; + + /* nested locks are illegal */ + assert(!device_lock_dec(h)); + + log_dbg(cd, "Unlocking %s lock for resource %s.", + device_locked_readonly(h) ? "READ" : "WRITE", h->u.name.name); + + unlock_internal(cd, h); +} + +void device_unlock_internal(struct crypt_device *cd, struct device *device) +{ + bool readonly; + struct crypt_lock_handle *h = device_get_lock_handle(device); + unsigned u = device_lock_dec(h); + + if (u) + return; + + readonly = device_locked_readonly(h); + + unlock_internal(cd, h); + + log_dbg(cd, "Device %s %s lock released.", device_path(device), + readonly ? "READ" : "WRITE"); + + device_set_lock_handle(device, NULL); +} + +int device_locked_verify(struct crypt_device *cd, int dev_fd, struct crypt_lock_handle *h) +{ + char res[PATH_MAX]; + struct stat dev_st, lck_st, st; + + if (fstat(dev_fd, &dev_st) || fstat(h->flock_fd, &lck_st)) + return 1; + + /* if device handle is regular file the handle must match the lock handle */ + if (S_ISREG(dev_st.st_mode)) { + log_dbg(cd, "Veryfing locked device handle (regular file)"); + if (!same_inode(dev_st, lck_st)) + return 1; + } else if (S_ISBLK(dev_st.st_mode)) { + log_dbg(cd, "Veryfing locked device handle (bdev)"); + if (resource_by_devno(res, sizeof(res), dev_st.st_rdev, 1) || + stat(res, &st) || + !same_inode(lck_st, st)) + return 1; + } else + return 1; + + return 0; +} diff --git a/lib/utils_device_locking.h b/lib/utils_device_locking.h new file mode 100644 index 0000000..41d0934 --- /dev/null +++ b/lib/utils_device_locking.h @@ -0,0 +1,47 @@ +/* + * Metadata on-disk locking for processes serialization + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_UTILS_LOCKING_H +#define _CRYPTSETUP_UTILS_LOCKING_H + +struct crypt_device; +struct crypt_lock_handle; +struct device; + +int device_locked_readonly(struct crypt_lock_handle *h); +int device_locked(struct crypt_lock_handle *h); + +int device_read_lock_internal(struct crypt_device *cd, struct device *device); +int device_write_lock_internal(struct crypt_device *cd, struct device *device); +void device_unlock_internal(struct crypt_device *cd, struct device *device); + +int device_locked_verify(struct crypt_device *cd, int fd, struct crypt_lock_handle *h); + +int crypt_read_lock(struct crypt_device *cd, const char *name, bool blocking, struct crypt_lock_handle **lock); +int crypt_write_lock(struct crypt_device *cd, const char *name, bool blocking, struct crypt_lock_handle **lock); +void crypt_unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h); + + +/* Used only in device internal allocation */ +void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h); +struct crypt_lock_handle *device_get_lock_handle(struct device *device); + +#endif diff --git a/lib/utils_devpath.c b/lib/utils_devpath.c index 963785a..b6c8975 100644 --- a/lib/utils_devpath.c +++ b/lib/utils_devpath.c @@ -1,10 +1,10 @@ /* * devname - search for device name * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2013, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,11 +26,13 @@ #include #include #include -#include #include #include #include #include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif #include "internal.h" static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level) @@ -108,7 +110,7 @@ static char *lookup_dev_old(int major, int minor) return result; /* If it is dm, try DM dir */ - if (dm_is_dm_device(major, minor)) { + if (dm_is_dm_device(major)) { strncpy(buf, dm_get_dir(), PATH_MAX); if ((result = __lookup_dev(buf, dev, 0, 0))) return result; @@ -276,24 +278,30 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t major(st.st_rdev), minor(st.st_rdev)) < 0) return NULL; + dir = opendir(path); + if (!dir) + return NULL; + len = readlink(path, link, sizeof(link) - 1); - if (len < 0) + if (len < 0) { + closedir(dir); return NULL; + } /* Get top level disk name for sysfs search */ link[len] = '\0'; devname = strrchr(link, '/'); - if (!devname) + if (!devname) { + closedir(dir); return NULL; + } devname++; /* DM devices do not use kernel partitions. */ - if (dm_is_dm_kernel_name(devname)) - return NULL; - - dir = opendir(path); - if (!dir) + if (dm_is_dm_kernel_name(devname)) { + closedir(dir); return NULL; + } devname_len = strlen(devname); while((entry = readdir(dir))) { @@ -362,3 +370,88 @@ char *crypt_get_base_device(const char *dev_path) snprintf(part_path, sizeof(part_path), "/dev/%s", devname); return strdup(part_path); } + +int lookup_by_disk_id(const char *dm_uuid) +{ + struct dirent *entry; + struct stat st; + int r = 0; /* not found */ + DIR *dir = opendir("/dev/disk/by-id"); + + if (!dir) + /* map ENOTDIR to ENOENT we'll handle both errors same */ + return errno == ENOTDIR ? -ENOENT : -errno; + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.' || + !strncmp(entry->d_name, "..", 2)) + continue; + + if (fstatat(dirfd(dir), entry->d_name, &st, AT_SYMLINK_NOFOLLOW)) { + r = -EINVAL; + break; + } + + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) + continue; + + if (!strncmp(entry->d_name, dm_uuid, strlen(dm_uuid))) { + r = 1; + break; + } + } + + closedir(dir); + + return r; +} + +int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len) +{ + struct dirent *entry; + char subpath[PATH_MAX], uuid[max_len]; + ssize_t s; + struct stat st; + int fd, len, r = 0; /* not found */ + DIR *dir = opendir("/sys/block/"); + + if (!dir) + /* map ENOTDIR to ENOENT we'll handle both errors same */ + return errno == ENOTDIR ? -ENOENT : -errno; + + while (r != 1 && (entry = readdir(dir))) { + if (entry->d_name[0] == '.' || + !strncmp(entry->d_name, "..", 2)) + continue; + + len = snprintf(subpath, PATH_MAX, "%s/%s", entry->d_name, "dm/uuid"); + if (len < 0 || len >= PATH_MAX) { + r = -EINVAL; + break; + } + + /* looking for dm-X/dm/uuid file, symlinks are fine */ + fd = openat(dirfd(dir), subpath, O_RDONLY | O_CLOEXEC); + if (fd < 0) + continue; + + if (fstat(fd, &st) || !S_ISREG(st.st_mode)) { + close(fd); + continue; + } + + /* reads binary data */ + s = read_buffer(fd, uuid, max_len - 1); + if (s > 0) { + uuid[s] = '\0'; + if (!strncmp(uuid, dm_uuid, strlen(dm_uuid))) + r = 1; + } + + close(fd); + } + + closedir(dir); + + return r; +} diff --git a/lib/utils_dm.h b/lib/utils_dm.h index cd8b653..1501eb5 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -1,10 +1,10 @@ /* * libdevmapper - device-mapper backend for cryptsetup * - * Copyright (C) 2004, Jana Saout - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2015, Milan Broz + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,6 +31,18 @@ struct crypt_device; struct volume_key; struct crypt_params_verity; struct device; +struct crypt_params_integrity; + +/* Device mapper internal flags */ +#define DM_RESUME_PRIVATE (1 << 4) /* CRYPT_ACTIVATE_PRIVATE */ +#define DM_SUSPEND_SKIP_LOCKFS (1 << 5) +#define DM_SUSPEND_WIPE_KEY (1 << 6) +#define DM_SUSPEND_NOFLUSH (1 << 7) + +static inline uint32_t act2dmflags(uint32_t act_flags) +{ + return (act_flags & DM_RESUME_PRIVATE); +} /* Device mapper backend - kernel support flags */ #define DM_KEY_WIPE_SUPPORTED (1 << 0) /* key wipe message */ @@ -42,71 +54,178 @@ struct device; #define DM_TCW_SUPPORTED (1 << 6) /* tcw (TCRYPT CBC with whitening) */ #define DM_SAME_CPU_CRYPT_SUPPORTED (1 << 7) /* same_cpu_crypt */ #define DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED (1 << 8) /* submit_from_crypt_cpus */ - -uint32_t dm_flags(void); +#define DM_VERITY_ON_CORRUPTION_SUPPORTED (1 << 9) /* ignore/restart_on_corruption, ignore_zero_block */ +#define DM_VERITY_FEC_SUPPORTED (1 << 10) /* Forward Error Correction (FEC) */ +#define DM_KERNEL_KEYRING_SUPPORTED (1 << 11) /* dm-crypt allows loading kernel keyring keys */ +#define DM_INTEGRITY_SUPPORTED (1 << 12) /* dm-integrity target supported */ +#define DM_SECTOR_SIZE_SUPPORTED (1 << 13) /* support for sector size setting in dm-crypt/dm-integrity */ +#define DM_CAPI_STRING_SUPPORTED (1 << 14) /* support for cryptoapi format cipher definition */ +#define DM_DEFERRED_SUPPORTED (1 << 15) /* deferred removal of device */ +#define DM_INTEGRITY_RECALC_SUPPORTED (1 << 16) /* dm-integrity automatic recalculation supported */ +#define DM_INTEGRITY_BITMAP_SUPPORTED (1 << 17) /* dm-integrity bitmap mode supported */ +#define DM_GET_TARGET_VERSION_SUPPORTED (1 << 18) /* dm DM_GET_TARGET version ioctl supported */ +#define DM_INTEGRITY_FIX_PADDING_SUPPORTED (1 << 19) /* supports the parameter fix_padding that fixes a bug that caused excessive padding */ +#define DM_BITLK_EBOIV_SUPPORTED (1 << 20) /* EBOIV for BITLK supported */ +#define DM_BITLK_ELEPHANT_SUPPORTED (1 << 21) /* Elephant diffuser for BITLK supported */ +#define DM_VERITY_SIGNATURE_SUPPORTED (1 << 22) /* Verity option root_hash_sig_key_desc supported */ +#define DM_INTEGRITY_DISCARDS_SUPPORTED (1 << 23) /* dm-integrity discards/TRIM option is supported */ + +typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type; +enum tdirection { TARGET_SET = 1, TARGET_QUERY }; + +int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags); #define DM_ACTIVE_DEVICE (1 << 0) #define DM_ACTIVE_UUID (1 << 1) +#define DM_ACTIVE_HOLDERS (1 << 2) -#define DM_ACTIVE_CRYPT_CIPHER (1 << 2) -#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 3) -#define DM_ACTIVE_CRYPT_KEY (1 << 4) +#define DM_ACTIVE_CRYPT_CIPHER (1 << 3) +#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 4) +#define DM_ACTIVE_CRYPT_KEY (1 << 5) -#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 5) -#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 6) -#define DM_ACTIVE_VERITY_PARAMS (1 << 7) +#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 6) +#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 7) +#define DM_ACTIVE_VERITY_PARAMS (1 << 8) -struct crypt_dm_active_device { - enum { DM_CRYPT = 0, DM_VERITY } target; - uint64_t size; /* active device size */ - uint32_t flags; /* activation flags */ - const char *uuid; +#define DM_ACTIVE_INTEGRITY_PARAMS (1 << 9) + +struct dm_target { + dm_target_type type; + enum tdirection direction; + uint64_t offset; + uint64_t size; struct device *data_device; union { struct { const char *cipher; + const char *integrity; /* Active key for device */ struct volume_key *vk; /* struct crypt_active_device */ uint64_t offset; /* offset in sectors */ - uint64_t iv_offset; /* IV initilisation sector */ + uint64_t iv_offset; /* IV initialisation sector */ + uint32_t tag_size; /* additional on-disk tag size */ + uint32_t sector_size; /* encryption sector size */ } crypt; struct { struct device *hash_device; + struct device *fec_device; const char *root_hash; uint32_t root_hash_size; + const char *root_hash_sig_key_desc; uint64_t hash_offset; /* hash offset in blocks (not header) */ + uint64_t hash_blocks; /* size of hash device (in hash blocks) */ + uint64_t fec_offset; /* FEC offset in blocks (not header) */ + uint64_t fec_blocks; /* size of FEC device (in hash blocks) */ struct crypt_params_verity *vp; } verity; + struct { + uint64_t journal_size; + uint32_t journal_watermark; + uint32_t journal_commit_time; + uint32_t interleave_sectors; + uint32_t tag_size; + uint64_t offset; /* offset in sectors */ + uint32_t sector_size; /* integrity sector size */ + uint32_t buffer_sectors; + + const char *integrity; + /* Active key for device */ + struct volume_key *vk; + + const char *journal_integrity; + struct volume_key *journal_integrity_key; + + const char *journal_crypt; + struct volume_key *journal_crypt_key; + + struct device *meta_device; + + bool fix_padding; + } integrity; + struct { + uint64_t offset; + } linear; + struct { + } zero; } u; + + char *params; + struct dm_target *next; }; -void dm_backend_init(void); -void dm_backend_exit(void); +struct crypt_dm_active_device { + uint64_t size; /* active device size */ + uint32_t flags; /* activation flags */ + const char *uuid; + + unsigned holders:1; /* device holders detected (on query only) */ -int dm_remove_device(struct crypt_device *cd, const char *name, - int force, uint64_t size); + struct dm_target segment; +}; + +static inline bool single_segment(const struct crypt_dm_active_device *dmd) +{ + return dmd && !dmd->segment.next; +} + +void dm_backend_init(struct crypt_device *cd); +void dm_backend_exit(struct crypt_device *cd); + +int dm_targets_allocate(struct dm_target *first, unsigned count); +void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd); + +int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, struct volume_key *vk, const char *cipher, + uint64_t iv_offset, uint64_t data_offset, const char *integrity, + uint32_t tag_size, uint32_t sector_size); +int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, struct device *hash_device, struct device *fec_device, + const char *root_hash, uint32_t root_hash_size, const char *root_hash_sig_key_desc, + uint64_t hash_offset_block, uint64_t hash_blocks, struct crypt_params_verity *vp); +int dm_integrity_target_set(struct crypt_device *cd, + struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *meta_device, + struct device *data_device, uint64_t tag_size, uint64_t offset, uint32_t sector_size, + struct volume_key *vk, + struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key, + const struct crypt_params_integrity *ip); +int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size, + struct device *data_device, uint64_t data_offset); +int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size); + +int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags); int dm_status_device(struct crypt_device *cd, const char *name); int dm_status_suspended(struct crypt_device *cd, const char *name); int dm_status_verity_ok(struct crypt_device *cd, const char *name); +int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count); int dm_query_device(struct crypt_device *cd, const char *name, uint32_t get_flags, struct crypt_dm_active_device *dmd); +int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, + char **names, size_t names_length); int dm_create_device(struct crypt_device *cd, const char *name, - const char *type, struct crypt_dm_active_device *dmd, - int reload); -int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name); + const char *type, struct crypt_dm_active_device *dmd); +int dm_reload_device(struct crypt_device *cd, const char *name, + struct crypt_dm_active_device *dmd, uint32_t dmflags, unsigned resume); +int dm_suspend_device(struct crypt_device *cd, const char *name, uint32_t dmflags); +int dm_resume_device(struct crypt_device *cd, const char *name, uint32_t dmflags); int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name, - size_t key_size, const char *key); + const struct volume_key *vk); +int dm_error_device(struct crypt_device *cd, const char *name); +int dm_clear_device(struct crypt_device *cd, const char *name); const char *dm_get_dir(void); +int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type); + /* These are DM helpers used only by utils_devpath file */ -int dm_is_dm_device(int major, int minor); +int dm_is_dm_device(int major); int dm_is_dm_kernel_name(const char *name); char *dm_device_path(const char *prefix, int major, int minor); +char *dm_device_name(const char *path); #endif /* _UTILS_DM_H */ diff --git a/lib/utils_fips.c b/lib/utils_fips.c index d5a18d7..34b2dae 100644 --- a/lib/utils_fips.c +++ b/lib/utils_fips.c @@ -1,7 +1,7 @@ /* * FIPS mode utilities * - * Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/lib/utils_fips.h b/lib/utils_fips.h index 63765c4..2388ba6 100644 --- a/lib/utils_fips.h +++ b/lib/utils_fips.h @@ -1,7 +1,7 @@ /* * FIPS mode utilities * - * Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved. + * Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/lib/utils_io.c b/lib/utils_io.c new file mode 100644 index 0000000..3fae22b --- /dev/null +++ b/lib/utils_io.c @@ -0,0 +1,299 @@ +/* + * utils - miscellaneous I/O utilities for cryptsetup + * + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "utils_io.h" + +static ssize_t _read_buffer(int fd, void *buf, size_t length, volatile int *quit) +{ + size_t read_size = 0; + ssize_t r; + + if (fd < 0 || !buf) + return -EINVAL; + + do { + r = read(fd, buf, length - read_size); + if (r == -1 && errno != EINTR) + return r; + if (r > 0) { + read_size += (size_t)r; + buf = (uint8_t*)buf + r; + } + if (r == 0 || (quit && *quit)) + return (ssize_t)read_size; + } while (read_size != length); + + return (ssize_t)length; +} + +ssize_t read_buffer(int fd, void *buf, size_t length) +{ + return _read_buffer(fd, buf, length, NULL); +} + +ssize_t read_buffer_intr(int fd, void *buf, size_t length, volatile int *quit) +{ + return _read_buffer(fd, buf, length, quit); +} + +static ssize_t _write_buffer(int fd, const void *buf, size_t length, volatile int *quit) +{ + size_t write_size = 0; + ssize_t w; + + if (fd < 0 || !buf || !length) + return -EINVAL; + + do { + w = write(fd, buf, length - write_size); + if (w < 0 && errno != EINTR) + return w; + if (w > 0) { + write_size += (size_t) w; + buf = (const uint8_t*)buf + w; + } + if (w == 0 || (quit && *quit)) + return (ssize_t)write_size; + } while (write_size != length); + + return (ssize_t)write_size; +} + +ssize_t write_buffer(int fd, const void *buf, size_t length) +{ + return _write_buffer(fd, buf, length, NULL); +} + +ssize_t write_buffer_intr(int fd, const void *buf, size_t length, volatile int *quit) +{ + return _write_buffer(fd, buf, length, quit); +} + +ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length) +{ + void *hangover_buf = NULL, *buf = NULL; + size_t hangover, solid; + ssize_t r, ret = -1; + + if (fd == -1 || !orig_buf || !bsize || !alignment) + return -1; + + hangover = length % bsize; + solid = length - hangover; + + if ((size_t)orig_buf & (alignment - 1)) { + if (posix_memalign(&buf, alignment, length)) + return -1; + memcpy(buf, orig_buf, length); + } else + buf = orig_buf; + + if (solid) { + r = write_buffer(fd, buf, solid); + if (r < 0 || r != (ssize_t)solid) + goto out; + } + + if (hangover) { + if (posix_memalign(&hangover_buf, alignment, bsize)) + goto out; + memset(hangover_buf, 0, bsize); + + r = read_buffer(fd, hangover_buf, bsize); + if (r < 0) + goto out; + + if (lseek(fd, -(off_t)r, SEEK_CUR) < 0) + goto out; + + memcpy(hangover_buf, (char*)buf + solid, hangover); + + r = write_buffer(fd, hangover_buf, bsize); + if (r < 0 || r < (ssize_t)hangover) + goto out; + } + ret = length; +out: + free(hangover_buf); + if (buf != orig_buf) + free(buf); + return ret; +} + +ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length) +{ + void *hangover_buf = NULL, *buf = NULL; + size_t hangover, solid; + ssize_t r, ret = -1; + + if (fd == -1 || !orig_buf || !bsize || !alignment) + return -1; + + hangover = length % bsize; + solid = length - hangover; + + if ((size_t)orig_buf & (alignment - 1)) { + if (posix_memalign(&buf, alignment, length)) + return -1; + } else + buf = orig_buf; + + r = read_buffer(fd, buf, solid); + if (r < 0 || r != (ssize_t)solid) + goto out; + + if (hangover) { + if (posix_memalign(&hangover_buf, alignment, bsize)) + goto out; + r = read_buffer(fd, hangover_buf, bsize); + if (r < 0 || r < (ssize_t)hangover) + goto out; + + memcpy((char *)buf + solid, hangover_buf, hangover); + } + ret = length; +out: + free(hangover_buf); + if (buf != orig_buf) { + if (ret != -1) + memcpy(orig_buf, buf, length); + free(buf); + } + return ret; +} + +/* + * Combines llseek with blockwise write. write_blockwise can already deal with short writes + * but we also need a function to deal with short writes at the start. But this information + * is implicitly included in the read/write offset, which can not be set to non-aligned + * boundaries. Hence, we combine llseek with write. + */ +ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset) +{ + void *frontPadBuf = NULL; + size_t frontHang, innerCount = 0; + ssize_t r, ret = -1; + + if (fd == -1 || !buf || !bsize || !alignment) + return -1; + + if (offset < 0) + offset = lseek(fd, offset, SEEK_END); + + if (offset < 0) + return -1; + + frontHang = offset % bsize; + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + return -1; + + if (frontHang && length) { + if (posix_memalign(&frontPadBuf, alignment, bsize)) + return -1; + + innerCount = bsize - frontHang; + if (innerCount > length) + innerCount = length; + + r = read_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r < (ssize_t)(frontHang + innerCount)) + goto out; + + memcpy((char*)frontPadBuf + frontHang, buf, innerCount); + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + goto out; + + r = write_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r != (ssize_t)bsize) + goto out; + + buf = (char*)buf + innerCount; + length -= innerCount; + } + + ret = length ? write_blockwise(fd, bsize, alignment, buf, length) : 0; + if (ret >= 0) + ret += innerCount; +out: + free(frontPadBuf); + return ret; +} + +ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset) +{ + void *frontPadBuf = NULL; + size_t frontHang, innerCount = 0; + ssize_t r, ret = -1; + + if (fd == -1 || !buf || bsize <= 0) + return -1; + + if (offset < 0) + offset = lseek(fd, offset, SEEK_END); + + if (offset < 0) + return -1; + + frontHang = offset % bsize; + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + return -1; + + if (frontHang && length) { + if (posix_memalign(&frontPadBuf, alignment, bsize)) + return -1; + + innerCount = bsize - frontHang; + if (innerCount > length) + innerCount = length; + + r = read_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r < (ssize_t)(frontHang + innerCount)) + goto out; + + memcpy(buf, (char*)frontPadBuf + frontHang, innerCount); + + buf = (char*)buf + innerCount; + length -= innerCount; + } + + ret = read_blockwise(fd, bsize, alignment, buf, length); + if (ret >= 0) + ret += innerCount; +out: + free(frontPadBuf); + return ret; +} diff --git a/lib/utils_io.h b/lib/utils_io.h new file mode 100644 index 0000000..4e64d86 --- /dev/null +++ b/lib/utils_io.h @@ -0,0 +1,42 @@ +/* + * utils - miscellaneous I/O utilities for cryptsetup + * + * Copyright (C) 2004 Jana Saout + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRYPTSETUP_UTILS_IO_H +#define _CRYPTSETUP_UTILS_IO_H + +#include + +ssize_t read_buffer(int fd, void *buf, size_t length); +ssize_t read_buffer_intr(int fd, void *buf, size_t length, volatile int *quit); +ssize_t write_buffer(int fd, const void *buf, size_t length); +ssize_t write_buffer_intr(int fd, const void *buf, size_t length, volatile int *quit); +ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length); +ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, + void *orig_buf, size_t length); +ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset); +ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, + void *buf, size_t length, off_t offset); + +#endif diff --git a/lib/utils_keyring.c b/lib/utils_keyring.c new file mode 100644 index 0000000..6e22c19 --- /dev/null +++ b/lib/utils_keyring.c @@ -0,0 +1,242 @@ +/* + * kernel keyring utilities + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include "libcryptsetup.h" +#include "utils_keyring.h" + +#ifndef HAVE_KEY_SERIAL_T +#define HAVE_KEY_SERIAL_T +typedef int32_t key_serial_t; +#endif + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +#ifdef KERNEL_KEYRING + +static const struct { + key_type_t type; + const char *type_name; +} key_types[] = { + { LOGON_KEY, "logon" }, + { USER_KEY, "user" }, +}; + +#include + +/* request_key */ +static key_serial_t request_key(const char *type, + const char *description, + const char *callout_info, + key_serial_t keyring) +{ + return syscall(__NR_request_key, type, description, callout_info, keyring); +} + +/* add_key */ +static key_serial_t add_key(const char *type, + const char *description, + const void *payload, + size_t plen, + key_serial_t keyring) +{ + return syscall(__NR_add_key, type, description, payload, plen, keyring); +} + +/* keyctl_read */ +static long keyctl_read(key_serial_t key, char *buffer, size_t buflen) +{ + return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen); +} + +/* keyctl_revoke */ +static long keyctl_revoke(key_serial_t key) +{ + return syscall(__NR_keyctl, KEYCTL_REVOKE, key); +} + +/* keyctl_unlink */ +static long keyctl_unlink(key_serial_t key, key_serial_t keyring) +{ + return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring); +} +#endif + +int keyring_check(void) +{ +#ifdef KERNEL_KEYRING + /* logon type key descriptions must be in format "prefix:description" */ + return syscall(__NR_request_key, "logon", "dummy", NULL, 0) == -1l && errno != ENOSYS; +#else + return 0; +#endif +} + +int keyring_add_key_in_thread_keyring(key_type_t ktype, const char *key_desc, const void *key, size_t key_size) +{ +#ifdef KERNEL_KEYRING + key_serial_t kid; + const char *type_name = key_type_name(ktype); + + if (!type_name || !key_desc) + return -EINVAL; + + kid = add_key(type_name, key_desc, key, key_size, KEY_SPEC_THREAD_KEYRING); + if (kid < 0) + return -errno; + + return 0; +#else + return -ENOTSUP; +#endif +} + +/* currently used in client utilities only */ +int keyring_add_key_in_user_keyring(key_type_t ktype, const char *key_desc, const void *key, size_t key_size) +{ +#ifdef KERNEL_KEYRING + const char *type_name = key_type_name(ktype); + key_serial_t kid; + + if (!type_name || !key_desc) + return -EINVAL; + + kid = add_key(type_name, key_desc, key, key_size, KEY_SPEC_USER_KEYRING); + if (kid < 0) + return -errno; + + return 0; +#else + return -ENOTSUP; +#endif +} + +/* alias for the same code */ +int keyring_get_key(const char *key_desc, + char **key, + size_t *key_size) +{ + return keyring_get_passphrase(key_desc, key, key_size); +} + +int keyring_get_passphrase(const char *key_desc, + char **passphrase, + size_t *passphrase_len) +{ +#ifdef KERNEL_KEYRING + int err; + key_serial_t kid; + long ret; + char *buf = NULL; + size_t len = 0; + + do + kid = request_key(key_type_name(USER_KEY), key_desc, NULL, 0); + while (kid < 0 && errno == EINTR); + + if (kid < 0) + return -errno; + + /* just get payload size */ + ret = keyctl_read(kid, NULL, 0); + if (ret > 0) { + len = ret; + buf = malloc(len); + if (!buf) + return -ENOMEM; + + /* retrieve actual payload data */ + ret = keyctl_read(kid, buf, len); + } + + if (ret < 0) { + err = errno; + if (buf) + crypt_safe_memzero(buf, len); + free(buf); + return -err; + } + + *passphrase = buf; + *passphrase_len = len; + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int keyring_revoke_and_unlink_key_type(const char *type_name, const char *key_desc) +{ +#ifdef KERNEL_KEYRING + key_serial_t kid; + + if (!type_name || !key_desc) + return -EINVAL; + + do + kid = request_key(type_name, key_desc, NULL, 0); + while (kid < 0 && errno == EINTR); + + if (kid < 0) + return 0; + + if (keyctl_revoke(kid)) + return -errno; + + /* + * best effort only. the key could have been linked + * in some other keyring and its payload is now + * revoked anyway. + */ + keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING); + keyctl_unlink(kid, KEY_SPEC_PROCESS_KEYRING); + keyctl_unlink(kid, KEY_SPEC_USER_KEYRING); + + return 0; +#else + return -ENOTSUP; +#endif +} + +const char *key_type_name(key_type_t type) +{ +#ifdef KERNEL_KEYRING + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(key_types); i++) + if (type == key_types[i].type) + return key_types[i].type_name; +#endif + return NULL; +} + +int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc) +{ + return keyring_revoke_and_unlink_key_type(key_type_name(ktype), key_desc); +} diff --git a/lib/utils_keyring.h b/lib/utils_keyring.h new file mode 100644 index 0000000..37a5ac6 --- /dev/null +++ b/lib/utils_keyring.h @@ -0,0 +1,55 @@ +/* + * kernel keyring syscall wrappers + * + * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2016-2020 Ondrej Kozina + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _UTILS_KEYRING +#define _UTILS_KEYRING + +#include + +typedef enum { LOGON_KEY = 0, USER_KEY } key_type_t; + +const char *key_type_name(key_type_t ktype); + +int keyring_check(void); + +int keyring_get_key(const char *key_desc, + char **key, + size_t *key_size); + +int keyring_get_passphrase(const char *key_desc, + char **passphrase, + size_t *passphrase_len); + +int keyring_add_key_in_thread_keyring( + key_type_t ktype, + const char *key_desc, + const void *key, + size_t key_size); + +int keyring_add_key_in_user_keyring( + key_type_t ktype, + const char *key_desc, + const void *key, + size_t key_size); + +int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc); + +#endif diff --git a/lib/utils_loop.c b/lib/utils_loop.c index d7b03a1..9696a40 100644 --- a/lib/utils_loop.c +++ b/lib/utils_loop.c @@ -1,8 +1,8 @@ /* * loopback block device utilities * - * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include #include @@ -28,6 +29,9 @@ #include #include #include +#ifdef HAVE_SYS_SYSMACROS_H +# include /* for major, minor */ +#endif #include #include "utils_loop.h" @@ -42,6 +46,10 @@ #define LOOP_CTL_GET_FREE 0x4C82 #endif +#ifndef LOOP_SET_CAPACITY +#define LOOP_SET_CAPACITY 0x4C07 +#endif + static char *crypt_loop_get_device_old(void) { char dev[20]; @@ -66,7 +74,7 @@ static char *crypt_loop_get_device_old(void) return NULL; } -char *crypt_loop_get_device(void) +static char *crypt_loop_get_device(void) { char dev[64]; int i, loop_fd; @@ -92,12 +100,15 @@ char *crypt_loop_get_device(void) return strdup(dev); } -int crypt_loop_attach(const char *loop, const char *file, int offset, +int crypt_loop_attach(char **loop, const char *file, int offset, int autoclear, int *readonly) { struct loop_info64 lo64 = {0}; + char *lo_file_name; int loop_fd = -1, file_fd = -1, r = 1; + *loop = NULL; + file_fd = open(file, (*readonly ? O_RDONLY : O_RDWR) | O_EXCL); if (file_fd < 0 && (errno == EROFS || errno == EACCES) && !*readonly) { *readonly = 1; @@ -106,18 +117,33 @@ int crypt_loop_attach(const char *loop, const char *file, int offset, if (file_fd < 0) goto out; - loop_fd = open(loop, *readonly ? O_RDONLY : O_RDWR); - if (loop_fd < 0) - goto out; + while (loop_fd < 0) { + *loop = crypt_loop_get_device(); + if (!*loop) + goto out; - strncpy((char*)lo64.lo_file_name, file, LO_NAME_SIZE); + loop_fd = open(*loop, *readonly ? O_RDONLY : O_RDWR); + if (loop_fd < 0) + goto out; + + if (ioctl(loop_fd, LOOP_SET_FD, file_fd) < 0) { + if (errno != EBUSY) + goto out; + free(*loop); + *loop = NULL; + + close(loop_fd); + loop_fd = -1; + } + } + + lo_file_name = (char*)lo64.lo_file_name; + lo_file_name[LO_NAME_SIZE-1] = '\0'; + strncpy(lo_file_name, file, LO_NAME_SIZE-1); lo64.lo_offset = offset; if (autoclear) lo64.lo_flags |= LO_FLAGS_AUTOCLEAR; - if (ioctl(loop_fd, LOOP_SET_FD, file_fd) < 0) - goto out; - if (ioctl(loop_fd, LOOP_SET_STATUS64, &lo64) < 0) { (void)ioctl(loop_fd, LOOP_CLR_FD, 0); goto out; @@ -139,6 +165,10 @@ out: close(loop_fd); if (file_fd >= 0) close(file_fd); + if (r && *loop) { + free(*loop); + *loop = NULL; + } return r ? -1 : loop_fd; } @@ -157,6 +187,21 @@ int crypt_loop_detach(const char *loop) return r; } +int crypt_loop_resize(const char *loop) +{ + int loop_fd = -1, r = 1; + + loop_fd = open(loop, O_RDONLY); + if (loop_fd < 0) + return 1; + + if (!ioctl(loop_fd, LOOP_SET_CAPACITY, 0)) + r = 0; + + close(loop_fd); + return r; +} + static char *_ioctl_backing_file(const char *loop) { struct loop_info64 lo64 = {0}; @@ -207,7 +252,12 @@ static char *_sysfs_backing_file(const char *loop) char *crypt_loop_backing_file(const char *loop) { - char *bf = _sysfs_backing_file(loop); + char *bf; + + if (!crypt_loop_device(loop)) + return NULL; + + bf = _sysfs_backing_file(loop); return bf ?: _ioctl_backing_file(loop); } diff --git a/lib/utils_loop.h b/lib/utils_loop.h index 052623d..a3572dc 100644 --- a/lib/utils_loop.h +++ b/lib/utils_loop.h @@ -1,7 +1,8 @@ /* * loopback block device utilities * - * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,11 +24,11 @@ /* loopback device helpers */ -char *crypt_loop_get_device(void); char *crypt_loop_backing_file(const char *loop); int crypt_loop_device(const char *loop); -int crypt_loop_attach(const char *loop, const char *file, int offset, +int crypt_loop_attach(char **loop, const char *file, int offset, int autoclear, int *readonly); int crypt_loop_detach(const char *loop); +int crypt_loop_resize(const char *loop); #endif /* _UTILS_LOOP_H */ diff --git a/lib/utils_pbkdf.c b/lib/utils_pbkdf.c new file mode 100644 index 0000000..967bb2c --- /dev/null +++ b/lib/utils_pbkdf.c @@ -0,0 +1,333 @@ +/* + * utils_pbkdf - PBKDF settings for libcryptsetup + * + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "internal.h" + +const struct crypt_pbkdf_type default_pbkdf2 = { + .type = CRYPT_KDF_PBKDF2, + .hash = DEFAULT_LUKS1_HASH, + .time_ms = DEFAULT_LUKS1_ITER_TIME +}; + +const struct crypt_pbkdf_type default_argon2i = { + .type = CRYPT_KDF_ARGON2I, + .hash = DEFAULT_LUKS1_HASH, + .time_ms = DEFAULT_LUKS2_ITER_TIME, + .max_memory_kb = DEFAULT_LUKS2_MEMORY_KB, + .parallel_threads = DEFAULT_LUKS2_PARALLEL_THREADS +}; + +const struct crypt_pbkdf_type default_argon2id = { + .type = CRYPT_KDF_ARGON2ID, + .hash = DEFAULT_LUKS1_HASH, + .time_ms = DEFAULT_LUKS2_ITER_TIME, + .max_memory_kb = DEFAULT_LUKS2_MEMORY_KB, + .parallel_threads = DEFAULT_LUKS2_PARALLEL_THREADS +}; + +const struct crypt_pbkdf_type *crypt_get_pbkdf_type_params(const char *pbkdf_type) +{ + if (!pbkdf_type) + return NULL; + + if (!strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) + return &default_pbkdf2; + else if (!strcmp(pbkdf_type, CRYPT_KDF_ARGON2I)) + return &default_argon2i; + else if (!strcmp(pbkdf_type, CRYPT_KDF_ARGON2ID)) + return &default_argon2id; + + return NULL; +} + +static uint32_t adjusted_phys_memory(void) +{ + uint64_t memory_kb = crypt_getphysmemory_kb(); + + /* Ignore bogus value */ + if (memory_kb < (128 * 1024) || memory_kb > UINT32_MAX) + return DEFAULT_LUKS2_MEMORY_KB; + + /* + * Never use more than half of physical memory. + * OOM killer is too clever... + */ + memory_kb /= 2; + + return memory_kb; +} + +/* + * PBKDF configuration interface + */ +int verify_pbkdf_params(struct crypt_device *cd, + const struct crypt_pbkdf_type *pbkdf) +{ + struct crypt_pbkdf_limits pbkdf_limits; + const char *pbkdf_type; + int r; + + r = init_crypto(cd); + if (r < 0) + return r; + + if (!pbkdf->type || + (!pbkdf->hash && !strcmp(pbkdf->type, "pbkdf2"))) + return -EINVAL; + + if (!pbkdf->time_ms && !(pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK)) { + log_err(cd, _("Requested PBKDF target time cannot be zero.")); + return -EINVAL; + } + + r = crypt_parse_pbkdf(pbkdf->type, &pbkdf_type); + if (r < 0) { + log_err(cd, _("Unknown PBKDF type %s."), pbkdf->type); + return r; + } + + if (pbkdf->hash && crypt_hash_size(pbkdf->hash) < 0) { + log_err(cd, _("Requested hash %s is not supported."), pbkdf->hash); + return -EINVAL; + } + + r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits); + if (r < 0) + return r; + + if (crypt_get_type(cd) && + !strcmp(crypt_get_type(cd), CRYPT_LUKS1) && + strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) { + log_err(cd, _("Requested PBKDF type is not supported for LUKS1.")); + return -EINVAL; + } + + if (!strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) { + if (pbkdf->max_memory_kb || pbkdf->parallel_threads) { + log_err(cd, _("PBKDF max memory or parallel threads must not be set with pbkdf2.")); + return -EINVAL; + } + if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK && + pbkdf->iterations < pbkdf_limits.min_iterations) { + log_err(cd, _("Forced iteration count is too low for %s (minimum is %u)."), + pbkdf_type, pbkdf_limits.min_iterations); + return -EINVAL; + } + return 0; + } + + /* TODO: properly define minimal iterations and also minimal memory values */ + if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) { + if (pbkdf->iterations < pbkdf_limits.min_iterations) { + log_err(cd, _("Forced iteration count is too low for %s (minimum is %u)."), + pbkdf_type, pbkdf_limits.min_iterations); + r = -EINVAL; + } + if (pbkdf->max_memory_kb < pbkdf_limits.min_memory) { + log_err(cd, _("Forced memory cost is too low for %s (minimum is %u kilobytes)."), + pbkdf_type, pbkdf_limits.min_memory); + r = -EINVAL; + } + } + + if (pbkdf->max_memory_kb > pbkdf_limits.max_memory) { + log_err(cd, _("Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."), + pbkdf_limits.max_memory); + r = -EINVAL; + } + if (!pbkdf->max_memory_kb) { + log_err(cd, _("Requested maximum PBKDF memory cannot be zero.")); + r = -EINVAL; + } + if (!pbkdf->parallel_threads) { + log_err(cd, _("Requested PBKDF parallel threads cannot be zero.")); + r = -EINVAL; + } + + return r; +} + +int init_pbkdf_type(struct crypt_device *cd, + const struct crypt_pbkdf_type *pbkdf, + const char *dev_type) +{ + struct crypt_pbkdf_type *cd_pbkdf = crypt_get_pbkdf(cd); + struct crypt_pbkdf_limits pbkdf_limits; + const char *hash, *type; + unsigned cpus; + uint32_t old_flags, memory_kb; + int r; + + if (crypt_fips_mode()) { + if (pbkdf && strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) { + log_err(cd, _("Only PBKDF2 is supported in FIPS mode.")); + return -EINVAL; + } + if (!pbkdf) + pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2); + } + + if (!pbkdf && dev_type && !strcmp(dev_type, CRYPT_LUKS2)) + pbkdf = crypt_get_pbkdf_type_params(DEFAULT_LUKS2_PBKDF); + else if (!pbkdf) + pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2); + + r = verify_pbkdf_params(cd, pbkdf); + if (r) + return r; + + r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits); + if (r < 0) + return r; + + type = strdup(pbkdf->type); + hash = pbkdf->hash ? strdup(pbkdf->hash) : NULL; + + if (!type || (!hash && pbkdf->hash)) { + free(CONST_CAST(void*)type); + free(CONST_CAST(void*)hash); + return -ENOMEM; + } + + free(CONST_CAST(void*)cd_pbkdf->type); + free(CONST_CAST(void*)cd_pbkdf->hash); + cd_pbkdf->type = type; + cd_pbkdf->hash = hash; + + old_flags = cd_pbkdf->flags; + cd_pbkdf->flags = pbkdf->flags; + + /* Reset iteration count so benchmark must run again. */ + if (cd_pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) + cd_pbkdf->iterations = pbkdf->iterations; + else + cd_pbkdf->iterations = 0; + + if (old_flags & CRYPT_PBKDF_ITER_TIME_SET) + cd_pbkdf->flags |= CRYPT_PBKDF_ITER_TIME_SET; + else + cd_pbkdf->time_ms = pbkdf->time_ms; + + cd_pbkdf->max_memory_kb = pbkdf->max_memory_kb; + cd_pbkdf->parallel_threads = pbkdf->parallel_threads; + + if (cd_pbkdf->parallel_threads > pbkdf_limits.max_parallel) { + log_dbg(cd, "Maximum PBKDF threads is %d (requested %d).", + pbkdf_limits.max_parallel, cd_pbkdf->parallel_threads); + cd_pbkdf->parallel_threads = pbkdf_limits.max_parallel; + } + + if (cd_pbkdf->parallel_threads) { + cpus = crypt_cpusonline(); + if (cd_pbkdf->parallel_threads > cpus) { + log_dbg(cd, "Only %u active CPUs detected, " + "PBKDF threads decreased from %d to %d.", + cpus, cd_pbkdf->parallel_threads, cpus); + cd_pbkdf->parallel_threads = cpus; + } + } + + if (cd_pbkdf->max_memory_kb) { + memory_kb = adjusted_phys_memory(); + if (cd_pbkdf->max_memory_kb > memory_kb) { + log_dbg(cd, "Not enough physical memory detected, " + "PBKDF max memory decreased from %dkB to %dkB.", + cd_pbkdf->max_memory_kb, memory_kb); + cd_pbkdf->max_memory_kb = memory_kb; + } + } + + if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) + log_dbg(cd, "PBKDF %s-%s, time_ms %u (iterations %u).", + cd_pbkdf->type, cd_pbkdf->hash, cd_pbkdf->time_ms, cd_pbkdf->iterations); + else + log_dbg(cd, "PBKDF %s, time_ms %u (iterations %u), max_memory_kb %u, parallel_threads %u.", + cd_pbkdf->type, cd_pbkdf->time_ms, cd_pbkdf->iterations, + cd_pbkdf->max_memory_kb, cd_pbkdf->parallel_threads); + + return 0; +} + +/* Libcryptsetup API */ + +int crypt_set_pbkdf_type(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf) +{ + if (!cd) + return -EINVAL; + + if (!pbkdf) + log_dbg(cd, "Resetting pbkdf type to default"); + + crypt_get_pbkdf(cd)->flags = 0; + + return init_pbkdf_type(cd, pbkdf, crypt_get_type(cd)); +} + +const struct crypt_pbkdf_type *crypt_get_pbkdf_type(struct crypt_device *cd) +{ + if (!cd) + return NULL; + + return crypt_get_pbkdf(cd)->type ? crypt_get_pbkdf(cd) : NULL; +} + +const struct crypt_pbkdf_type *crypt_get_pbkdf_default(const char *type) +{ + if (!type) + return NULL; + + if (!strcmp(type, CRYPT_LUKS1) || crypt_fips_mode()) + return crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2); + else if (!strcmp(type, CRYPT_LUKS2)) + return crypt_get_pbkdf_type_params(DEFAULT_LUKS2_PBKDF); + + return NULL; +} + +void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms) +{ + struct crypt_pbkdf_type *pbkdf; + uint32_t old_time_ms; + + if (!cd || iteration_time_ms > UINT32_MAX) + return; + + pbkdf = crypt_get_pbkdf(cd); + old_time_ms = pbkdf->time_ms; + pbkdf->time_ms = (uint32_t)iteration_time_ms; + + if (pbkdf->type && verify_pbkdf_params(cd, pbkdf)) { + pbkdf->time_ms = old_time_ms; + log_dbg(cd, "Invalid iteration time."); + return; + } + + pbkdf->flags |= CRYPT_PBKDF_ITER_TIME_SET; + + /* iterations must be benchmarked now */ + pbkdf->flags &= ~(CRYPT_PBKDF_NO_BENCHMARK); + pbkdf->iterations = 0; + + log_dbg(cd, "Iteration time set to %" PRIu64 " milliseconds.", iteration_time_ms); +} diff --git a/lib/utils_safe_memory.c b/lib/utils_safe_memory.c new file mode 100644 index 0000000..8c1fb5c --- /dev/null +++ b/lib/utils_safe_memory.c @@ -0,0 +1,102 @@ +/* + * utils_safe_memory - safe memory helpers + * + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include "libcryptsetup.h" + +struct safe_allocation { + size_t size; + char data[0]; +}; + +/* + * Replacement for memset(s, 0, n) on stack that can be optimized out + * Also used in safe allocations for explicit memory wipe. + */ +void crypt_safe_memzero(void *data, size_t size) +{ +#ifdef HAVE_EXPLICIT_BZERO + explicit_bzero(data, size); +#else + volatile uint8_t *p = (volatile uint8_t *)data; + + while(size--) + *p++ = 0; +#endif +} + +/* safe allocations */ +void *crypt_safe_alloc(size_t size) +{ + struct safe_allocation *alloc; + + if (!size || size > (SIZE_MAX - offsetof(struct safe_allocation, data))) + return NULL; + + alloc = malloc(size + offsetof(struct safe_allocation, data)); + if (!alloc) + return NULL; + + alloc->size = size; + crypt_safe_memzero(&alloc->data, size); + + /* coverity[leaked_storage] */ + return &alloc->data; +} + +void crypt_safe_free(void *data) +{ + struct safe_allocation *alloc; + + if (!data) + return; + + alloc = (struct safe_allocation *) + ((char *)data - offsetof(struct safe_allocation, data)); + + crypt_safe_memzero(data, alloc->size); + + alloc->size = 0x55aa55aa; + free(alloc); +} + +void *crypt_safe_realloc(void *data, size_t size) +{ + struct safe_allocation *alloc; + void *new_data; + + new_data = crypt_safe_alloc(size); + + if (new_data && data) { + + alloc = (struct safe_allocation *) + ((char *)data - offsetof(struct safe_allocation, data)); + + if (size > alloc->size) + size = alloc->size; + + memcpy(new_data, data, size); + } + + crypt_safe_free(data); + return new_data; +} diff --git a/lib/utils_storage_wrappers.c b/lib/utils_storage_wrappers.c new file mode 100644 index 0000000..b7e816b --- /dev/null +++ b/lib/utils_storage_wrappers.c @@ -0,0 +1,394 @@ +/* + * Generic wrapper for storage functions + * (experimental only) + * + * Copyright (C) 2018-2020, Ondrej Kozina + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils_storage_wrappers.h" +#include "internal.h" + +struct crypt_storage_wrapper { + crypt_storage_wrapper_type type; + int dev_fd; + int block_size; + size_t mem_alignment; + uint64_t data_offset; + union { + struct { + struct crypt_storage *s; + uint64_t iv_start; + } cb; + struct { + int dmcrypt_fd; + char name[PATH_MAX]; + } dm; + } u; +}; + +static int crypt_storage_backend_init(struct crypt_device *cd, + struct crypt_storage_wrapper *w, + uint64_t iv_start, + int sector_size, + const char *cipher, + const char *cipher_mode, + const struct volume_key *vk, + uint32_t flags) +{ + int r; + struct crypt_storage *s; + + /* iv_start, sector_size */ + r = crypt_storage_init(&s, sector_size, cipher, cipher_mode, vk->key, vk->keylength); + if (r) + return r; + + if ((flags & DISABLE_KCAPI) && crypt_storage_kernel_only(s)) { + log_dbg(cd, "Could not initialize userspace block cipher and kernel fallback is disabled."); + crypt_storage_destroy(s); + return -ENOTSUP; + } + + w->type = USPACE; + w->u.cb.s = s; + w->u.cb.iv_start = iv_start; + + return 0; +} + +static int crypt_storage_dmcrypt_init( + struct crypt_device *cd, + struct crypt_storage_wrapper *cw, + struct device *device, + uint64_t device_offset, + uint64_t iv_start, + int sector_size, + const char *cipher_spec, + struct volume_key *vk, + int open_flags) +{ + static int counter = 0; + char path[PATH_MAX]; + struct crypt_dm_active_device dmd = { + .flags = CRYPT_ACTIVATE_PRIVATE, + }; + int mode, r, fd = -1; + + log_dbg(cd, "Using temporary dmcrypt to access data."); + + if (snprintf(cw->u.dm.name, sizeof(cw->u.dm.name), "temporary-cryptsetup-%d-%d", getpid(), counter++) < 0) + return -ENOMEM; + if (snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), cw->u.dm.name) < 0) + return -ENOMEM; + + r = device_block_adjust(cd, device, DEV_OK, + device_offset, &dmd.size, &dmd.flags); + if (r < 0) { + log_err(cd, _("Device %s does not exist or access denied."), + device_path(device)); + return -EIO; + } + + mode = open_flags | O_DIRECT; + if (dmd.flags & CRYPT_ACTIVATE_READONLY) + mode = (open_flags & ~O_ACCMODE) | O_RDONLY; + + if (vk->key_description) + dmd.flags |= CRYPT_ACTIVATE_KEYRING_KEY; + + r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, + device, + vk, + cipher_spec, + iv_start, + device_offset, + NULL, + 0, + sector_size); + if (r) + return r; + + r = dm_create_device(cd, cw->u.dm.name, "TEMP", &dmd); + if (r < 0) { + if (r != -EACCES && r != -ENOTSUP) + log_dbg(cd, "error hint would be nice"); + r = -EIO; + } + + dm_targets_free(cd, &dmd); + + if (r) + return r; + + fd = open(path, mode); + if (fd < 0) { + log_dbg(cd, "Failed to open %s", path); + dm_remove_device(cd, cw->u.dm.name, CRYPT_DEACTIVATE_FORCE); + return -EINVAL; + } + + cw->type = DMCRYPT; + cw->u.dm.dmcrypt_fd = fd; + + return 0; +} + +int crypt_storage_wrapper_init(struct crypt_device *cd, + struct crypt_storage_wrapper **cw, + struct device *device, + uint64_t data_offset, + uint64_t iv_start, + int sector_size, + const char *cipher, + struct volume_key *vk, + uint32_t flags) +{ + int open_flags, r; + char _cipher[MAX_CIPHER_LEN], mode[MAX_CIPHER_LEN]; + struct crypt_storage_wrapper *w; + + /* device-mapper restrictions */ + if (data_offset & ((1 << SECTOR_SHIFT) - 1)) + return -EINVAL; + + if (crypt_parse_name_and_mode(cipher, _cipher, NULL, mode)) + return -EINVAL; + + open_flags = O_CLOEXEC | ((flags & OPEN_READONLY) ? O_RDONLY : O_RDWR); + + w = malloc(sizeof(*w)); + if (!w) + return -ENOMEM; + + memset(w, 0, sizeof(*w)); + w->data_offset = data_offset; + w->mem_alignment = device_alignment(device); + w->block_size = device_block_size(cd, device); + if (!w->block_size || !w->mem_alignment) { + log_dbg(cd, "block size or alignment error."); + r = -EINVAL; + goto err; + } + + w->dev_fd = device_open(cd, device, open_flags); + if (w->dev_fd < 0) { + r = -EINVAL; + goto err; + } + + if (!strcmp(_cipher, "cipher_null")) { + log_dbg(cd, "Requested cipher_null, switching to noop wrapper."); + w->type = NONE; + *cw = w; + return 0; + } + + if (!vk) { + log_dbg(cd, "no key passed."); + r = -EINVAL; + goto err; + } + + r = crypt_storage_backend_init(cd, w, iv_start, sector_size, _cipher, mode, vk, flags); + if (!r) { + *cw = w; + return 0; + } + + log_dbg(cd, "Failed to initialize userspace block cipher."); + + if ((r != -ENOTSUP && r != -ENOENT) || (flags & DISABLE_DMCRYPT)) + goto err; + + r = crypt_storage_dmcrypt_init(cd, w, device, data_offset >> SECTOR_SHIFT, iv_start, + sector_size, cipher, vk, open_flags); + if (r) { + log_dbg(cd, "Dm-crypt backend failed to initialize."); + goto err; + } + *cw = w; + return 0; +err: + crypt_storage_wrapper_destroy(w); + /* wrapper destroy */ + return r; +} + +/* offset is relative to sector_start */ +ssize_t crypt_storage_wrapper_read(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + return read_lseek_blockwise(cw->dev_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + cw->data_offset + offset); +} + +ssize_t crypt_storage_wrapper_read_decrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + int r; + ssize_t read; + + if (cw->type == DMCRYPT) + return read_lseek_blockwise(cw->u.dm.dmcrypt_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + offset); + + read = read_lseek_blockwise(cw->dev_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + cw->data_offset + offset); + if (cw->type == NONE || read < 0) + return read; + + r = crypt_storage_decrypt(cw->u.cb.s, + cw->u.cb.iv_start + (offset >> SECTOR_SHIFT), + read, + buffer); + if (r) + return -EINVAL; + + return read; +} + +ssize_t crypt_storage_wrapper_decrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + int r; + ssize_t read; + + if (cw->type == NONE) + return 0; + + if (cw->type == DMCRYPT) { + /* there's nothing we can do, just read/decrypt via dm-crypt */ + read = crypt_storage_wrapper_read_decrypt(cw, offset, buffer, buffer_length); + if (read < 0 || (size_t)read != buffer_length) + return -EINVAL; + return 0; + } + + r = crypt_storage_decrypt(cw->u.cb.s, + cw->u.cb.iv_start + (offset >> SECTOR_SHIFT), + buffer_length, + buffer); + if (r) + return r; + + return 0; +} + +ssize_t crypt_storage_wrapper_write(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + return write_lseek_blockwise(cw->dev_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + cw->data_offset + offset); +} + +ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + if (cw->type == DMCRYPT) + return write_lseek_blockwise(cw->u.dm.dmcrypt_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + offset); + + if (cw->type == USPACE && + crypt_storage_encrypt(cw->u.cb.s, + cw->u.cb.iv_start + (offset >> SECTOR_SHIFT), + buffer_length, buffer)) + return -EINVAL; + + return write_lseek_blockwise(cw->dev_fd, + cw->block_size, + cw->mem_alignment, + buffer, + buffer_length, + cw->data_offset + offset); +} + +ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length) +{ + if (cw->type == NONE) + return 0; + + if (cw->type == DMCRYPT) + return -ENOTSUP; + + if (crypt_storage_encrypt(cw->u.cb.s, + cw->u.cb.iv_start + (offset >> SECTOR_SHIFT), + buffer_length, + buffer)) + return -EINVAL; + + return 0; +} + +void crypt_storage_wrapper_destroy(struct crypt_storage_wrapper *cw) +{ + if (!cw) + return; + + if (cw->type == USPACE) + crypt_storage_destroy(cw->u.cb.s); + if (cw->type == DMCRYPT) { + close(cw->u.dm.dmcrypt_fd); + dm_remove_device(NULL, cw->u.dm.name, CRYPT_DEACTIVATE_FORCE); + } + + free(cw); +} + +int crypt_storage_wrapper_datasync(const struct crypt_storage_wrapper *cw) +{ + if (!cw) + return -EINVAL; + if (cw->type == DMCRYPT) + return fdatasync(cw->u.dm.dmcrypt_fd); + else + return fdatasync(cw->dev_fd); +} + +crypt_storage_wrapper_type crypt_storage_wrapper_get_type(const struct crypt_storage_wrapper *cw) +{ + return cw ? cw->type : NONE; +} diff --git a/lib/utils_storage_wrappers.h b/lib/utils_storage_wrappers.h new file mode 100644 index 0000000..aaaa824 --- /dev/null +++ b/lib/utils_storage_wrappers.h @@ -0,0 +1,71 @@ +/* + * Generic wrapper for storage functions + * (experimental only) + * + * Copyright (C) 2018-2020, Ondrej Kozina + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _UTILS_STORAGE_WRAPPERS_H +#define _UTILS_STORAGE_WRAPPERS_H + +struct crypt_storage_wrapper; +struct device; +struct volume_key; +struct crypt_device; + +#define DISABLE_USPACE (1 << 0) +#define DISABLE_KCAPI (1 << 1) +#define DISABLE_DMCRYPT (1 << 2) +#define OPEN_READONLY (1 << 3) + +typedef enum { + NONE = 0, + USPACE, + DMCRYPT +} crypt_storage_wrapper_type; + +int crypt_storage_wrapper_init(struct crypt_device *cd, + struct crypt_storage_wrapper **cw, + struct device *device, + uint64_t data_offset, + uint64_t iv_start, + int sector_size, + const char *cipher, + struct volume_key *vk, + uint32_t flags); + +void crypt_storage_wrapper_destroy(struct crypt_storage_wrapper *cw); + +/* !!! when doing 'read' or 'write' all offset values are RELATIVE to data_offset !!! */ +ssize_t crypt_storage_wrapper_read(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); +ssize_t crypt_storage_wrapper_read_decrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); +ssize_t crypt_storage_wrapper_decrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); + +ssize_t crypt_storage_wrapper_write(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); +ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); +ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw, + off_t offset, void *buffer, size_t buffer_length); + +int crypt_storage_wrapper_datasync(const struct crypt_storage_wrapper *cw); + +crypt_storage_wrapper_type crypt_storage_wrapper_get_type(const struct crypt_storage_wrapper *cw); +#endif diff --git a/lib/utils_wipe.c b/lib/utils_wipe.c index 210c566..96dff29 100644 --- a/lib/utils_wipe.c +++ b/lib/utils_wipe.c @@ -1,9 +1,9 @@ /* * utils_wipe - wipe a device * - * Copyright (C) 2004-2007, Clemens Fruhwirth - * Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2012, Milan Broz + * Copyright (C) 2004-2007 Clemens Fruhwirth + * Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2020 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,41 +20,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include #include #include -#include -#include -#include -#include -#include -#include - -#include "libcryptsetup.h" #include "internal.h" -#define MAXIMUM_WIPE_BYTES 1024 * 1024 * 32 /* 32 MiB */ - -static ssize_t _crypt_wipe_zero(int fd, int bsize, char *buffer, - uint64_t offset, uint64_t size) -{ - memset(buffer, 0, size); - return write_lseek_blockwise(fd, bsize, buffer, size, offset); -} - -static ssize_t _crypt_wipe_random(int fd, int bsize, char *buffer, - uint64_t offset, uint64_t size) -{ - if (crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL) < 0) - return -EINVAL; - - return write_lseek_blockwise(fd, bsize, buffer, size, offset); -} - /* * Wipe using Peter Gutmann method described in * http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html + * Note: used only for rotational device (and even there it is not needed today...) */ static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn) { @@ -72,126 +45,222 @@ static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn) {"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"} }; - for(i = 0; i < buffer_size / 3; ++i) { + for (i = 0; i < buffer_size / 3; ++i) { memcpy(buffer, write_modes[turn], 3); buffer += 3; } } -static ssize_t _crypt_wipe_disk(int fd, int bsize, char *buffer, - uint64_t offset, uint64_t size) +static int crypt_wipe_special(struct crypt_device *cd, int fd, size_t bsize, + size_t alignment, char *buffer, + uint64_t offset, size_t size) { - int r; + int r = 0; unsigned int i; ssize_t written; - for(i = 0; i < 39; ++i) { + for (i = 0; i < 39; ++i) { if (i < 5) { - r = crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL); - } else if(i >= 5 && i < 32) { + r = crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL); + } else if (i >= 5 && i < 32) { wipeSpecial(buffer, size, i - 5); r = 0; - } else if(i >= 32 && i < 38) { - r = crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL); - } else if(i >= 38 && i < 39) { + } else if (i >= 32 && i < 38) { + r = crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL); + } else if (i >= 38 && i < 39) { memset(buffer, 0xFF, size); r = 0; } if (r < 0) - return r; + return -EIO; - written = write_lseek_blockwise(fd, bsize, buffer, size, offset); + written = write_lseek_blockwise(fd, bsize, alignment, + buffer, size, offset); if (written < 0 || written != (ssize_t)size) - return written; + return -EIO; } /* Rewrite it finally with random */ - return _crypt_wipe_random(fd, bsize, buffer, offset, size); + if (crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL) < 0) + return -EIO; + + written = write_lseek_blockwise(fd, bsize, alignment, buffer, size, offset); + if (written < 0 || written != (ssize_t)size) + return -EIO; + + return 0; } -static ssize_t _crypt_wipe_ssd(int fd, int bsize, char *buffer, - uint64_t offset, uint64_t size) +static int wipe_block(struct crypt_device *cd, int devfd, crypt_wipe_pattern pattern, + char *sf, size_t device_block_size, size_t alignment, + size_t wipe_block_size, uint64_t offset, bool *need_block_init) { - // FIXME: for now just rewrite it by random - return _crypt_wipe_random(fd, bsize, buffer, offset, size); + int r; + + if (pattern == CRYPT_WIPE_SPECIAL) + return crypt_wipe_special(cd, devfd, device_block_size, alignment, + sf, offset, wipe_block_size); + + if (*need_block_init) { + if (pattern == CRYPT_WIPE_ZERO) { + memset(sf, 0, wipe_block_size); + *need_block_init = false; + r = 0; + } else if (pattern == CRYPT_WIPE_RANDOM) { + r = crypt_random_get(cd, sf, wipe_block_size, + CRYPT_RND_NORMAL) ? -EIO : 0; + *need_block_init = true; + } else if (pattern == CRYPT_WIPE_ENCRYPTED_ZERO) { + // FIXME + r = crypt_random_get(cd, sf, wipe_block_size, + CRYPT_RND_NORMAL) ? -EIO : 0; + *need_block_init = true; + } else + r = -EINVAL; + + if (r) + return r; + } + + if (write_blockwise(devfd, device_block_size, alignment, sf, + wipe_block_size) == (ssize_t)wipe_block_size) + return 0; + + return -EIO; } -int crypt_wipe(struct device *device, - uint64_t offset, - uint64_t size, - crypt_wipe_type type, - int exclusive) +int crypt_wipe_device(struct crypt_device *cd, + struct device *device, + crypt_wipe_pattern pattern, + uint64_t offset, + uint64_t length, + size_t wipe_block_size, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr), + void *usrptr) { - struct stat st; - char *buffer; - int devfd, flags, bsize; - ssize_t written; + int r, devfd; + size_t bsize, alignment; + char *sf = NULL; + uint64_t dev_size; + bool need_block_init = true; - if (!size || size % SECTOR_SIZE || (size > MAXIMUM_WIPE_BYTES)) { - log_dbg("Unsuported wipe size for device %s: %ld.", - device_path(device), (unsigned long)size); + /* Note: LUKS1 calls it with wipe_block not aligned to multiple of bsize */ + bsize = device_block_size(cd, device); + alignment = device_alignment(device); + if (!bsize || !alignment || !wipe_block_size) return -EINVAL; - } - if (stat(device_path(device), &st) < 0) { - log_dbg("Device %s not found.", device_path(device)); + /* FIXME: if wipe_block_size < bsize, then a wipe is highly ineffective */ + + /* Everything must be aligned to SECTOR_SIZE */ + if (MISALIGNED_512(offset) || MISALIGNED_512(length) || MISALIGNED_512(wipe_block_size)) return -EINVAL; - } - if (type == CRYPT_WIPE_DISK && S_ISBLK(st.st_mode)) { - if (!crypt_dev_is_rotational(major(st.st_rdev), - minor(st.st_rdev))) { - type = CRYPT_WIPE_SSD; - log_dbg("Non-rotational device, using SSD wipe mode."); - } else - log_dbg("Rotational device, using normal wipe mode."); - } + if (device_is_locked(device)) + devfd = device_open_locked(cd, device, O_RDWR); + else + devfd = device_open(cd, device, O_RDWR); + if (devfd < 0) + return errno ? -errno : -EINVAL; - bsize = device_block_size(device); - if (bsize <= 0) - return -EINVAL; + if (length) + dev_size = offset + length; + else { + r = device_size(device, &dev_size); + if (r) + goto out; - buffer = malloc(size); - if (!buffer) - return -ENOMEM; + if (dev_size <= offset) { + r = -EINVAL; + goto out; + } + } - flags = O_RDWR; + r = posix_memalign((void **)&sf, alignment, wipe_block_size); + if (r) + goto out; - /* use O_EXCL only for block devices */ - if (exclusive && S_ISBLK(st.st_mode)) - flags |= O_EXCL; + if (lseek64(devfd, offset, SEEK_SET) < 0) { + log_err(cd, _("Cannot seek to device offset.")); + r = -EINVAL; + goto out; + } - /* coverity[toctou] */ - devfd = device_open(device, flags); - if (devfd == -1) { - free(buffer); - return errno ? -errno : -EINVAL; + if (progress && progress(dev_size, offset, usrptr)) { + r = -EINVAL; /* No change yet, treat this as a parameter error */ + goto out; } - // FIXME: use fixed block size and loop here - switch (type) { - case CRYPT_WIPE_ZERO: - written = _crypt_wipe_zero(devfd, bsize, buffer, offset, size); - break; - case CRYPT_WIPE_DISK: - written = _crypt_wipe_disk(devfd, bsize, buffer, offset, size); - break; - case CRYPT_WIPE_SSD: - written = _crypt_wipe_ssd(devfd, bsize, buffer, offset, size); + if (pattern == CRYPT_WIPE_SPECIAL && !device_is_rotational(device)) { + log_dbg(cd, "Non-rotational device, using random data wipe mode."); + pattern = CRYPT_WIPE_RANDOM; + } + + while (offset < dev_size) { + if ((offset + wipe_block_size) > dev_size) + wipe_block_size = dev_size - offset; + + //log_dbg("Wipe %012" PRIu64 "-%012" PRIu64 " bytes", offset, offset + wipe_block_size); + + r = wipe_block(cd, devfd, pattern, sf, bsize, alignment, + wipe_block_size, offset, &need_block_init); + if (r) { + log_err(cd,_("Device wipe error, offset %" PRIu64 "."), offset); break; - case CRYPT_WIPE_RANDOM: - written = _crypt_wipe_random(devfd, bsize, buffer, offset, size); + } + + offset += wipe_block_size; + + if (progress && progress(dev_size, offset, usrptr)) { + r = -EINTR; break; - default: - log_dbg("Unsuported wipe type requested: (%d)", type); - written = -1; + } } - close(devfd); - free(buffer); + device_sync(cd, device); +out: + free(sf); + return r; +} - if (written != (ssize_t)size || written < 0) - return -EIO; +int crypt_wipe(struct crypt_device *cd, + const char *dev_path, + crypt_wipe_pattern pattern, + uint64_t offset, + uint64_t length, + size_t wipe_block_size, + uint32_t flags, + int (*progress)(uint64_t size, uint64_t offset, void *usrptr), + void *usrptr) +{ + struct device *device; + int r; - return 0; + if (!cd) + return -EINVAL; + + if (!dev_path) + device = crypt_data_device(cd); + else { + r = device_alloc_no_check(&device, dev_path); + if (r < 0) + return r; + + if (flags & CRYPT_WIPE_NO_DIRECT_IO) + device_disable_direct_io(device); + } + + if (!wipe_block_size) + wipe_block_size = 1024*1024; + + log_dbg(cd, "Wipe [%u] device %s, offset %" PRIu64 ", length %" PRIu64 ", block %zu.", + (unsigned)pattern, device_path(device), offset, length, wipe_block_size); + + r = crypt_wipe_device(cd, device, pattern, offset, length, + wipe_block_size, progress, usrptr); + + if (dev_path) + device_free(cd, device); + + return r; } diff --git a/lib/verity/Makefile.am b/lib/verity/Makefile.am deleted file mode 100644 index b5ffc92..0000000 --- a/lib/verity/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -moduledir = $(libdir)/cryptsetup - -noinst_LTLIBRARIES = libverity.la - -libverity_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ - -libverity_la_SOURCES = \ - verity_hash.c \ - verity.c \ - verity.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend diff --git a/lib/verity/Makefile.in b/lib/verity/Makefile.in deleted file mode 100644 index bcb42e8..0000000 --- a/lib/verity/Makefile.in +++ /dev/null @@ -1,655 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = lib/verity -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libverity_la_LIBADD = -am_libverity_la_OBJECTS = libverity_la-verity_hash.lo \ - libverity_la-verity.lo -libverity_la_OBJECTS = $(am_libverity_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libverity_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libverity_la_CFLAGS) \ - $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libverity_la_SOURCES) -DIST_SOURCES = $(libverity_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -moduledir = $(libdir)/cryptsetup -noinst_LTLIBRARIES = libverity.la -libverity_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@ -libverity_la_SOURCES = \ - verity_hash.c \ - verity.c \ - verity.h - -AM_CPPFLAGS = -include config.h \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/crypto_backend - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/verity/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu lib/verity/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libverity.la: $(libverity_la_OBJECTS) $(libverity_la_DEPENDENCIES) $(EXTRA_libverity_la_DEPENDENCIES) - $(AM_V_CCLD)$(libverity_la_LINK) $(libverity_la_OBJECTS) $(libverity_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libverity_la-verity.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libverity_la-verity_hash.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -libverity_la-verity_hash.lo: verity_hash.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libverity_la_CFLAGS) $(CFLAGS) -MT libverity_la-verity_hash.lo -MD -MP -MF $(DEPDIR)/libverity_la-verity_hash.Tpo -c -o libverity_la-verity_hash.lo `test -f 'verity_hash.c' || echo '$(srcdir)/'`verity_hash.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libverity_la-verity_hash.Tpo $(DEPDIR)/libverity_la-verity_hash.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='verity_hash.c' object='libverity_la-verity_hash.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libverity_la_CFLAGS) $(CFLAGS) -c -o libverity_la-verity_hash.lo `test -f 'verity_hash.c' || echo '$(srcdir)/'`verity_hash.c - -libverity_la-verity.lo: verity.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libverity_la_CFLAGS) $(CFLAGS) -MT libverity_la-verity.lo -MD -MP -MF $(DEPDIR)/libverity_la-verity.Tpo -c -o libverity_la-verity.lo `test -f 'verity.c' || echo '$(srcdir)/'`verity.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libverity_la-verity.Tpo $(DEPDIR)/libverity_la-verity.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='verity.c' object='libverity_la-verity.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libverity_la_CFLAGS) $(CFLAGS) -c -o libverity_la-verity.lo `test -f 'verity.c' || echo '$(srcdir)/'`verity.c - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/lib/verity/rs.h b/lib/verity/rs.h new file mode 100644 index 0000000..9171814 --- /dev/null +++ b/lib/verity/rs.h @@ -0,0 +1,63 @@ +/* + * Reed-Solomon codecs, based on libfec + * + * Copyright (C) 2004 Phil Karn, KA9Q + * libcryptsetup modifications + * Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _LIBFEC_RS_H +#define _LIBFEC_RS_H + +/* Special reserved value encoding zero in index form. */ +#define A0 (rs->nn) + +#define RS_MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef unsigned char data_t; + +/* Reed-Solomon codec control block */ +struct rs { + int mm; /* Bits per symbol */ + int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} + +struct rs *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad); +void free_rs_char(struct rs *rs); + +/* General purpose RS codec, 8-bit symbols */ +void encode_rs_char(struct rs *rs, data_t *data, data_t *parity); +int decode_rs_char(struct rs *rs, data_t *data); + +#endif diff --git a/lib/verity/rs_decode_char.c b/lib/verity/rs_decode_char.c new file mode 100644 index 0000000..920475e --- /dev/null +++ b/lib/verity/rs_decode_char.c @@ -0,0 +1,197 @@ +/* + * Reed-Solomon decoder, based on libfec + * + * Copyright (C) 2002, Phil Karn, KA9Q + * libcryptsetup modifications + * Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "rs.h" + +int decode_rs_char(struct rs* rs, data_t* data) +{ + int deg_lambda, el, deg_omega, syn_error, count; + int i, j, r, k; + data_t q, tmp, num1, num2, den, discr_r; + /* FIXME: remove VLAs here */ + data_t lambda[rs->nroots + 1], s[rs->nroots]; /* Err+Eras Locator poly and syndrome poly */ + data_t b[rs->nroots + 1], t[rs->nroots + 1], omega[rs->nroots + 1]; + data_t root[rs->nroots], reg[rs->nroots + 1], loc[rs->nroots]; + + memset(s, 0, rs->nroots * sizeof(data_t)); + memset(b, 0, (rs->nroots + 1) * sizeof(data_t)); + + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for (i = 0; i < rs->nroots; i++) + s[i] = data[0]; + + for (j = 1; j < rs->nn - rs->pad; j++) { + for (i = 0; i < rs->nroots; i++) { + if (s[i] == 0) { + s[i] = data[j]; + } else { + s[i] = data[j] ^ rs->alpha_to[modnn(rs, rs->index_of[s[i]] + (rs->fcr + i) * rs->prim)]; + } + } + } + + /* Convert syndromes to index form, checking for nonzero condition */ + syn_error = 0; + for (i = 0; i < rs->nroots; i++) { + syn_error |= s[i]; + s[i] = rs->index_of[s[i]]; + } + + /* + * if syndrome is zero, data[] is a codeword and there are no + * errors to correct. So return data[] unmodified + */ + if (!syn_error) + return 0; + + memset(&lambda[1], 0, rs->nroots * sizeof(lambda[0])); + lambda[0] = 1; + + for (i = 0; i < rs->nroots + 1; i++) + b[i] = rs->index_of[lambda[i]]; + + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + r = 0; + el = 0; + while (++r <= rs->nroots) { /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++) { + if ((lambda[i] != 0) && (s[r - i - 1] != A0)) { + discr_r ^= rs->alpha_to[modnn(rs, rs->index_of[lambda[i]] + s[r - i - 1])]; + } + } + discr_r = rs->index_of[discr_r]; /* Index form */ + if (discr_r == A0) { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, rs->nroots * sizeof(b[0])); + b[0] = A0; + } else { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0; i < rs->nroots; i++) { + if (b[i] != A0) + t[i + 1] = lambda[i + 1] ^ rs->alpha_to[modnn(rs, discr_r + b[i])]; + else + t[i + 1] = lambda[i + 1]; + } + if (2 * el <= r - 1) { + el = r - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; i <= rs->nroots; i++) + b[i] = (lambda[i] == 0) ? A0 : modnn(rs, rs->index_of[lambda[i]] - discr_r + rs->nn); + } else { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, rs->nroots * sizeof(b[0])); + b[0] = A0; + } + memcpy(lambda, t, (rs->nroots + 1) * sizeof(t[0])); + } + } + + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for (i = 0; i < rs->nroots + 1; i++) { + lambda[i] = rs->index_of[lambda[i]]; + if (lambda[i] != A0) + deg_lambda = i; + } + /* Find roots of the error+erasure locator polynomial by Chien search */ + memcpy(®[1], &lambda[1], rs->nroots * sizeof(reg[0])); + count = 0; /* Number of roots of lambda(x) */ + for (i = 1, k = rs->iprim - 1; i <= rs->nn; i++, k = modnn(rs, k + rs->iprim)) { + q = 1; /* lambda[0] is always 0 */ + for (j = deg_lambda; j > 0; j--) { + if (reg[j] != A0) { + reg[j] = modnn(rs, reg[j] + j); + q ^= rs->alpha_to[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, abort the search to save time */ + if (++count == deg_lambda) + break; + } + + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + if (deg_lambda != count) + return -1; + + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**rs->nroots). in index form. Also find deg(omega). + */ + deg_omega = deg_lambda - 1; + for (i = 0; i <= deg_omega; i++) { + tmp = 0; + for (j = i; j >= 0; j--) { + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= rs->alpha_to[modnn(rs, s[i - j] + lambda[j])]; + } + omega[i] = rs->index_of[tmp]; + } + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(rs->fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count - 1; j >= 0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= rs->alpha_to[modnn(rs, omega[i] + i * root[j])]; + } + num2 = rs->alpha_to[modnn(rs, root[j] * (rs->fcr - 1) + rs->nn)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = RS_MIN(deg_lambda, rs->nroots - 1) & ~1; i >= 0; i -= 2) { + if (lambda[i + 1] != A0) + den ^= rs->alpha_to[modnn(rs, lambda[i + 1] + i * root[j])]; + } + + /* Apply error to data */ + if (num1 != 0 && loc[j] >= rs->pad) { + data[loc[j] - rs->pad] ^= rs->alpha_to[modnn(rs, rs->index_of[num1] + + rs->index_of[num2] + rs->nn - rs->index_of[den])]; + } + } + + return count; +} diff --git a/lib/verity/rs_encode_char.c b/lib/verity/rs_encode_char.c new file mode 100644 index 0000000..00ebb8b --- /dev/null +++ b/lib/verity/rs_encode_char.c @@ -0,0 +1,173 @@ +/* + * Reed-Solomon encoder, based on libfec + * + * Copyright (C) 2002, Phil Karn, KA9Q + * libcryptsetup modifications + * Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "rs.h" + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + * pad = padding bytes at front of shortened block + */ +struct rs *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + struct rs *rs; + int i, j, sr, root, iprim; + + /* Check parameter ranges */ + if (symsize < 0 || symsize > 8 * (int)sizeof(data_t)) + return NULL; + if (fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; + rs->nn = (1<pad = pad; + + rs->alpha_to = malloc(sizeof(data_t) * (rs->nn + 1)); + if (rs->alpha_to == NULL) { + free(rs); + return NULL; + } + rs->index_of = malloc(sizeof(data_t) * (rs->nn + 1)); + if (rs->index_of == NULL) { + free(rs->alpha_to); + free(rs); + return NULL; + } + memset(rs->index_of, 0, sizeof(data_t) * (rs->nn + 1)); + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for (i = 0; i < rs->nn; i++) { + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<nn; + } + if (sr != 1) { + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = malloc(sizeof(data_t) * (nroots + 1)); + if (rs->genpoly == NULL) { + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + + /* Find prim-th root of 1, used in decoding */ + for (iprim = 1; (iprim % prim) != 0; iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { + rs->genpoly[i + 1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j - 1] ^ rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j - 1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + + return rs; +} + +void free_rs_char(struct rs *rs) +{ + if (!rs) + return; + + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +void encode_rs_char(struct rs *rs, data_t *data, data_t *parity) +{ + int i, j; + data_t feedback; + + memset(parity, 0, rs->nroots * sizeof(data_t)); + + for (i = 0; i < rs->nn - rs->nroots - rs->pad; i++) { + feedback = rs->index_of[data[i] ^ parity[0]]; + if (feedback != A0) { + /* feedback term is non-zero */ +#ifdef UNNORMALIZED + /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + * always be for the polynomials constructed by init_rs() */ + feedback = modnn(rs, rs->nn - rs->genpoly[rs->nroots] + feedback); +#endif + for (j = 1; j < rs->nroots; j++) + parity[j] ^= rs->alpha_to[modnn(rs, feedback + rs->genpoly[rs->nroots - j])]; + } + + /* Shift */ + memmove(&parity[0], &parity[1], sizeof(data_t) * (rs->nroots - 1)); + + if (feedback != A0) + parity[rs->nroots - 1] = rs->alpha_to[modnn(rs, feedback + rs->genpoly[0])]; + else + parity[rs->nroots - 1] = 0; + } +} diff --git a/lib/verity/verity.c b/lib/verity/verity.c index 5108e9e..af31784 100644 --- a/lib/verity/verity.c +++ b/lib/verity/verity.c @@ -1,7 +1,7 @@ /* * dm-verity volume handling * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -58,52 +57,49 @@ int VERITY_read_sb(struct crypt_device *cd, struct crypt_params_verity *params) { struct device *device = crypt_metadata_device(cd); - int bsize = device_block_size(device); struct verity_sb sb = {}; ssize_t hdr_size = sizeof(struct verity_sb); - int devfd = 0, sb_version; + int devfd, sb_version; - log_dbg("Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".", + log_dbg(cd, "Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".", sizeof(struct verity_sb), device_path(device), sb_offset); if (params->flags & CRYPT_VERITY_NO_HEADER) { - log_err(cd, _("Verity device %s doesn't use on-disk header.\n"), + log_err(cd, _("Verity device %s does not use on-disk header."), device_path(device)); return -EINVAL; } - if (sb_offset % 512) { - log_err(cd, _("Unsupported VERITY hash offset.\n")); + if (MISALIGNED_512(sb_offset)) { + log_err(cd, _("Unsupported VERITY hash offset.")); return -EINVAL; } - devfd = device_open(device, O_RDONLY); - if(devfd == -1) { - log_err(cd, _("Cannot open device %s.\n"), device_path(device)); + devfd = device_open(cd, device, O_RDONLY); + if (devfd < 0) { + log_err(cd, _("Cannot open device %s."), device_path(device)); return -EINVAL; } - if(lseek(devfd, sb_offset, SEEK_SET) < 0 || - read_blockwise(devfd, bsize, &sb, hdr_size) < hdr_size) { - close(devfd); + if (read_lseek_blockwise(devfd, device_block_size(cd, device), + device_alignment(device), &sb, hdr_size, + sb_offset) < hdr_size) return -EIO; - } - close(devfd); if (memcmp(sb.signature, VERITY_SIGNATURE, sizeof(sb.signature))) { - log_err(cd, _("Device %s is not a valid VERITY device.\n"), + log_err(cd, _("Device %s is not a valid VERITY device."), device_path(device)); return -EINVAL; } sb_version = le32_to_cpu(sb.version); if (sb_version != 1) { - log_err(cd, _("Unsupported VERITY version %d.\n"), sb_version); + log_err(cd, _("Unsupported VERITY version %d."), sb_version); return -EINVAL; } params->hash_type = le32_to_cpu(sb.hash_type); if (params->hash_type > VERITY_MAX_HASH_TYPE) { - log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type); + log_err(cd, _("Unsupported VERITY hash type %d."), params->hash_type); return -EINVAL; } @@ -111,7 +107,7 @@ int VERITY_read_sb(struct crypt_device *cd, params->hash_block_size = le32_to_cpu(sb.hash_block_size); if (VERITY_BLOCK_SIZE_OK(params->data_block_size) || VERITY_BLOCK_SIZE_OK(params->hash_block_size)) { - log_err(cd, _("Unsupported VERITY block size.\n")); + log_err(cd, _("Unsupported VERITY block size.")); return -EINVAL; } params->data_size = le64_to_cpu(sb.data_blocks); @@ -120,21 +116,24 @@ int VERITY_read_sb(struct crypt_device *cd, if (!params->hash_name) return -ENOMEM; if (crypt_hash_size(params->hash_name) <= 0) { - log_err(cd, _("Hash algorithm %s not supported.\n"), + log_err(cd, _("Hash algorithm %s not supported."), params->hash_name); free(CONST_CAST(char*)params->hash_name); + params->hash_name = NULL; return -EINVAL; } params->salt_size = le16_to_cpu(sb.salt_size); if (params->salt_size > sizeof(sb.salt)) { - log_err(cd, _("VERITY header corrupted.\n")); + log_err(cd, _("VERITY header corrupted.")); free(CONST_CAST(char*)params->hash_name); + params->hash_name = NULL; return -EINVAL; } params->salt = malloc(params->salt_size); if (!params->salt) { free(CONST_CAST(char*)params->hash_name); + params->hash_name = NULL; return -ENOMEM; } memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size); @@ -153,30 +152,30 @@ int VERITY_write_sb(struct crypt_device *cd, struct crypt_params_verity *params) { struct device *device = crypt_metadata_device(cd); - int bsize = device_block_size(device); struct verity_sb sb = {}; ssize_t hdr_size = sizeof(struct verity_sb); + char *algorithm; uuid_t uuid; - int r, devfd = 0; + int r, devfd; - log_dbg("Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".", + log_dbg(cd, "Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".", sizeof(struct verity_sb), device_path(device), sb_offset); if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) { - log_err(cd, _("Wrong VERITY UUID format provided on device %s.\n"), + log_err(cd, _("Wrong VERITY UUID format provided on device %s."), device_path(device)); return -EINVAL; } if (params->flags & CRYPT_VERITY_NO_HEADER) { - log_err(cd, _("Verity device %s doesn't use on-disk header.\n"), + log_err(cd, _("Verity device %s does not use on-disk header."), device_path(device)); return -EINVAL; } - devfd = device_open(device, O_RDWR); - if(devfd == -1) { - log_err(cd, _("Cannot open device %s.\n"), device_path(device)); + devfd = device_open(cd, device, O_RDWR); + if (devfd < 0) { + log_err(cd, _("Cannot open device %s."), device_path(device)); return -EINVAL; } @@ -187,15 +186,19 @@ int VERITY_write_sb(struct crypt_device *cd, sb.hash_block_size = cpu_to_le32(params->hash_block_size); sb.salt_size = cpu_to_le16(params->salt_size); sb.data_blocks = cpu_to_le64(params->data_size); - strncpy((char *)sb.algorithm, params->hash_name, sizeof(sb.algorithm)); + algorithm = (char *)sb.algorithm; + algorithm[sizeof(sb.algorithm)-1] = '\0'; + strncpy(algorithm, params->hash_name, sizeof(sb.algorithm)-1); memcpy(sb.salt, params->salt, params->salt_size); memcpy(sb.uuid, uuid, sizeof(sb.uuid)); - r = write_lseek_blockwise(devfd, bsize, (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0; + r = write_lseek_blockwise(devfd, device_block_size(cd, device), device_alignment(device), + (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0; if (r) - log_err(cd, _("Error during update of verity header on device %s.\n"), + log_err(cd, _("Error during update of verity header on device %s."), device_path(device)); - close(devfd); + + device_sync(cd, device); return r; } @@ -218,7 +221,8 @@ int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string) { uuid_t uuid; - if (!(*uuid_string = malloc(40))) + *uuid_string = malloc(40); + if (!*uuid_string) return -ENOMEM; uuid_generate(uuid); uuid_unparse(uuid, *uuid_string); @@ -230,19 +234,42 @@ int VERITY_activate(struct crypt_device *cd, const char *name, const char *root_hash, size_t root_hash_size, + const char *signature_description, + struct device *fec_device, struct crypt_params_verity *verity_hdr, uint32_t activation_flags) { - struct crypt_dm_active_device dmd; + uint32_t dmv_flags; + unsigned int fec_errors = 0; int r; + struct crypt_dm_active_device dmd = { + .size = verity_hdr->data_size * verity_hdr->data_block_size / 512, + .flags = activation_flags, + .uuid = crypt_get_uuid(cd), + }; - log_dbg("Trying to activate VERITY device %s using hash %s.", + log_dbg(cd, "Trying to activate VERITY device %s using hash %s.", name ?: "[none]", verity_hdr->hash_name); if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) { - log_dbg("Verification of data in userspace required."); - r = VERITY_verify(cd, verity_hdr, - root_hash, root_hash_size); + if (signature_description) { + log_err(cd, _("Root hash signature verification is not supported.")); + return -EINVAL; + } + + log_dbg(cd, "Verification of data in userspace required."); + r = VERITY_verify(cd, verity_hdr, root_hash, root_hash_size); + + if (r == -EPERM && fec_device) { + log_dbg(cd, "Verification failed, trying to repair with FEC device."); + r = VERITY_FEC_process(cd, verity_hdr, fec_device, 1, &fec_errors); + if (r < 0) + log_err(cd, _("Errors cannot be repaired with FEC device.")); + else if (fec_errors) + log_err(cd, _("Found %u repairable errors with FEC device."), + fec_errors); + } + if (r < 0) return r; } @@ -250,40 +277,53 @@ int VERITY_activate(struct crypt_device *cd, if (!name) return 0; - dmd.target = DM_VERITY; - dmd.data_device = crypt_data_device(cd); - dmd.u.verity.hash_device = crypt_metadata_device(cd); - dmd.u.verity.root_hash = root_hash; - dmd.u.verity.root_hash_size = root_hash_size; - dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr), - dmd.flags = activation_flags; - dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512; - dmd.uuid = crypt_get_uuid(cd); - dmd.u.verity.vp = verity_hdr; - - r = device_block_adjust(cd, dmd.u.verity.hash_device, DEV_OK, + r = device_block_adjust(cd, crypt_metadata_device(cd), DEV_OK, 0, NULL, NULL); if (r) return r; - r = device_block_adjust(cd, dmd.data_device, DEV_EXCL, + r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL, 0, &dmd.size, &dmd.flags); if (r) return r; - r = dm_create_device(cd, name, CRYPT_VERITY, &dmd, 0); - if (r < 0 && !(dm_flags() & DM_VERITY_SUPPORTED)) { - log_err(cd, _("Kernel doesn't support dm-verity mapping.\n")); - return -ENOTSUP; + if (fec_device) { + r = device_block_adjust(cd, fec_device, DEV_OK, + 0, NULL, NULL); + if (r) + return r; } - if (r < 0) + + r = dm_verity_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), + crypt_metadata_device(cd), fec_device, root_hash, + root_hash_size, signature_description, + VERITY_hash_offset_block(verity_hdr), + VERITY_hash_blocks(cd, verity_hdr), verity_hdr); + + if (r) return r; + r = dm_create_device(cd, name, CRYPT_VERITY, &dmd); + if (r < 0 && (dm_flags(cd, DM_VERITY, &dmv_flags) || !(dmv_flags & DM_VERITY_SUPPORTED))) { + log_err(cd, _("Kernel does not support dm-verity mapping.")); + r = -ENOTSUP; + } + if (r < 0 && signature_description && !(dmv_flags & DM_VERITY_SIGNATURE_SUPPORTED)) { + log_err(cd, _("Kernel does not support dm-verity signature option.")); + r = -ENOTSUP; + } + if (r < 0) + goto out; + r = dm_status_verity_ok(cd, name); if (r < 0) - return r; + goto out; if (!r) - log_err(cd, _("Verity device detected corruption after activation.\n")); - return 0; + log_err(cd, _("Verity device detected corruption after activation.")); + + r = 0; +out: + dm_targets_free(cd, &dmd); + return r; } diff --git a/lib/verity/verity.h b/lib/verity/verity.h index 4f457cb..0b7f0cc 100644 --- a/lib/verity/verity.h +++ b/lib/verity/verity.h @@ -1,7 +1,7 @@ /* * dm-verity volume handling * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,8 @@ #ifndef _VERITY_H #define _VERITY_H -#include +#include +#include #define VERITY_MAX_HASH_TYPE 1 #define VERITY_BLOCK_SIZE_OK(x) ((x) % 512 || (x) < 512 || \ @@ -29,6 +30,7 @@ struct crypt_device; struct crypt_params_verity; +struct device; int VERITY_read_sb(struct crypt_device *cd, uint64_t sb_offset, @@ -44,6 +46,8 @@ int VERITY_activate(struct crypt_device *cd, const char *name, const char *root_hash, size_t root_hash_size, + const char *signature_description, + struct device *fec_device, struct crypt_params_verity *verity_hdr, uint32_t activation_flags); @@ -54,11 +58,19 @@ int VERITY_verify(struct crypt_device *cd, int VERITY_create(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, - char *root_hash, + const char *root_hash, size_t root_hash_size); +int VERITY_FEC_process(struct crypt_device *cd, + struct crypt_params_verity *params, + struct device *fec_device, + int check_fec, + unsigned int *errors); + uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params); +uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params); + int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string); #endif diff --git a/lib/verity/verity_fec.c b/lib/verity/verity_fec.c new file mode 100644 index 0000000..a8a5e86 --- /dev/null +++ b/lib/verity/verity_fec.c @@ -0,0 +1,281 @@ +/* + * dm-verity Forward Error Correction (FEC) support + * + * Copyright (C) 2015 Google, Inc. All rights reserved. + * Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "verity.h" +#include "internal.h" +#include "rs.h" + +/* ecc parameters */ +#define FEC_RSM 255 +#define FEC_MIN_RSN 231 +#define FEC_MAX_RSN 253 + +#define FEC_INPUT_DEVICES 2 + +/* parameters to init_rs_char */ +#define FEC_PARAMS(roots) \ + 8, /* symbol size in bits */ \ + 0x11d, /* field generator polynomial coefficients */ \ + 0, /* first root of the generator */ \ + 1, /* primitive element to generate polynomial roots */ \ + (roots), /* polynomial degree (number of roots) */ \ + 0 /* padding bytes at the front of shortened block */ + +struct fec_input_device { + struct device *device; + int fd; + uint64_t start; + uint64_t count; +}; + +struct fec_context { + uint32_t rsn; + uint32_t roots; + uint64_t size; + uint64_t blocks; + uint64_t rounds; + uint32_t block_size; + struct fec_input_device *inputs; + size_t ninputs; +}; + +/* computes ceil(x / y) */ +static inline uint64_t FEC_div_round_up(uint64_t x, uint64_t y) +{ + return (x / y) + (x % y > 0 ? 1 : 0); +} + +/* returns a physical offset for the given RS offset */ +static inline uint64_t FEC_interleave(struct fec_context *ctx, uint64_t offset) +{ + return (offset / ctx->rsn) + + (offset % ctx->rsn) * ctx->rounds * ctx->block_size; +} + +/* returns data for a byte at the specified RS offset */ +static int FEC_read_interleaved(struct fec_context *ctx, uint64_t i, + void *output, size_t count) +{ + size_t n; + uint64_t offset = FEC_interleave(ctx, i); + + /* offsets outside input area are assumed to contain zeros */ + if (offset >= ctx->size) { + memset(output, 0, count); + return 0; + } + + /* find the correct input device and read from it */ + for (n = 0; n < ctx->ninputs; ++n) { + if (offset >= ctx->inputs[n].count) { + offset -= ctx->inputs[n].count; + continue; + } + + /* FIXME: read_lseek_blockwise candidate */ + if (lseek(ctx->inputs[n].fd, ctx->inputs[n].start + offset, SEEK_SET) < 0) + return -1; + return (read_buffer(ctx->inputs[n].fd, output, count) == (ssize_t)count) ? 0 : -1; + } + + /* should never be reached */ + return -1; +} + +/* encodes/decode inputs to/from fd */ +static int FEC_process_inputs(struct crypt_device *cd, + struct crypt_params_verity *params, + struct fec_input_device *inputs, + size_t ninputs, int fd, + int decode, unsigned int *errors) +{ + int r = 0; + unsigned int i; + struct fec_context ctx; + uint32_t b; + uint64_t n; + uint8_t rs_block[FEC_RSM]; + uint8_t *buf = NULL; + void *rs; + + /* initialize parameters */ + ctx.roots = params->fec_roots; + ctx.rsn = FEC_RSM - ctx.roots; + ctx.block_size = params->data_block_size; + ctx.inputs = inputs; + ctx.ninputs = ninputs; + + rs = init_rs_char(FEC_PARAMS(ctx.roots)); + if (!rs) { + log_err(cd, _("Failed to allocate RS context.")); + return -ENOMEM; + } + + /* calculate the total area covered by error correction codes */ + ctx.size = 0; + for (n = 0; n < ctx.ninputs; ++n) + ctx.size += ctx.inputs[n].count; + + /* each byte in a data block is covered by a different code */ + ctx.blocks = FEC_div_round_up(ctx.size, ctx.block_size); + ctx.rounds = FEC_div_round_up(ctx.blocks, ctx.rsn); + + buf = malloc((size_t)ctx.block_size * ctx.rsn); + if (!buf) { + log_err(cd, _("Failed to allocate buffer.")); + r = -ENOMEM; + goto out; + } + + /* encode/decode input */ + for (n = 0; n < ctx.rounds; ++n) { + for (i = 0; i < ctx.rsn; ++i) { + if (FEC_read_interleaved(&ctx, n * ctx.rsn * ctx.block_size + i, + &buf[i * ctx.block_size], ctx.block_size)) { + log_err(cd, _("Failed to read RS block %" PRIu64 " byte %d."), n, i); + r = -EIO; + goto out; + } + } + + for (b = 0; b < ctx.block_size; ++b) { + for (i = 0; i < ctx.rsn; ++i) + rs_block[i] = buf[i * ctx.block_size + b]; + + /* decoding from parity device */ + if (decode) { + if (read_buffer(fd, &rs_block[ctx.rsn], ctx.roots) < 0) { + log_err(cd, _("Failed to read parity for RS block %" PRIu64 "."), n); + r = -EIO; + goto out; + } + + /* coverity[tainted_data] */ + r = decode_rs_char(rs, rs_block); + if (r < 0) { + log_err(cd, _("Failed to repair parity for block %" PRIu64 "."), n); + goto out; + } + /* return number of detected errors */ + if (errors) + *errors += r; + r = 0; + } else { + /* encoding and writing parity data to fec device */ + encode_rs_char(rs, rs_block, &rs_block[ctx.rsn]); + if (write_buffer(fd, &rs_block[ctx.rsn], ctx.roots) < 0) { + log_err(cd, _("Failed to write parity for RS block %" PRIu64 "."), n); + r = -EIO; + goto out; + } + } + } + } +out: + free_rs_char(rs); + free(buf); + return r; +} + +int VERITY_FEC_process(struct crypt_device *cd, + struct crypt_params_verity *params, + struct device *fec_device, int check_fec, + unsigned int *errors) +{ + int r; + int fd = -1; + struct fec_input_device inputs[FEC_INPUT_DEVICES] = { + { + .device = crypt_data_device(cd), + .fd = -1, + .start = 0, + .count = params->data_size * params->data_block_size + },{ + .device = crypt_metadata_device(cd), + .fd = -1, + .start = VERITY_hash_offset_block(params) * params->data_block_size + } + }; + + /* validate parameters */ + if (params->data_block_size != params->hash_block_size) { + log_err(cd, _("Block sizes must match for FEC.")); + return -EINVAL; + } + + if (params->fec_roots > FEC_RSM - FEC_MIN_RSN || + params->fec_roots < FEC_RSM - FEC_MAX_RSN) { + log_err(cd, _("Invalid number of parity bytes.")); + return -EINVAL; + } + + r = -EIO; + + if (check_fec) + fd = open(device_path(fec_device), O_RDONLY); + else + fd = open(device_path(fec_device), O_RDWR); + + if (fd == -1) { + log_err(cd, _("Cannot open device %s."), device_path(fec_device)); + goto out; + } + + if (lseek(fd, params->fec_area_offset, SEEK_SET) < 0) { + log_dbg(cd, "Cannot seek to requested position in FEC device."); + goto out; + } + + /* input devices */ + inputs[0].fd = open(device_path(inputs[0].device), O_RDONLY); + if (inputs[0].fd == -1) { + log_err(cd, _("Cannot open device %s."), device_path(inputs[0].device)); + goto out; + } + inputs[1].fd = open(device_path(inputs[1].device), O_RDONLY); + if (inputs[1].fd == -1) { + log_err(cd, _("Cannot open device %s."), device_path(inputs[1].device)); + goto out; + } + + /* cover the entire hash device starting from hash_offset */ + r = device_size(inputs[1].device, &inputs[1].count); + if (r) { + log_err(cd, _("Failed to determine size for device %s."), + device_path(inputs[1].device)); + goto out; + } + inputs[1].count -= inputs[1].start; + + r = FEC_process_inputs(cd, params, inputs, FEC_INPUT_DEVICES, fd, check_fec, errors); +out: + if (inputs[0].fd != -1) + close(inputs[0].fd); + if (inputs[1].fd != -1) + close(inputs[1].fd); + if (fd != -1) + close(fd); + + return r; +} diff --git a/lib/verity/verity_hash.c b/lib/verity/verity_hash.c index 3f25e91..6142430 100644 --- a/lib/verity/verity_hash.c +++ b/lib/verity/verity_hash.c @@ -1,7 +1,7 @@ /* * dm-verity volume handling * - * Copyright (C) 2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,12 +51,12 @@ static int verify_zero(struct crypt_device *cd, FILE *wr, size_t bytes) size_t i; if (fread(block, bytes, 1, wr) != 1) { - log_dbg("EIO while reading spare area."); + log_dbg(cd, "EIO while reading spare area."); return -EIO; } for (i = 0; i < bytes; i++) if (block[i]) { - log_err(cd, _("Spare area is not zeroed at position %" PRIu64 ".\n"), + log_err(cd, _("Spare area is not zeroed at position %" PRIu64 "."), ftello(wr) - bytes); return -EPERM; } @@ -97,6 +97,48 @@ static int mult_overflow(off_t *u, off_t b, size_t size) return 0; } +static int hash_levels(size_t hash_block_size, size_t digest_size, + off_t data_file_blocks, off_t *hash_position, int *levels, + off_t *hash_level_block, off_t *hash_level_size) +{ + size_t hash_per_block_bits; + off_t s, s_shift; + int i; + + if (!digest_size) + return -EINVAL; + + hash_per_block_bits = get_bits_down(hash_block_size / digest_size); + if (!hash_per_block_bits) + return -EINVAL; + + *levels = 0; + while (hash_per_block_bits * *levels < 64 && + (data_file_blocks - 1) >> (hash_per_block_bits * *levels)) + (*levels)++; + + if (*levels > VERITY_MAX_LEVELS) + return -EINVAL; + + for (i = *levels - 1; i >= 0; i--) { + if (hash_level_block) + hash_level_block[i] = *hash_position; + // verity position of block data_file_blocks at level i + s_shift = (i + 1) * hash_per_block_bits; + if (s_shift > 63) + return -EINVAL; + s = (data_file_blocks + ((off_t)1 << s_shift) - 1) >> ((i + 1) * hash_per_block_bits); + if (hash_level_size) + hash_level_size[i] = s; + if ((*hash_position + s) < *hash_position || + (*hash_position + s) < 0) + return -EINVAL; + *hash_position += s; + } + + return 0; +} + static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, off_t data_block, size_t data_block_size, off_t hash_block, size_t hash_block_size, @@ -118,17 +160,17 @@ static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, if (mult_overflow(&seek_rd, data_block, data_block_size) || mult_overflow(&seek_wr, hash_block, hash_block_size)) { - log_err(cd, _("Device offset overflow.\n")); + log_err(cd, _("Device offset overflow.")); return -EINVAL; } if (fseeko(rd, seek_rd, SEEK_SET)) { - log_dbg("Cannot seek to requested position in data device."); + log_dbg(cd, "Cannot seek to requested position in data device."); return -EIO; } if (wr && fseeko(wr, seek_wr, SEEK_SET)) { - log_dbg("Cannot seek to requested position in hash device."); + log_dbg(cd, "Cannot seek to requested position in hash device."); return -EIO; } @@ -140,7 +182,7 @@ static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, break; blocks--; if (fread(data_buffer, data_block_size, 1, rd) != 1) { - log_dbg("Cannot read data device block."); + log_dbg(cd, "Cannot read data device block."); return -EIO; } @@ -154,17 +196,17 @@ static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, break; if (verify) { if (fread(read_digest, digest_size, 1, wr) != 1) { - log_dbg("Cannot read digest form hash device."); + log_dbg(cd, "Cannot read digest form hash device."); return -EIO; } if (memcmp(read_digest, calculated_digest, digest_size)) { - log_err(cd, _("Verification failed at position %" PRIu64 ".\n"), + log_err(cd, _("Verification failed at position %" PRIu64 "."), ftello(rd) - data_block_size); return -EPERM; } } else { if (fwrite(calculated_digest, digest_size, 1, wr) != 1) { - log_dbg("Cannot write digest to hash device."); + log_dbg(cd, "Cannot write digest to hash device."); return -EIO; } } @@ -177,7 +219,7 @@ static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, if (r) return r; } else if (fwrite(left_block, digest_size_full - digest_size, 1, wr) != 1) { - log_dbg("Cannot write spare area to hash device."); + log_dbg(cd, "Cannot write spare area to hash device."); return -EIO; } } @@ -190,7 +232,7 @@ static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr, if (r) return r; } else if (fwrite(left_block, left_bytes, 1, wr) != 1) { - log_dbg("Cannot write remaining spare area to hash device."); + log_dbg(cd, "Cannot write remaining spare area to hash device."); return -EIO; } } @@ -219,20 +261,19 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd, FILE *hash_file = NULL, *hash_file_2; off_t hash_level_block[VERITY_MAX_LEVELS]; off_t hash_level_size[VERITY_MAX_LEVELS]; - off_t data_file_blocks, s; - size_t hash_per_block_bits; + off_t data_file_blocks; off_t data_device_size = 0, hash_device_size = 0; uint64_t dev_size; int levels, i, r; - log_dbg("Hash %s %s, data device %s, data blocks %" PRIu64 + log_dbg(cd, "Hash %s %s, data device %s, data blocks %" PRIu64 ", hash_device %s, offset %" PRIu64 ".", verify ? "verification" : "creation", hash_name, device_path(data_device), data_blocks, device_path(hash_device), hash_position); if (data_blocks < 0 || hash_position < 0) { - log_err(cd, _("Invalid size parameters for verity device.\n")); + log_err(cd, _("Invalid size parameters for verity device.")); return -EINVAL; } @@ -246,61 +287,39 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd, data_file_blocks = data_blocks; if (mult_overflow(&data_device_size, data_blocks, data_block_size)) { - log_err(cd, _("Device offset overflow.\n")); + log_err(cd, _("Device offset overflow.")); return -EINVAL; } - hash_per_block_bits = get_bits_down(hash_block_size / digest_size); - if (!hash_per_block_bits) + if (hash_levels(hash_block_size, digest_size, data_file_blocks, &hash_position, + &levels, &hash_level_block[0], &hash_level_size[0])) { + log_err(cd, _("Hash area overflow.")); return -EINVAL; - - levels = 0; - if (data_file_blocks) { - while (hash_per_block_bits * levels < 64 && - (data_file_blocks - 1) >> (hash_per_block_bits * levels)) - levels++; } - log_dbg("Using %d hash levels.", levels); - if (levels > VERITY_MAX_LEVELS) { - log_err(cd, _("Too many tree levels for verity volume.\n")); - return -EINVAL; - } - - for (i = levels - 1; i >= 0; i--) { - hash_level_block[i] = hash_position; - // verity position of block data_file_blocks at level i - s = (data_file_blocks + ((off_t)1 << ((i + 1) * hash_per_block_bits)) - 1) >> ((i + 1) * hash_per_block_bits); - hash_level_size[i] = s; - if ((hash_position + s) < hash_position || - (hash_position + s) < 0) { - log_err(cd, _("Device offset overflow.\n")); - return -EINVAL; - } - hash_position += s; - } + log_dbg(cd, "Using %d hash levels.", levels); if (mult_overflow(&hash_device_size, hash_position, hash_block_size)) { - log_err(cd, _("Device offset overflow.\n")); + log_err(cd, _("Device offset overflow.")); return -EINVAL; } - log_dbg("Data device size required: %" PRIu64 " bytes.", + log_dbg(cd, "Data device size required: %" PRIu64 " bytes.", data_device_size); data_file = fopen(device_path(data_device), "r"); if (!data_file) { - log_err(cd, _("Cannot open device %s.\n"), + log_err(cd, _("Cannot open device %s."), device_path(data_device) ); r = -EIO; goto out; } - log_dbg("Hash device size required: %" PRIu64 " bytes.", + log_dbg(cd, "Hash device size required: %" PRIu64 " bytes.", hash_device_size); hash_file = fopen(device_path(hash_device), verify ? "r" : "r+"); if (!hash_file) { - log_err(cd, _("Cannot open device %s.\n"), + log_err(cd, _("Cannot open device %s."), device_path(hash_device)); r = -EIO; goto out; @@ -320,7 +339,7 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd, } else { hash_file_2 = fopen(device_path(hash_device), "r"); if (!hash_file_2) { - log_err(cd, _("Cannot open device %s.\n"), + log_err(cd, _("Cannot open device %s."), device_path(hash_device)); r = -EIO; goto out; @@ -351,20 +370,20 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd, out: if (verify) { if (r) - log_err(cd, _("Verification of data area failed.\n")); + log_err(cd, _("Verification of data area failed.")); else { - log_dbg("Verification of data area succeeded."); + log_dbg(cd, "Verification of data area succeeded."); r = memcmp(root_hash, calculated_digest, digest_size) ? -EPERM : 0; if (r) - log_err(cd, _("Verification of root hash failed.\n")); + log_err(cd, _("Verification of root hash failed.")); else - log_dbg("Verification of root hash succeeded."); + log_dbg(cd, "Verification of root hash succeeded."); } } else { if (r == -EIO) - log_err(cd, _("Input/output error while creating hash area.\n")); + log_err(cd, _("Input/output error while creating hash area.")); else if (r) - log_err(cd, _("Creation of hash area failed.\n")); + log_err(cd, _("Creation of hash area failed.")); else { fsync(fileno(hash_file)); memcpy(root_hash, calculated_digest, digest_size); @@ -402,17 +421,17 @@ int VERITY_verify(struct crypt_device *cd, /* Create verity hash */ int VERITY_create(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, - char *root_hash, + const char *root_hash, size_t root_hash_size) { - unsigned pgsize = crypt_getpagesize(); + unsigned pgsize = (unsigned)crypt_getpagesize(); if (verity_hdr->salt_size > 256) return -EINVAL; if (verity_hdr->data_block_size > pgsize) log_err(cd, _("WARNING: Kernel cannot activate device if data " - "block size exceeds page size (%u).\n"), pgsize); + "block size exceeds page size (%u)."), pgsize); return VERITY_create_or_verify_hash(cd, 0, verity_hdr->hash_type, @@ -423,8 +442,20 @@ int VERITY_create(struct crypt_device *cd, verity_hdr->data_block_size, verity_hdr->data_size, VERITY_hash_offset_block(verity_hdr), - root_hash, + CONST_CAST(char*)root_hash, root_hash_size, verity_hdr->salt, verity_hdr->salt_size); } + +uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params) +{ + off_t hash_position = 0; + int levels = 0; + + if (hash_levels(params->hash_block_size, crypt_get_volume_key_size(cd), + params->data_size, &hash_position, &levels, NULL, NULL)) + return 0; + + return (uint64_t)hash_position; +} diff --git a/lib/volumekey.c b/lib/volumekey.c index e7150aa..4507451 100644 --- a/lib/volumekey.c +++ b/lib/volumekey.c @@ -1,8 +1,8 @@ /* * cryptsetup volume key implementation * - * Copyright (C) 2004-2006, Clemens Fruhwirth - * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2006 Clemens Fruhwirth + * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,36 +20,116 @@ */ #include +#include #include +#include #include "internal.h" -struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key) +struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key) { - struct volume_key *vk = malloc(sizeof(*vk) + keylength); + struct volume_key *vk; + + if (keylength > (SIZE_MAX - sizeof(*vk))) + return NULL; + vk = malloc(sizeof(*vk) + keylength); if (!vk) return NULL; + vk->key_description = NULL; vk->keylength = keylength; - if (key) - memcpy(&vk->key, key, keylength); - else - crypt_memzero(&vk->key, keylength); + vk->id = -1; + vk->next = NULL; + + /* keylength 0 is valid => no key */ + if (vk->keylength) { + if (key) + memcpy(&vk->key, key, keylength); + else + crypt_safe_memzero(&vk->key, keylength); + } + + return vk; +} + +int crypt_volume_key_set_description(struct volume_key *vk, const char *key_description) +{ + if (!vk) + return -EINVAL; + + free(CONST_CAST(void*)vk->key_description); + vk->key_description = NULL; + if (key_description && !(vk->key_description = strdup(key_description))) + return -ENOMEM; + + return 0; +} + +void crypt_volume_key_set_id(struct volume_key *vk, int id) +{ + if (vk && id >= 0) + vk->id = id; +} + +int crypt_volume_key_get_id(const struct volume_key *vk) +{ + return vk ? vk->id : -1; +} + +struct volume_key *crypt_volume_key_by_id(struct volume_key *vks, int id) +{ + struct volume_key *vk = vks; + + if (id < 0) + return NULL; + + while (vk && vk->id != id) + vk = vk->next; return vk; } +void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk) +{ + struct volume_key *tmp; + + if (!vks) + return; + + if (!*vks) { + *vks = vk; + return; + } + + tmp = *vks; + + while (tmp->next) + tmp = tmp->next; + + tmp->next = vk; +} + +struct volume_key *crypt_volume_key_next(struct volume_key *vk) +{ + return vk ? vk->next : NULL; +} + void crypt_free_volume_key(struct volume_key *vk) { - if (vk) { - crypt_memzero(vk->key, vk->keylength); + struct volume_key *vk_next; + + while (vk) { + crypt_safe_memzero(vk->key, vk->keylength); vk->keylength = 0; + free(CONST_CAST(void*)vk->key_description); + vk_next = vk->next; free(vk); + vk = vk_next; } } -struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, unsigned keylength) +struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength) { int r; struct volume_key *vk; diff --git a/ltmain.sh b/ltmain.sh index bffda54..0cb7f90 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -1,9 +1,12 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 -# libtool (GNU libtool) 2.4.2 +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -23,881 +26,2185 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.2 Debian-2.4.2-1.11" -TIMESTAMP="" -package_revision=1.3337 +VERSION="2.4.6 Debian-2.4.6-14" +package_revision=2.4.6 -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL -$lt_unset CDPATH +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. : ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -exit_status=$EXIT_SUCCESS - -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" -dirname="s,/[^/]*$,," -basename="s,^.*/,," -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation +## ----------------- ## +## Global variables. ## +## ----------------- ## -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () -{ - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` -# Make sure we have an absolute path for reexecution: +# Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) - progdir=$func_dirname_result + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" + progpath=$progdir/$progname ;; *) - save_IFS="$IFS" + _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do - IFS="$save_IFS" + IFS=$_G_IFS test -x "$progdir/$progname" && break done - IFS="$save_IFS" + IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" + progpath=$progdir/$progname ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' +## ----------------- ## +## Standard options. ## +## ----------------- ## -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. -# Standard options: opt_dry_run=false -opt_help=false opt_quiet=false opt_verbose=false -opt_warning=: -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} +## -------------------- ## +## Resource management. ## +## -------------------- ## -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. - # bash bug again: - : -} -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () { - func_error ${1+"$@"} - exit $EXIT_FAILURE -} + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" + require_term_colors=: } -help="Try \`$progname --help' for more information." ## default -# func_grep expression filename +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { + $debug_cmd + $GREP "$1" "$2" >/dev/null 2>&1 } -# func_mkdir_p directory-path +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { - my_directory_path="$1" - my_dir_list= + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do + while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" + _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac + case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : + $MKDIR "$_G_dir" 2>/dev/null || : done - IFS="$save_mkdir_p_IFS" + IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" fi } -# func_mktempdir [string] +# func_mktempdir [BASENAME] +# ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. +# given, BASENAME is the basename for that directory. func_mktempdir () { - my_template="${TMPDIR-/tmp}/${1-$progname}" + $debug_cmd - if test "$opt_dry_run" = ":"; then + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" + _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - if test ! -d "$my_tmpdir"; then + if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" + _G_tmpdir=$_G_template-${RANDOM-0}$$ - save_mktempdir_umask=`umask` + func_mktempdir_umask=`umask` umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi - $ECHO "$my_tmpdir" + $ECHO "$_G_tmpdir" } -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () { - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac + $debug_cmd - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. ;; *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done } -# func_quote_for_expand arg +# func_quote_for_expand ARG +# ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { + $debug_cmd + case $1 in *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) - my_arg="$1" ;; + _G_arg=$1 ;; esac - case $my_arg in + case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" + _G_arg=\"$_G_arg\" ;; esac - func_quote_for_expand_result="$my_arg" + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-07.11; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote_for_eval ${1+"$@"} +# # my_options_prep_result=$func_quote_for_eval_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit } -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } + _G_rc_options=false - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote_for_eval ${1+"$@"} + func_options_result=$func_quote_for_eval_result fi + + $_G_rc_options } -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } + # Option defaults: + opt_verbose=false + opt_warning_types= - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result fi + + $_G_rc_options_prep } -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () { - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_parse_options } -# func_version -# Echo version message to standard output and exit. -func_version () +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () { - $opt_debug + $debug_cmd - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options } -# func_usage -# Echo short help message to standard output and exit. -func_usage () + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () { - $opt_debug + $debug_cmd - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE } -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. + +# func_help +# --------- +# Echo long help message to standard output and exit. func_help () { - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 } -# func_missing_arg argname + +# func_missing_arg ARGNAME +# ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { - $opt_debug + $debug_cmd - func_error "missing argument for $1." + func_error "Missing argument for '$1'." exit_cmd=exit } -# func_split_short_opt shortopt +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () { - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + $debug_cmd - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () { - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' + $debug_cmd - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} -exit_cmd=: +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + exit $? +} -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () { - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation + $debug_cmd -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () -{ - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} -# func_arith arithmetic-term... -func_arith () +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () { - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation + $debug_cmd + $warning_func ${1+"$@"} +} -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" -# func_lo2o object -func_lo2o () +# Additional text appended to 'usage_message' in response to '--help'. +func_help () { - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-14 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi -# func_fatal_configuration arg... +# func_fatal_configuration ARG... +# ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." } # func_config +# ----------- # Display the configuration for all the tags in this script. func_config () { @@ -915,17 +2222,19 @@ func_config () exit $? } + # func_features +# ------------- # Display the features supported by this script. func_features () { echo "host: $host" - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" @@ -934,314 +2243,369 @@ func_features () exit $? } -# func_enable_tag tagname + +# func_enable_tag TAGNAME +# ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { - # Global variable: - tagname="$1" + # Global variable: + tagname=$1 - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac } + # func_check_version_match +# ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - else - cat >&2 <<_LT_EOF + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - fi - else - cat >&2 <<_LT_EOF + fi + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF - fi + fi - exit $EXIT_MISMATCH - fi + exit $EXIT_MISMATCH + fi } -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false + nonopt= + preserve_args= + _G_rc_lt_options_prep=: -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; esac - done - # Validate options: + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result + fi - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd - $opt_help || { - # Sanity checks first: - func_check_version_match + _G_rc_lt_parse_options=false - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result fi - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift fi - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + $opt_help || { + # Sanity checks first: + func_check_version_match - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result } +func_add_hook func_validate_options libtool_validate_options +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + ## ----------- ## ## Main. ## ## ----------- ## +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + # func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. +# fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no @@ -1249,13 +2613,13 @@ func_lalib_unsafe_p () for lalib_p_l in 1 2 3 4 do read lalib_p_line - case "$lalib_p_line" in + case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi - test "$lalib_p" = yes + test yes = "$lalib_p" } # func_ltwrapper_script_p file @@ -1264,7 +2628,8 @@ func_lalib_unsafe_p () # determined imposters. func_ltwrapper_script_p () { - func_lalib_p "$1" + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file @@ -1289,7 +2654,7 @@ func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file @@ -1308,11 +2673,13 @@ func_ltwrapper_p () # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { - $opt_debug + $debug_cmd + save_ifs=$IFS; IFS='~' for cmd in $1; do - IFS=$save_ifs + IFS=$sp$nl eval cmd=\"$cmd\" + IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs @@ -1324,10 +2691,11 @@ func_execute_cmds () # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. +# 'FILE.' does not work on cygwin managed mounts. func_source () { - $opt_debug + $debug_cmd + case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; @@ -1354,10 +2722,10 @@ func_resolve_sysroot () # store the result into func_replace_sysroot_result. func_replace_sysroot () { - case "$lt_sysroot:$1" in + case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" + func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. @@ -1374,7 +2742,8 @@ func_replace_sysroot () # arg is usually of the form 'gcc ...' func_infer_tag () { - $opt_debug + $debug_cmd + if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do @@ -1393,7 +2762,7 @@ func_infer_tag () for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. @@ -1418,7 +2787,7 @@ func_infer_tag () # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" + func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi @@ -1434,15 +2803,15 @@ func_infer_tag () # but don't create it if we're doing a dry run. func_write_libtool_object () { - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' else write_lobj=none fi - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' else write_oldobj=none fi @@ -1450,7 +2819,7 @@ func_write_libtool_object () $opt_dry_run || { cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` + $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi @@ -1514,18 +2884,19 @@ func_convert_core_file_wine_to_w32 () # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { - $opt_debug + $debug_cmd + # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" + func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi @@ -1554,7 +2925,8 @@ func_convert_core_path_wine_to_w32 () # environment variable; do not put it in $PATH. func_cygpath () { - $opt_debug + $debug_cmd + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then @@ -1563,7 +2935,7 @@ func_cygpath () fi else func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath @@ -1574,10 +2946,11 @@ func_cygpath () # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { - $opt_debug + $debug_cmd + # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 @@ -1588,13 +2961,14 @@ func_convert_core_msys_to_w32 () # func_to_host_file_result to ARG1). func_convert_file_check () { - $opt_debug - if test -z "$2" && test -n "$1" ; then + $debug_cmd + + if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" - func_error " \`$1'" + func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: - func_to_host_file_result="$1" + func_to_host_file_result=$1 fi } # end func_convert_file_check @@ -1606,10 +2980,11 @@ func_convert_file_check () # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { - $opt_debug + $debug_cmd + if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" - func_error " \`$3'" + func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. @@ -1618,7 +2993,7 @@ func_convert_path_check () func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else - func_to_host_path_result="$3" + func_to_host_path_result=$3 fi fi } @@ -1630,9 +3005,10 @@ func_convert_path_check () # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { - $opt_debug + $debug_cmd + case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" + $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in @@ -1646,7 +3022,7 @@ func_convert_path_front_back_pathsep () ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## -# invoked via `$to_host_file_cmd ARG' +# invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. @@ -1657,7 +3033,8 @@ func_convert_path_front_back_pathsep () # in func_to_host_file_result. func_to_host_file () { - $opt_debug + $debug_cmd + $to_host_file_cmd "$1" } # end func_to_host_file @@ -1669,7 +3046,8 @@ func_to_host_file () # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { - $opt_debug + $debug_cmd + case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 @@ -1687,7 +3065,7 @@ func_to_tool_file () # Copy ARG to func_to_host_file_result. func_convert_file_noop () { - func_to_host_file_result="$1" + func_to_host_file_result=$1 } # end func_convert_file_noop @@ -1698,11 +3076,12 @@ func_convert_file_noop () # func_to_host_file_result. func_convert_file_msys_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1714,8 +3093,9 @@ func_convert_file_msys_to_w32 () # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. @@ -1731,11 +3111,12 @@ func_convert_file_cygwin_to_w32 () # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1747,12 +3128,13 @@ func_convert_file_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1765,13 +3147,14 @@ func_convert_file_msys_to_cygwin () # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1781,7 +3164,7 @@ func_convert_file_nix_to_cygwin () ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# -# invoked via `$to_host_path_cmd ARG' +# invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. @@ -1805,10 +3188,11 @@ func_convert_file_nix_to_cygwin () to_host_path_cmd= func_init_to_host_path_cmd () { - $opt_debug + $debug_cmd + if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" + to_host_path_cmd=func_convert_path_$func_stripname_result fi } @@ -1818,7 +3202,8 @@ func_init_to_host_path_cmd () # in func_to_host_path_result. func_to_host_path () { - $opt_debug + $debug_cmd + func_init_to_host_path_cmd $to_host_path_cmd "$1" } @@ -1829,7 +3214,7 @@ func_to_host_path () # Copy ARG to func_to_host_path_result. func_convert_path_noop () { - func_to_host_path_result="$1" + func_to_host_path_result=$1 } # end func_convert_path_noop @@ -1840,8 +3225,9 @@ func_convert_path_noop () # func_to_host_path_result. func_convert_path_msys_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; @@ -1849,7 +3235,7 @@ func_convert_path_msys_to_w32 () func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1863,8 +3249,9 @@ func_convert_path_msys_to_w32 () # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" @@ -1883,14 +3270,15 @@ func_convert_path_cygwin_to_w32 () # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1904,15 +3292,16 @@ func_convert_path_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1927,8 +3316,9 @@ func_convert_path_msys_to_cygwin () # func_to_host_file_result. func_convert_path_nix_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them @@ -1937,7 +3327,7 @@ func_convert_path_nix_to_cygwin () func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1946,13 +3336,31 @@ func_convert_path_nix_to_cygwin () # end func_convert_path_nix_to_cygwin +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + # func_mode_compile arg... func_mode_compile () { - $opt_debug + $debug_cmd + # Get the compilation command and the source file. base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" + srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal @@ -1965,12 +3373,12 @@ func_mode_compile () case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile - lastarg="$arg" + lastarg=$arg arg_mode=normal ;; target ) - libobj="$arg" + libobj=$arg arg_mode=normal continue ;; @@ -1980,7 +3388,7 @@ func_mode_compile () case $arg in -o) test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" + func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; @@ -2009,12 +3417,12 @@ func_mode_compile () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for arg in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_append_quoted lastarg "$arg" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result @@ -2027,8 +3435,8 @@ func_mode_compile () # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # - lastarg="$srcfile" - srcfile="$arg" + lastarg=$srcfile + srcfile=$arg ;; esac # case $arg ;; @@ -2043,13 +3451,13 @@ func_mode_compile () func_fatal_error "you must specify an argument for -Xcompile" ;; target) - func_fatal_error "you must specify a target with \`-o'" + func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" - libobj="$func_basename_result" + libobj=$func_basename_result } ;; esac @@ -2069,7 +3477,7 @@ func_mode_compile () case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) - func_fatal_error "cannot determine name of library object from \`$libobj'" + func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac @@ -2078,8 +3486,8 @@ func_mode_compile () for arg in $later; do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; @@ -2105,17 +3513,17 @@ func_mode_compile () func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." + && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" @@ -2127,16 +3535,16 @@ func_mode_compile () pic_mode=default ;; esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock else output_obj= need_locks=no @@ -2145,12 +3553,12 @@ func_mode_compile () # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then + if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done - elif test "$need_locks" = warn; then + elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: @@ -2158,7 +3566,7 @@ func_mode_compile () This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2180,11 +3588,11 @@ compiler." qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile - if test "$pic_mode" != no; then + if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code @@ -2201,7 +3609,7 @@ compiler." func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2212,7 +3620,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2228,20 +3636,20 @@ compiler." fi # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then + if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi - if test "$compiler_c_o" = yes; then + if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi @@ -2250,7 +3658,7 @@ compiler." func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2261,7 +3669,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2281,7 +3689,7 @@ compiler." func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked - if test "$need_locks" != no; then + if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi @@ -2291,7 +3699,7 @@ compiler." } $opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () @@ -2311,7 +3719,7 @@ func_mode_help () Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated @@ -2330,16 +3738,16 @@ This mode accepts the following additional options: -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler -COMPILE-COMMAND is a command to be used in creating a \`standard' object file +COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." ;; execute) @@ -2352,7 +3760,7 @@ This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path -This mode sets the library path environment variable according to \`-dlopen' +This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated @@ -2371,7 +3779,7 @@ Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." +the '--dry-run' option if you just want to see what would be executed." ;; install) @@ -2381,7 +3789,7 @@ the \`--dry-run' option if you just want to see what would be executed." Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. +either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: @@ -2407,7 +3815,7 @@ The following components of LINK-COMMAND are treated specially: -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE @@ -2421,7 +3829,8 @@ The following components of LINK-COMMAND are treated specially: -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information @@ -2441,20 +3850,20 @@ The following components of LINK-COMMAND are treated specially: -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) -All other options (arguments beginning with \`-') are ignored. +All other options (arguments beginning with '-') are ignored. -Every other argument is treated as a filename. Files ending in \`.la' are +Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; @@ -2465,7 +3874,7 @@ is created, otherwise an executable program is created." Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. @@ -2473,17 +3882,17 @@ Otherwise, only FILE itself is deleted using RM." ;; *) - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo - $ECHO "Try \`$progname --help' for more information about other modes." + $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then - if test "$opt_help" = :; then + if test : = "$opt_help"; then func_mode_help else { @@ -2491,7 +3900,7 @@ if $opt_help; then for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do @@ -2499,7 +3908,7 @@ if $opt_help; then func_mode_help done } | - sed '1d + $SED '1d /^When reporting/,/^Report/{ H d @@ -2516,16 +3925,17 @@ fi # func_mode_execute arg... func_mode_execute () { - $opt_debug + $debug_cmd + # The first argument is the command name. - cmd="$nonopt" + cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ - || func_fatal_help "\`$file' is not a file" + || func_fatal_help "'$file' is not a file" dir= case $file in @@ -2535,7 +3945,7 @@ func_mode_execute () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" + || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= @@ -2546,18 +3956,18 @@ func_mode_execute () if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" + func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; @@ -2565,18 +3975,18 @@ func_mode_execute () *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result ;; *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" + test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then @@ -2588,7 +3998,7 @@ func_mode_execute () # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. - libtool_execute_magic="$magic" + libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= @@ -2601,12 +4011,12 @@ func_mode_execute () if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program fi ;; esac @@ -2614,7 +4024,15 @@ func_mode_execute () func_append_quoted args "$file" done - if test "X$opt_dry_run" = Xfalse; then + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" @@ -2631,25 +4049,18 @@ func_mode_execute () done # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS + exec_cmd=\$cmd$args fi } -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { - $opt_debug + $debug_cmd + libs= libdirs= admincmds= @@ -2663,11 +4074,11 @@ func_mode_finish () if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else - func_warning "\`$opt' is not a valid libtool archive" + func_warning "'$opt' is not a valid libtool archive" fi else - func_fatal_error "invalid argument \`$opt'" + func_fatal_error "invalid argument '$opt'" fi done @@ -2682,12 +4093,12 @@ func_mode_finish () # Remove sysroot references if $opt_dry_run; then for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done @@ -2712,7 +4123,7 @@ func_mode_finish () fi # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS + $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" @@ -2723,27 +4134,27 @@ func_mode_finish () echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" - $ECHO " - use the \`$flag' linker flag" + $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo @@ -2762,18 +4173,20 @@ func_mode_finish () exit $EXIT_SUCCESS } -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { - $opt_debug + $debug_cmd + # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then + case $nonopt in *shtool*) :;; *) false;; esac + then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " @@ -2800,7 +4213,7 @@ func_mode_install () opts= prev= install_type= - isdir=no + isdir=false stripme= no_mode=: for arg @@ -2813,7 +4226,7 @@ func_mode_install () fi case $arg in - -d) isdir=yes ;; + -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg @@ -2831,7 +4244,7 @@ func_mode_install () *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi @@ -2856,7 +4269,7 @@ func_mode_install () func_fatal_help "you must specify an install program" test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" + func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else @@ -2878,19 +4291,19 @@ func_mode_install () dest=$func_stripname_result # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" + destdir=$func_dirname_result + destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" + func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; @@ -2899,7 +4312,7 @@ func_mode_install () case $file in *.lo) ;; *) - func_fatal_help "\`$destdir' must be an absolute directory name" + func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done @@ -2908,7 +4321,7 @@ func_mode_install () # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic staticlibs= future_libdirs= @@ -2928,7 +4341,7 @@ func_mode_install () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" + || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= @@ -2950,7 +4363,7 @@ func_mode_install () fi func_dirname "$file" "/" "" - dir="$func_dirname_result" + dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then @@ -2964,7 +4377,7 @@ func_mode_install () # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. @@ -2973,29 +4386,36 @@ func_mode_install () relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi - func_warning "relinking \`$file'" + func_warning "relinking '$file'" func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then - realname="$1" + realname=$1 shift - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T + srcname=$realname + test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' - tstripme="$stripme" + tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) - tstripme="" + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= ;; esac ;; @@ -3006,7 +4426,7 @@ func_mode_install () if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on + # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname @@ -3017,14 +4437,14 @@ func_mode_install () fi # Do each command in the postinstall commands. - lib="$destdir/$realname" + lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i + name=$func_basename_result + instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. @@ -3036,11 +4456,11 @@ func_mode_install () # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. @@ -3050,11 +4470,11 @@ func_mode_install () staticdest=$func_lo2o_result ;; *.$objext) - staticdest="$destfile" + staticdest=$destfile destfile= ;; *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" + func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac @@ -3063,7 +4483,7 @@ func_mode_install () func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result @@ -3075,23 +4495,23 @@ func_mode_install () *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install - stripped_ext="" + stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result - stripped_ext=".exe" + stripped_ext=.exe fi ;; esac @@ -3119,19 +4539,19 @@ func_mode_install () # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" + func_fatal_error "invalid libtool wrapper script '$wrapper'" - finalize=yes + finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false fi done @@ -3139,29 +4559,29 @@ func_mode_install () func_source "$wrapper" outputname= - if test "$fast_install" = no && test -n "$relink_command"; then + if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { - if test "$finalize" = yes; then + if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" + file=$func_basename_result + outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - $opt_silent || { + $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else - func_error "error: relink \`$file' with the above command before installing it" + func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi - file="$outputname" + file=$outputname else - func_warning "cannot relink \`$file'" + func_warning "cannot relink '$file'" fi } else @@ -3198,10 +4618,10 @@ func_mode_install () for file in $staticlibs; do func_basename "$file" - name="$func_basename_result" + name=$func_basename_result # Set up the ranlib parameters. - oldlib="$destdir/$name" + oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result @@ -3216,18 +4636,18 @@ func_mode_install () done test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" + func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } -test "$opt_mode" = install && func_mode_install ${1+"$@"} +test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p @@ -3235,16 +4655,17 @@ test "$opt_mode" = install && func_mode_install ${1+"$@"} # a dlpreopen symbol table. func_generate_dlsyms () { - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" + my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi @@ -3255,7 +4676,7 @@ func_generate_dlsyms () "") ;; *.c) # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" + nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" @@ -3263,34 +4684,36 @@ func_generate_dlsyms () func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* External symbol declarations for the compiler. */\ " - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" @@ -3298,7 +4721,7 @@ extern \"C\" { progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done @@ -3318,10 +4741,10 @@ extern \"C\" { # Prepare the list of exported symbols if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" + export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' @@ -3331,7 +4754,7 @@ extern \"C\" { } else $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in @@ -3345,22 +4768,22 @@ extern \"C\" { fi for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" + func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" - name="$func_basename_result" + name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" + dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then + if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" + dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" @@ -3368,7 +4791,7 @@ extern \"C\" { fi fi $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then + if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" @@ -3424,6 +4847,11 @@ extern \"C\" { echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ @@ -3432,11 +4860,30 @@ typedef struct { void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi case $need_lib_prefix in no) @@ -3478,9 +4925,7 @@ static const void *lt_preloaded_setup() { *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi + $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; @@ -3497,10 +4942,10 @@ static const void *lt_preloaded_setup() { func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" + symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then @@ -3518,7 +4963,7 @@ static const void *lt_preloaded_setup() { esac ;; *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" + func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else @@ -3532,6 +4977,32 @@ static const void *lt_preloaded_setup() { fi } +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + # func_win32_libid arg # return the library type of file 'arg' # @@ -3541,8 +5012,9 @@ static const void *lt_preloaded_setup() { # Despite the name, also deal with 64 bit binaries. func_win32_libid () { - $opt_debug - win32_libid_type="unknown" + $debug_cmd + + win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import @@ -3552,16 +5024,29 @@ func_win32_libid () # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' 1,100{ / I /{ - s,.*,import, + s|.*|import| p q } }'` + ;; + esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -3593,7 +5078,8 @@ func_win32_libid () # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { - $opt_debug + $debug_cmd + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } @@ -3610,7 +5096,8 @@ func_cygming_dll_for_implib () # specified import library. func_cygming_dll_for_implib_fallback_core () { - $opt_debug + $debug_cmd + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ @@ -3646,8 +5133,8 @@ func_cygming_dll_for_implib_fallback_core () /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually @@ -3658,30 +5145,6 @@ func_cygming_dll_for_implib_fallback_core () $SED -e '/^\./d;/^.\./d;q' } -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified @@ -3695,16 +5158,17 @@ func_cygming_ms_implib_p () # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then + elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown - sharedlib_from_linklib_result="" + sharedlib_from_linklib_result= fi } @@ -3712,10 +5176,11 @@ func_cygming_dll_for_implib_fallback () # func_extract_an_archive dir oldlib func_extract_an_archive () { - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" @@ -3724,7 +5189,7 @@ func_extract_an_archive () fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then + if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then @@ -3738,22 +5203,23 @@ func_extract_an_archive () # func_extract_archives gentop oldlib ... func_extract_archives () { - $opt_debug - my_gentop="$1"; shift + $debug_cmd + + my_gentop=$1; shift my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" - my_xlib="$func_basename_result" + my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in @@ -3765,7 +5231,7 @@ func_extract_archives () esac done extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" @@ -3778,22 +5244,23 @@ func_extract_archives () cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do @@ -3815,7 +5282,7 @@ func_extract_archives () my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done - func_extract_archives_result="$my_oldobjs" + func_extract_archives_result=$my_oldobjs } @@ -3830,7 +5297,7 @@ func_extract_archives () # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is +# will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () @@ -3841,7 +5308,7 @@ func_emit_wrapper () #! $SHELL # $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. @@ -3898,9 +5365,9 @@ _LTECHO_EOF' # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on +# /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match +# (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and @@ -3933,7 +5400,7 @@ func_parse_lt_options () # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } @@ -3944,7 +5411,7 @@ func_lt_dump_args () lt_dump_args_N=1; for lt_arg do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } @@ -3958,7 +5425,7 @@ func_exec_program_core () *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} @@ -3968,7 +5435,7 @@ func_exec_program_core () *) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} @@ -4043,13 +5510,13 @@ func_exec_program () test -n \"\$absdir\" && thisdir=\"\$absdir\" " - if test "$fast_install" = yes; then + if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" @@ -4066,7 +5533,7 @@ func_exec_program () if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else - $ECHO \"\$relink_command_output\" >&2 + \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi @@ -4101,7 +5568,7 @@ func_exec_program () fi # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" @@ -4121,7 +5588,7 @@ func_exec_program () fi else # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 @@ -4140,7 +5607,7 @@ func_emit_cwrapperexe_src () cat < #include +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* declarations of non-ANSI functions */ -#if defined(__MINGW32__) +#if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif -/* #elif defined (other platforms) ... */ +/* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) +#if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) +#elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ +/* #elif defined other platforms ... */ #endif -#if defined(PATH_MAX) +#if defined PATH_MAX # define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) +#elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 @@ -4234,8 +5699,8 @@ int setenv (const char *, const char *, int); # define PATH_SEPARATOR ':' #endif -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 @@ -4268,10 +5733,10 @@ int setenv (const char *, const char *, int); #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ + if (stale) { free (stale); stale = 0; } \ } while (0) -#if defined(LT_DEBUGWRAPPER) +#if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; @@ -4300,11 +5765,16 @@ void lt_dump_script (FILE *f); EOF cat < 0) && IS_PATH_SEPARATOR (new_value[len-1])) + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { - new_value[len-1] = '\0'; + new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); @@ -5082,27 +6552,47 @@ EOF # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { - $opt_debug + $debug_cmd + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + # func_mode_link arg... func_mode_link () { - $opt_debug + $debug_cmd + case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra + # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not + # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. @@ -5146,10 +6636,11 @@ func_mode_link () module=no no_install=no objs= + os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no - preload=no + preload=false prev= prevarg= release= @@ -5161,7 +6652,7 @@ func_mode_link () vinfo= vinfo_number=no weak_libs= - single_module="${wl}-single_module" + single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. @@ -5169,15 +6660,15 @@ func_mode_link () do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then @@ -5210,7 +6701,7 @@ func_mode_link () # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do - arg="$1" + arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result @@ -5227,21 +6718,21 @@ func_mode_link () case $prev in bindir) - bindir="$arg" + bindir=$arg prev= continue ;; dlfiles|dlprefiles) - if test "$preload" = no; then + $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" - preload=yes - fi + preload=: + } case $arg in *.la | *.lo) ;; # We handle these cases below. force) - if test "$dlself" = no; then + if test no = "$dlself"; then dlself=needless export_dynamic=yes fi @@ -5249,9 +6740,9 @@ func_mode_link () continue ;; self) - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless @@ -5261,7 +6752,7 @@ func_mode_link () continue ;; *) - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" @@ -5272,14 +6763,14 @@ func_mode_link () esac ;; expsyms) - export_symbols="$arg" + export_symbols=$arg test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" + || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) - export_symbols_regex="$arg" + export_symbols_regex=$arg prev= continue ;; @@ -5297,7 +6788,13 @@ func_mode_link () continue ;; inst_prefix) - inst_prefix_dir="$arg" + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. prev= continue ;; @@ -5321,21 +6818,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5346,7 +6843,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5354,23 +6851,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" + arg=$pic_object fi # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5378,7 +6875,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5386,24 +6883,29 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi done else - func_fatal_error "link input file \`$arg' does not exist" + func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; precious_regex) - precious_files_regex="$arg" + precious_files_regex=$arg prev= continue ;; release) - release="-$arg" + release=-$arg prev= continue ;; @@ -5415,7 +6917,7 @@ func_mode_link () func_fatal_error "only absolute run-paths are allowed" ;; esac - if test "$prev" = rpath; then + if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; @@ -5430,7 +6932,7 @@ func_mode_link () continue ;; shrext) - shrext_cmds="$arg" + shrext_cmds=$arg prev= continue ;; @@ -5470,7 +6972,7 @@ func_mode_link () esac fi # test -n "$prev" - prevarg="$arg" + prevarg=$arg case $arg in -all-static) @@ -5484,7 +6986,7 @@ func_mode_link () -allow-undefined) # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" + func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) @@ -5516,7 +7018,7 @@ func_mode_link () if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi - if test "X$arg" = "X-export-symbols"; then + if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex @@ -5550,9 +7052,9 @@ func_mode_link () func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" + func_fatal_error "require no space between '-L' and '$1'" else - func_fatal_error "need path for \`-L' option" + func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" @@ -5563,8 +7065,8 @@ func_mode_link () *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir ;; esac case "$deplibs " in @@ -5599,7 +7101,7 @@ func_mode_link () ;; -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) @@ -5607,11 +7109,11 @@ func_mode_link () ;; *-*-os2*) # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework @@ -5620,16 +7122,16 @@ func_mode_link () ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; esac - elif test "X$arg" = "X-lc_r"; then + elif test X-lc_r = "X$arg"; then case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; @@ -5639,6 +7141,11 @@ func_mode_link () continue ;; + -mllvm) + prev=mllvm + continue + ;; + -module) module=yes continue @@ -5668,7 +7175,7 @@ func_mode_link () ;; -multi_module) - single_module="${wl}-multi_module" + single_module=$wl-multi_module continue ;; @@ -5682,8 +7189,8 @@ func_mode_link () *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; @@ -5701,6 +7208,11 @@ func_mode_link () continue ;; + -os2dllname) + prev=os2dllname + continue + ;; + -o) prev=output ;; -precious-files-regex) @@ -5788,14 +7300,14 @@ func_mode_link () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -5804,15 +7316,15 @@ func_mode_link () func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -5835,7 +7347,7 @@ func_mode_link () # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: @@ -5847,25 +7359,52 @@ func_mode_link () # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + # -static-* direct GCC to link specific libraries statically + # -fcilkplus Cilk Plus language extension features for C/C++ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; *.$objext) @@ -5886,21 +7425,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + test none = "$pic_object" || { # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5911,7 +7450,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5919,23 +7458,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" - fi + arg=$pic_object + } # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5943,7 +7482,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5951,7 +7490,7 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; @@ -5967,11 +7506,11 @@ func_mode_link () # A libtool-controlled library. func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= - elif test "$prev" = dlprefiles; then + elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= @@ -5986,7 +7525,7 @@ func_mode_link () # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; esac # arg @@ -5998,9 +7537,9 @@ func_mode_link () done # argument parsing loop test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" + func_fatal_help "the '$prevarg' option requires an argument" - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" @@ -6009,20 +7548,23 @@ func_mode_link () oldlibs= # calculate the name of the file, without its directory func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" + outputname=$func_basename_result + libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" + output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. @@ -6045,7 +7587,7 @@ func_mode_link () # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6053,7 +7595,7 @@ func_mode_link () func_append libs " $deplib" done - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps @@ -6085,7 +7627,7 @@ func_mode_link () case $file in *.la) ;; *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done @@ -6093,7 +7635,7 @@ func_mode_link () prog) compile_deplibs= finalize_deplibs= - alldeplibs=no + alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" @@ -6105,32 +7647,32 @@ func_mode_link () for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then + if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs fi - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs deplibs= fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then + if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs @@ -6151,26 +7693,26 @@ func_mode_link () esac done done - libs="$dlprefiles" + libs=$dlprefiles fi - if test "$pass" = dlopen; then + if test dlopen = "$pass"; then # Collect dlpreopened libraries - save_deplibs="$deplibs" + save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= - found=no + found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6180,13 +7722,13 @@ func_mode_link () continue ;; -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" @@ -6194,31 +7736,22 @@ func_mode_link () for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" + lib=$searchdir/lib$name$search_ext if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes + if test .la = "$search_ext"; then + found=: else - found=no + found=false fi break 2 fi done done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library + if $found; then + # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then @@ -6226,19 +7759,19 @@ func_mode_link () old_library= func_source "$lib" for l in $old_library $library_names; do - ll="$l" + ll=$l done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no + if test "X$ll" = "X$old_library"; then # only static version available + found=false func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi @@ -6247,15 +7780,25 @@ func_mode_link () *) ;; esac fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue fi ;; # -l *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6268,18 +7811,18 @@ func_mode_link () case $linkmode in lib) deplibs="$deplib $deplibs" - test "$pass" = conv && continue + test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi - if test "$pass" = scan; then + if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6290,13 +7833,13 @@ func_mode_link () func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) - func_warning "\`-L' is ignored for archives/objects" + func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) - if test "$pass" = link; then + if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result @@ -6314,7 +7857,7 @@ func_mode_link () lib=$func_resolve_sysroot_result ;; *.$libext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi @@ -6325,21 +7868,26 @@ func_mode_link () case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) - valid_a_lib=no + valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes + valid_a_lib=: fi ;; pass_all) - valid_a_lib=yes + valid_a_lib=: ;; esac - if test "$valid_a_lib" != yes; then + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" @@ -6347,18 +7895,13 @@ func_mode_link () echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) - if test "$pass" != link; then + if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6369,10 +7912,10 @@ func_mode_link () esac # linkmode ;; # *.$libext *.lo | *.$objext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" @@ -6385,22 +7928,20 @@ func_mode_link () continue ;; %DEPLIBS%) - alldeplibs=yes + alldeplibs=: continue ;; esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" + || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result dlname= dlopen= @@ -6430,19 +7971,19 @@ func_mode_link () done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi - if test "$pass" = conv; then + if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" @@ -6450,15 +7991,15 @@ func_mode_link () tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv @@ -6467,26 +8008,26 @@ func_mode_link () # Get the name of the library we link against. linklib= if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do - linklib="$l" + linklib=$l done fi if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't @@ -6500,40 +8041,40 @@ func_mode_link () # We need an absolute path. case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" + abs_ladir=$ladir fi ;; esac func_basename "$lib" - laname="$func_basename_result" + laname=$func_basename_result # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then + if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" + dir=$ladir + absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi @@ -6542,11 +8083,11 @@ func_mode_link () name=$func_stripname_result # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi - case "$host" in + case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both @@ -6590,9 +8131,9 @@ func_mode_link () if test -z "$libdir"; then # Link the convenience library - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then + elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else @@ -6602,14 +8143,14 @@ func_mode_link () fi - if test "$linkmode" = prog && test "$pass" != link; then + if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: fi tmp_libs= @@ -6621,14 +8162,14 @@ func_mode_link () ;; esac # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then + if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6638,15 +8179,15 @@ func_mode_link () continue fi # $linkmode = prog... - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in + case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac @@ -6675,9 +8216,9 @@ func_mode_link () esac fi # $linkmode,$pass = prog,link... - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue @@ -6686,19 +8227,19 @@ func_mode_link () link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then + if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then + { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in - *cygwin* | *mingw* | *cegcc*) + *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) - if test "$installed" = no; then + if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi @@ -6708,24 +8249,24 @@ func_mode_link () # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" + dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" + dlopenmodule=$dlpremoduletest break fi done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. @@ -6753,43 +8294,43 @@ func_mode_link () # figure out the soname set dummy $library_names shift - realname="$1" + realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then - soname="$dlname" + soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in - *cygwin* | mingw* | *cegcc*) + *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; esac eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" + soroot=$soname func_basename "$soroot" - soname="$func_basename_result" + soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else - func_verbose "extracting exported symbol list from \`$soname'" + func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" + func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library @@ -6797,58 +8338,58 @@ func_mode_link () linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" - if test "$linkmode" = prog || test "$opt_mode" != relink; then + if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" + if test no = "$hardcode_direct"; then + add=$dir/$linklib case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; + *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not + # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then + $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then + if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else - add="$dir/$old_library" + add=$dir/$old_library fi elif test -n "$old_library"; then - add="$dir/$old_library" + add=$dir/$old_library fi fi esac - elif test "$hardcode_minus_L" = no; then + elif test no = "$hardcode_minus_L"; then case $host in - *-*-sunos*) add_shlibpath="$dir" ;; + *-*-sunos*) add_shlibpath=$dir ;; esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi ;; relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6857,10 +8398,10 @@ func_mode_link () ;; esac fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi @@ -6868,7 +8409,7 @@ func_mode_link () *) lib_linked=no ;; esac - if test "$lib_linked" != yes; then + if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi @@ -6878,15 +8419,15 @@ func_mode_link () *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; @@ -6895,33 +8436,33 @@ func_mode_link () fi fi - if test "$linkmode" = prog || test "$opt_mode" = relink; then + if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then + add=-l$name + elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib else - add="$libdir/$linklib" + add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" + add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6930,10 +8471,10 @@ func_mode_link () ;; esac fi - add="-l$name" + add=-l$name fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else @@ -6941,43 +8482,43 @@ func_mode_link () test -n "$add" && deplibs="$add $deplibs" fi fi - elif test "$linkmode" = prog; then + elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi - elif test "$build_libtool_libs" = yes; then + elif test yes = "$build_libtool_libs"; then # Not a shared library - if test "$deplibs_check_method" != pass_all; then + if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then + if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then + if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else @@ -6990,11 +8531,11 @@ func_mode_link () fi fi # link shared/static library? - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do @@ -7008,12 +8549,12 @@ func_mode_link () *) func_append temp_deplibs " $libdir";; esac done - dependency_libs="$temp_deplibs" + dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do @@ -7023,7 +8564,7 @@ func_mode_link () func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; @@ -7032,12 +8573,12 @@ func_mode_link () func_append tmp_libs " $func_resolve_sysroot_result" done - if test "$link_all_deplibs" != no; then + if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in - -L*) path="$deplib" ;; + -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result @@ -7045,12 +8586,12 @@ func_mode_link () dir=$func_dirname_result # We need an absolute path. case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir fi ;; esac @@ -7058,35 +8599,35 @@ func_mode_link () case $host in *-*-darwin*) depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do depdepl=$tmp done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) - path="-L$absdir/$objdir" + path=-L$absdir/$objdir ;; esac else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" + func_warning "'$deplib' seems to be moved" - path="-L$absdir" + path=-L$absdir fi ;; esac @@ -7098,23 +8639,23 @@ func_mode_link () fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then + if test link = "$pass"; then + if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then + if test dlopen != "$pass"; then + test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do @@ -7124,12 +8665,12 @@ func_mode_link () esac done newlib_search_path= - fi + } - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else + if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" + else + vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order @@ -7187,62 +8728,93 @@ func_mode_link () eval $var=\"$tmp_libs\" done # for var fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= - for i in $dependency_libs ; do + for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) - i="" + i= ;; esac - if test -n "$i" ; then + if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" + if test prog = "$linkmode"; then + dlfiles=$newdlfiles fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles fi case $linkmode in oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; + func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" + func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" + func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" + func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ - func_warning "\`-release' is ignored for archives" + func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" + func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no - oldlibs="$output" + oldlibs=$output func_append objs "$old_deplibs" ;; lib) - # Make sure we only generate libraries of the form `libNAME.la'. + # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" @@ -7251,10 +8823,10 @@ func_mode_link () eval libname=\"$libname_spec\" ;; *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" - if test "$need_lib_prefix" != no; then + if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result @@ -7268,8 +8840,8 @@ func_mode_link () esac if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" @@ -7278,21 +8850,21 @@ func_mode_link () fi fi - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" - install_libdir="$1" + install_libdir=$1 oldlibs= if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so + # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" @@ -7301,20 +8873,20 @@ func_mode_link () fi test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" + func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. - save_ifs="$IFS"; IFS=':' + save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift - IFS="$save_ifs" + IFS=$save_ifs test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" + func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts @@ -7322,45 +8894,45 @@ func_mode_link () case $vinfo_number in yes) - number_major="$1" - number_minor="$2" - number_revision="$3" + number_major=$1 + number_minor=$2 + number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix - # which has an extra 1 added just for fun + # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) + darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_revision" + age=$number_minor + revision=$number_revision ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_minor" + age=$number_minor + revision=$number_minor lt_irix_increment=no ;; *) - func_fatal_configuration "$modename: unknown library version type \`$version_type'" + func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) - current="$1" - revision="$2" - age="$3" + current=$1 + revision=$2 + age=$3 ;; esac @@ -7368,30 +8940,30 @@ func_mode_link () case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. @@ -7406,26 +8978,36 @@ func_mode_link () # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac ;; freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; + major=.$current + versuffix=.$current.$revision ;; freebsd-elf) - major=".$current" - versuffix=".$current" + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision ;; irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then + if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 @@ -7436,69 +9018,74 @@ func_mode_link () nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac - verstring="$verstring_prefix$major.$revision" + verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" + verstring=$verstring_prefix$major.$iface:$verstring done - # Before this point, $major must not contain `.'. + # Before this point, $major must not contain '.'. major=.$major - versuffix="$major.$revision" + versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring:${iface}.0" + verstring=$verstring:$iface.0 done # Make executables depend on our current version. - func_append verstring ":${current}.0" + func_append verstring ":$current.0" ;; qnx) - major=".$current" - versuffix=".$current" + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current ;; sunos) - major=".$current" - versuffix=".$current.$revision" + major=.$current + versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. + # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; *) - func_fatal_configuration "unknown library version type \`$version_type'" + func_fatal_configuration "unknown library version type '$version_type'" ;; esac @@ -7512,42 +9099,45 @@ func_mode_link () verstring= ;; *) - verstring="0.0" + verstring=0.0 ;; esac - if test "$need_version" = no; then + if test no = "$need_version"; then versuffix= else - versuffix=".0.0" + versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then + if test yes,no = "$avoid_version,$need_version"; then major= versuffix= - verstring="" + verstring= fi # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi fi else # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" + allow_undefined_flag=$no_undefined_flag fi fi - func_generate_dlsyms "$libname" "$libname" "yes" + func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= + test " " = "$libobjs" && libobjs= - if test "$opt_mode" != relink; then + if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= @@ -7556,8 +9146,8 @@ func_mode_link () case $p in *.$objext | *.gcno) ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue @@ -7573,11 +9163,11 @@ func_mode_link () fi # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. @@ -7598,13 +9188,13 @@ func_mode_link () *) func_append finalize_rpath " $libdir" ;; esac done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" + old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in @@ -7614,7 +9204,7 @@ func_mode_link () done # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" + old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in @@ -7623,7 +9213,7 @@ func_mode_link () esac done - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) @@ -7647,7 +9237,7 @@ func_mode_link () ;; *) # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then + if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; @@ -7663,9 +9253,9 @@ func_mode_link () # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? - release="" - versuffix="" - major="" + release= + versuffix= + major= newdeplibs= droppeddeps=no case $deplibs_check_method in @@ -7694,20 +9284,20 @@ EOF -l*) func_stripname -l '' "$i" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7737,20 +9327,20 @@ EOF $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7787,24 +9377,24 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` if test -n "$file_magic_glob"; then libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` else libnameglob=$libname fi - test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` + test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - if test "$want_nocaseglob" = yes; then + if test yes = "$want_nocaseglob"; then shopt -s nocaseglob potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` $nocaseglob @@ -7822,25 +9412,25 @@ EOF # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? - potlib="$potent_lib" + potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7848,7 +9438,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7871,30 +9461,30 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test + potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7902,7 +9492,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7918,18 +9508,18 @@ EOF done # Gone through all deplibs. ;; none | unknown | *) - newdeplibs="" + newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo - if test "X$deplibs_check_method" = "Xnone"; then + if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." @@ -7953,8 +9543,8 @@ EOF ;; esac - if test "$droppeddeps" = yes; then - if test "$module" = yes; then + if test yes = "$droppeddeps"; then + if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" @@ -7963,12 +9553,12 @@ EOF if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -7979,14 +9569,14 @@ EOF echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." - if test "$allow_undefined" = no; then + if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -8032,7 +9622,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - deplibs="$new_libs" + deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= @@ -8040,25 +9630,25 @@ EOF dlname= # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac - if test "$hardcode_into_libs" = yes; then + if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8083,7 +9673,7 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then @@ -8097,8 +9687,8 @@ EOF test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi @@ -8108,19 +9698,19 @@ EOF eval library_names=\"$library_names_spec\" set dummy $library_names shift - realname="$1" + realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi if test -z "$dlname"; then dlname=$soname fi - lib="$output_objdir/$realname" + lib=$output_objdir/$realname linknames= for link do @@ -8134,7 +9724,7 @@ EOF delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi @@ -8143,31 +9733,31 @@ EOF cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. - orig_export_symbols="$export_symbols" + orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes - fi + } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do - IFS="$save_ifs" + IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in @@ -8181,7 +9771,7 @@ EOF try_normal_branch=no ;; esac - if test "$try_normal_branch" = yes \ + if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then @@ -8192,7 +9782,7 @@ EOF output_la=$func_basename_result save_libobjs=$libobjs save_output=$output - output=${output_objdir}/${output_la}.nm + output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" @@ -8215,8 +9805,8 @@ EOF break fi done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi @@ -8224,16 +9814,16 @@ EOF fi if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8252,11 +9842,11 @@ EOF ;; esac done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && + test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. @@ -8267,7 +9857,7 @@ EOF eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8276,18 +9866,18 @@ EOF fi fi - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds @@ -8305,7 +9895,7 @@ EOF fi fi - if test "X$skipped_export" != "X:" && + if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then @@ -8338,8 +9928,8 @@ EOF last_robj= k=1 - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs @@ -8351,14 +9941,14 @@ EOF func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= - if test "$compiler_needs_object" = yes; then + if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi @@ -8373,7 +9963,7 @@ EOF else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result @@ -8385,13 +9975,13 @@ EOF func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result - if test "X$objlist" = X || + if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. - if test "$k" -eq 1 ; then + if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" @@ -8401,10 +9991,10 @@ EOF reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi - last_robj=$output_objdir/$output_la-${k}.$objext + last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result @@ -8416,9 +10006,9 @@ EOF # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" @@ -8426,9 +10016,9 @@ EOF output= fi - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. @@ -8437,16 +10027,16 @@ EOF if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi - fi + } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { + IFS=$save_ifs + $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -8454,7 +10044,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8463,7 +10053,7 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' @@ -8471,18 +10061,18 @@ EOF fi fi - if ${skipped_export-false}; then + ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8491,7 +10081,7 @@ EOF export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi - fi + } libobjs=$output # Restore the value of output. @@ -8505,7 +10095,7 @@ EOF # value of $libobjs for piecewise linking. # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else @@ -8527,7 +10117,7 @@ EOF # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -8535,11 +10125,12 @@ EOF test "X$libobjs" = "X " && libobjs= fi - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $cmds; do - IFS="$save_ifs" + IFS=$sp$nl eval cmd=\"$cmd\" - $opt_silent || { + IFS=$save_ifs + $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -8547,7 +10138,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8556,10 +10147,10 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then @@ -8579,39 +10170,39 @@ EOF done # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then + if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. - dlname="$soname" + dlname=$soname fi fi ;; obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; + func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" + func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" + func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" + func_warning "'-version-info' is ignored for objects" test -n "$release" && \ - func_warning "\`-release' is ignored for objects" + func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" + func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" @@ -8619,7 +10210,7 @@ EOF ;; *) libobj= - obj="$output" + obj=$output ;; esac @@ -8632,17 +10223,19 @@ EOF # the extraction. reload_conv_objs= gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else - gentop="$output_objdir/${obj}x" + gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8651,12 +10244,12 @@ EOF fi # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs - output="$obj" + output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. @@ -8668,7 +10261,7 @@ EOF exit $EXIT_SUCCESS fi - if test "$build_libtool_libs" != yes; then + test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi @@ -8678,12 +10271,12 @@ EOF # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS - fi + } - if test -n "$pic_flag" || test "$pic_mode" != default; then + if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" - output="$libobj" + output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi @@ -8700,16 +10293,14 @@ EOF output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" + func_warning "'-version-info' is ignored for programs" test -n "$release" && \ - func_warning "\`-release' is ignored for programs" + func_warning "'-release' is ignored for programs" - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) @@ -8723,11 +10314,11 @@ EOF *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then + if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" ;; esac fi @@ -8763,7 +10354,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - compile_deplibs="$new_libs" + compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" @@ -8787,7 +10378,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8810,7 +10401,7 @@ EOF fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; @@ -8827,10 +10418,10 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - compile_rpath="$rpath" + compile_rpath=$rpath rpath= hardcode_libdirs= @@ -8838,7 +10429,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8863,45 +10454,43 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - finalize_rpath="$rpath" + finalize_rpath=$rpath - if test -n "$libobjs" && test "$build_old_libs" = yes; then + if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi - wrappers_required=yes + wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no + wrappers_required=false ;; *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi + test yes = "$build_libtool_libs" || wrappers_required=false ;; *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false fi ;; esac - if test "$wrappers_required" = no; then + $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" + link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 @@ -8914,12 +10503,12 @@ EOF fi # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status - fi + } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" @@ -8949,9 +10538,9 @@ EOF fi fi - if test "$no_install" = yes; then + if test yes = "$no_install"; then # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" + link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. @@ -8968,27 +10557,28 @@ EOF exit $EXIT_SUCCESS fi - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` @@ -9045,8 +10635,8 @@ EOF func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 @@ -9067,7 +10657,7 @@ EOF trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then + if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result @@ -9090,25 +10680,27 @@ EOF # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience build_libtool_libs=no - else + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs @@ -9116,13 +10708,13 @@ EOF fi # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -9143,7 +10735,7 @@ EOF : else echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs @@ -9152,7 +10744,7 @@ EOF for obj in $save_oldobjs do func_basename "$obj" - objbase="$func_basename_result" + objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) @@ -9221,18 +10813,18 @@ EOF else # the above command should be used before it gets too long oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then + if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist - if test "X$oldobjs" = "X" ; then + if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" @@ -9249,7 +10841,7 @@ EOF case $output in *.la) old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" + test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior @@ -9264,31 +10856,31 @@ EOF fi done # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then + if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do - if test "$installed" = yes; then + if test yes = "$installed"; then if test -z "$install_libdir"; then break fi - output="$output_objdir/$outputname"i + output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" - name="$func_basename_result" + name=$func_basename_result func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) @@ -9304,23 +10896,23 @@ EOF *) func_append newdependency_libs " $deplib" ;; esac done - dependency_libs="$newdependency_libs" + dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in @@ -9330,34 +10922,34 @@ EOF # didn't already link the preopened objects directly into # the library: func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin @@ -9373,10 +10965,9 @@ EOF case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then + if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname + tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname @@ -9385,7 +10976,7 @@ EOF esac $ECHO > $output "\ # $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. @@ -9399,7 +10990,7 @@ library_names='$library_names' # The name of the static archive. old_library='$old_library' -# Linker flags that can not go in dependency_libs. +# Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. @@ -9425,7 +11016,7 @@ dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then + if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi @@ -9440,27 +11031,29 @@ relink_command=\"$relink_command\"" exit $EXIT_SUCCESS } -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi # func_mode_uninstall arg... func_mode_uninstall () { - $opt_debug - RM="$nonopt" + $debug_cmd + + RM=$nonopt files= - rmforce= + rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic for arg do case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; + -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac @@ -9473,18 +11066,18 @@ func_mode_uninstall () for file in $files; do func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir else - odir="$dir/$objdir" + odir=$dir/$objdir fi func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then + if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; @@ -9499,11 +11092,11 @@ func_mode_uninstall () elif test -d "$file"; then exit_status=1 continue - elif test "$rmforce" = yes; then + elif $rmforce; then continue fi - rmfiles="$file" + rmfiles=$file case $name in *.la) @@ -9517,7 +11110,7 @@ func_mode_uninstall () done test -n "$old_library" && func_append rmfiles " $odir/$old_library" - case "$opt_mode" in + case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; @@ -9528,12 +11121,12 @@ func_mode_uninstall () uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; @@ -9549,21 +11142,19 @@ func_mode_uninstall () func_source $dir/$name # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then + if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then + if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) - if test "$opt_mode" = clean ; then + if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) @@ -9590,12 +11181,12 @@ func_mode_uninstall () # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" fi fi fi @@ -9604,7 +11195,7 @@ func_mode_uninstall () func_show_eval "$RM $rmfiles" 'exit_status=1' done - # Try to remove the ${objdir}s in the directories where we deleted files + # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" @@ -9614,16 +11205,17 @@ func_mode_uninstall () exit $exit_status } -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi test -z "$opt_mode" && { - help="$generic_help" + help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" @@ -9634,7 +11226,7 @@ exit $exit_status # The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting +# where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support @@ -9657,5 +11249,3 @@ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # mode:shell-script # sh-indentation:2 # End: -# vi:sw=2 - diff --git a/m4/gettext.m4 b/m4/gettext.m4 index dae3d81..8d1f066 100644 --- a/m4/gettext.m4 +++ b/m4/gettext.m4 @@ -1,5 +1,5 @@ -# gettext.m4 serial 53 (gettext-0.15) -dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +# gettext.m4 serial 66 (gettext-0.18.2) +dnl Copyright (C) 1995-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -15,7 +15,7 @@ dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2005. +dnl Bruno Haible , 2000-2006, 2008-2010. dnl Macro to add for using GNU gettext. @@ -35,7 +35,7 @@ dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, -dnl the value `$(top_builddir)/intl/' is used. +dnl the value '$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled @@ -60,11 +60,18 @@ AC_DEFUN([AM_GNU_GETTEXT], ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) - define([gt_included_intl], ifelse([$1], [external], [no], [yes])) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ @@ -78,7 +85,7 @@ AC_DEFUN([AM_GNU_GETTEXT], dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then - dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: @@ -90,7 +97,7 @@ AC_DEFUN([AM_GNU_GETTEXT], AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) - dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. @@ -104,16 +111,25 @@ AC_DEFUN([AM_GNU_GETTEXT], LTLIBINTL= POSUB= + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) - AC_ARG_WITH(included-gettext, + AC_ARG_WITH([included-gettext], [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) - AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then @@ -122,26 +138,41 @@ AC_DEFUN([AM_GNU_GETTEXT], dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. - dnl Add a version number to the cache macros. - define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) - define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) - define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) - - AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, - [AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif +changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -]], [])[extern int _nl_msg_cat_cntr; -extern int *_nl_domain_bindings;], - [bindtextdomain ("", ""); -return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], - gt_cv_func_gnugettext_libc=yes, - gt_cv_func_gnugettext_libc=no)]) - - if test "$gt_cv_func_gnugettext_libc" != "yes"; then +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK @@ -152,49 +183,53 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], - gt_cv_func_gnugettext_libintl, + [$gt_func_gnugettext_libintl], [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. - AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION -#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) -#endif -typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -]], [])[extern int _nl_msg_cat_cntr; + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif -const char *_nl_expand_alias (const char *);], - [bindtextdomain ("", ""); -return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], - gt_cv_func_gnugettext_libintl=yes, - gt_cv_func_gnugettext_libintl=no) +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) dnl Now see whether libintl exists and depends on libiconv. - if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" - AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION -#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) -#endif -typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -]], [])[extern int _nl_msg_cat_cntr; + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif -const char *_nl_expand_alias (const char *);], - [bindtextdomain ("", ""); -return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], - [LIBINTL="$LIBINTL $LIBICONV" - LTLIBINTL="$LTLIBINTL $LTLIBICONV" - gt_cv_func_gnugettext_libintl=yes - ]) +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) @@ -204,8 +239,8 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) - if test "$gt_cv_func_gnugettext_libc" = "yes" \ - || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes @@ -252,7 +287,7 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then - AC_DEFINE(ENABLE_NLS, 1, + AC_DEFINE([ENABLE_NLS], [1], [Define to 1 if translation of program messages to the user's native language is requested.]) else @@ -265,7 +300,7 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" @@ -279,16 +314,16 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. - AC_DEFINE(HAVE_GETTEXT, 1, + AC_DEFINE([HAVE_GETTEXT], [1], [Define if the GNU gettext() function is already present or preinstalled.]) - AC_DEFINE(HAVE_DCGETTEXT, 1, + AC_DEFINE([HAVE_DCGETTEXT], [1], [Define if the GNU dcgettext() function is already present or preinstalled.]) fi @@ -304,9 +339,9 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], fi dnl Make all variables we use known to autoconf. - AC_SUBST(BUILD_INCLUDED_LIBINTL) - AC_SUBST(USE_INCLUDED_LIBINTL) - AC_SUBST(CATOBJEXT) + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= @@ -314,316 +349,51 @@ return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share - AC_SUBST(DATADIRNAME) + AC_SUBST([DATADIRNAME]) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo - AC_SUBST(INSTOBJEXT) + AC_SUBST([INSTOBJEXT]) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat - AC_SUBST(GENCAT) + AC_SUBST([GENCAT]) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi - AC_SUBST(INTLOBJS) + AC_SUBST([INTLOBJS]) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix - AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" - AC_SUBST(INTLLIBS) + AC_SUBST([INTLLIBS]) dnl Make all documented variables known to autoconf. - AC_SUBST(LIBINTL) - AC_SUBST(LTLIBINTL) - AC_SUBST(POSUB) + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) ]) -dnl Checks for all prerequisites of the intl subdirectory, -dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, -dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. -AC_DEFUN([AM_INTL_SUBDIR], +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], [ - AC_REQUIRE([AC_PROG_INSTALL])dnl - AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake - AC_REQUIRE([AC_PROG_CC])dnl - AC_REQUIRE([AC_CANONICAL_HOST])dnl - AC_REQUIRE([gt_GLIBC2])dnl - AC_REQUIRE([AC_PROG_RANLIB])dnl - AC_REQUIRE([gl_VISIBILITY])dnl - AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl - AC_REQUIRE([bh_C_SIGNED])dnl - AC_REQUIRE([gl_AC_TYPE_LONG_LONG])dnl - AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl - AC_REQUIRE([gt_TYPE_WCHAR_T])dnl - AC_REQUIRE([gt_TYPE_WINT_T])dnl - AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) - AC_REQUIRE([gt_TYPE_INTMAX_T]) - AC_REQUIRE([gt_PRINTF_POSIX]) - AC_REQUIRE([gl_GLIBC21])dnl - AC_REQUIRE([gl_XSIZE])dnl - AC_REQUIRE([gt_INTL_MACOSX])dnl - - AC_CHECK_TYPE([ptrdiff_t], , - [AC_DEFINE([ptrdiff_t], [long], - [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) - ]) - AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) - AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) - - dnl Use the _snprintf function only if it is declared (because on NetBSD it - dnl is defined as a weak alias of snprintf; we prefer to use the latter). - gt_CHECK_DECL(_snprintf, [#include ]) - gt_CHECK_DECL(_snwprintf, [#include ]) - - dnl Use the *_unlocked functions only if they are declared. - dnl (because some of them were defined without being declared in Solaris - dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built - dnl on Solaris 2.5.1 to run on Solaris 2.6). - dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. - gt_CHECK_DECL(getc_unlocked, [#include ]) - - case $gt_cv_func_printf_posix in - *yes) HAVE_POSIX_PRINTF=1 ;; - *) HAVE_POSIX_PRINTF=0 ;; - esac - AC_SUBST([HAVE_POSIX_PRINTF]) - if test "$ac_cv_func_asprintf" = yes; then - HAVE_ASPRINTF=1 - else - HAVE_ASPRINTF=0 - fi - AC_SUBST([HAVE_ASPRINTF]) - if test "$ac_cv_func_snprintf" = yes; then - HAVE_SNPRINTF=1 - else - HAVE_SNPRINTF=0 - fi - AC_SUBST([HAVE_SNPRINTF]) - if test "$ac_cv_func_wprintf" = yes; then - HAVE_WPRINTF=1 - else - HAVE_WPRINTF=0 - fi - AC_SUBST([HAVE_WPRINTF]) - - AM_LANGINFO_CODESET - gt_LC_MESSAGES - - dnl Compilation on mingw and Cygwin needs special Makefile rules, because - dnl 1. when we install a shared library, we must arrange to export - dnl auxiliary pointer variables for every exported variable, - dnl 2. when we install a shared library and a static library simultaneously, - dnl the include file specifies __declspec(dllimport) and therefore we - dnl must arrange to define the auxiliary pointer variables for the - dnl exported variables _also_ in the static library. - if test "$enable_shared" = yes; then - case "$host_os" in - cygwin*) is_woe32dll=yes ;; - *) is_woe32dll=no ;; - esac - else - is_woe32dll=no - fi - WOE32DLL=$is_woe32dll - AC_SUBST([WOE32DLL]) - - dnl Rename some macros and functions used for locking. - AH_BOTTOM([ -#define __libc_lock_t gl_lock_t -#define __libc_lock_define gl_lock_define -#define __libc_lock_define_initialized gl_lock_define_initialized -#define __libc_lock_init gl_lock_init -#define __libc_lock_lock gl_lock_lock -#define __libc_lock_unlock gl_lock_unlock -#define __libc_lock_recursive_t gl_recursive_lock_t -#define __libc_lock_define_recursive gl_recursive_lock_define -#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized -#define __libc_lock_init_recursive gl_recursive_lock_init -#define __libc_lock_lock_recursive gl_recursive_lock_lock -#define __libc_lock_unlock_recursive gl_recursive_lock_unlock -#define glthread_in_use libintl_thread_in_use -#define glthread_lock_init libintl_lock_init -#define glthread_lock_lock libintl_lock_lock -#define glthread_lock_unlock libintl_lock_unlock -#define glthread_lock_destroy libintl_lock_destroy -#define glthread_rwlock_init libintl_rwlock_init -#define glthread_rwlock_rdlock libintl_rwlock_rdlock -#define glthread_rwlock_wrlock libintl_rwlock_wrlock -#define glthread_rwlock_unlock libintl_rwlock_unlock -#define glthread_rwlock_destroy libintl_rwlock_destroy -#define glthread_recursive_lock_init libintl_recursive_lock_init -#define glthread_recursive_lock_lock libintl_recursive_lock_lock -#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock -#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy -#define glthread_once libintl_once -#define glthread_once_call libintl_once_call -#define glthread_once_singlethreaded libintl_once_singlethreaded -]) -]) - - -dnl Checks for the core files of the intl subdirectory: -dnl dcigettext.c -dnl eval-plural.h -dnl explodename.c -dnl finddomain.c -dnl gettextP.h -dnl gmo.h -dnl hash-string.h hash-string.c -dnl l10nflist.c -dnl libgnuintl.h.in (except the *printf stuff) -dnl loadinfo.h -dnl loadmsgcat.c -dnl localealias.c -dnl log.c -dnl plural-exp.h plural-exp.c -dnl plural.y -dnl Used by libglocale. -AC_DEFUN([gt_INTL_SUBDIR_CORE], -[ - AC_REQUIRE([AC_C_INLINE])dnl - AC_REQUIRE([AC_TYPE_SIZE_T])dnl - AC_REQUIRE([gl_AC_HEADER_STDINT_H]) - AC_REQUIRE([AC_FUNC_ALLOCA])dnl - AC_REQUIRE([AC_FUNC_MMAP])dnl - AC_REQUIRE([gt_INTDIV0])dnl - AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl - AC_REQUIRE([gl_HEADER_INTTYPES_H])dnl - AC_REQUIRE([gt_INTTYPES_PRI])dnl - AC_REQUIRE([gl_LOCK])dnl - - AC_TRY_LINK( - [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], - [], - [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, - [Define to 1 if the compiler understands __builtin_expect.])]) - - AC_CHECK_HEADERS([argz.h limits.h unistd.h sys/param.h]) - AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ - stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ - argz_next __fsetlocking]) - - dnl Use the *_unlocked functions only if they are declared. - dnl (because some of them were defined without being declared in Solaris - dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built - dnl on Solaris 2.5.1 to run on Solaris 2.6). - dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. - gt_CHECK_DECL(feof_unlocked, [#include ]) - gt_CHECK_DECL(fgets_unlocked, [#include ]) - - AM_ICONV - - dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, - dnl and a _NL_LOCALE_NAME macro always. - AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, - [AC_TRY_LINK([#include -#include ], - [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES));], - gt_cv_nl_locale_name=yes, - gt_cv_nl_locale_name=no) - ]) - if test $gt_cv_nl_locale_name = yes; then - AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, - [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) - fi - - dnl intl/plural.c is generated from intl/plural.y. It requires bison, - dnl because plural.y uses bison specific features. It requires at least - dnl bison-1.26 because earlier versions generate a plural.c that doesn't - dnl compile. - dnl bison is only needed for the maintainer (who touches plural.y). But in - dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put - dnl the rule in general Makefile. Now, some people carelessly touch the - dnl files or have a broken "make" program, hence the plural.c rule will - dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not - dnl present or too old. - AC_CHECK_PROGS([INTLBISON], [bison]) - if test -z "$INTLBISON"; then - ac_verc_fail=yes - else - dnl Found it, now check the version. - AC_MSG_CHECKING([version of bison]) -changequote(<<,>>)dnl - ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` - case $ac_prog_version in - '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; - 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) -changequote([,])dnl - ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; - *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; - esac - AC_MSG_RESULT([$ac_prog_version]) - fi - if test $ac_verc_fail = yes; then - INTLBISON=: - fi -]) - - -dnl Checks for special options needed on MacOS X. -dnl Defines INTL_MACOSX_LIBS. -AC_DEFUN([gt_INTL_MACOSX], -[ - dnl Check for API introduced in MacOS X 10.2. - AC_CACHE_CHECK([for CFPreferencesCopyAppValue], - gt_cv_func_CFPreferencesCopyAppValue, - [gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - AC_TRY_LINK([#include ], - [CFPreferencesCopyAppValue(NULL, NULL)], - [gt_cv_func_CFPreferencesCopyAppValue=yes], - [gt_cv_func_CFPreferencesCopyAppValue=no]) - LIBS="$gt_save_LIBS"]) - if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then - AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, - [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) - fi - dnl Check for API introduced in MacOS X 10.3. - AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, - [gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], - [gt_cv_func_CFLocaleCopyCurrent=yes], - [gt_cv_func_CFLocaleCopyCurrent=no]) - LIBS="$gt_save_LIBS"]) - if test $gt_cv_func_CFLocaleCopyCurrent = yes; then - AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, - [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) - fi - INTL_MACOSX_LIBS= - if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then - INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" - fi - AC_SUBST([INTL_MACOSX_LIBS]) + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) ]) -dnl gt_CHECK_DECL(FUNC, INCLUDES) -dnl Check whether a function is declared. -AC_DEFUN([gt_CHECK_DECL], +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], [ - AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, - [AC_TRY_COMPILE([$2], [ -#ifndef $1 - char *p = (char *) $1; -#endif -], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) - if test $ac_cv_have_decl_$1 = yes; then - gt_value=1 - else - gt_value=0 - fi - AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], - [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) ]) diff --git a/m4/iconv.m4 b/m4/iconv.m4 index 654c415..a503646 100644 --- a/m4/iconv.m4 +++ b/m4/iconv.m4 @@ -1,5 +1,5 @@ -# iconv.m4 serial AM4 (gettext-0.11.3) -dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +# iconv.m4 serial 18 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -21,6 +21,7 @@ AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. @@ -29,34 +30,170 @@ AC_DEFUN([AM_ICONV_LINK], dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first - dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) - AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_func_iconv=yes) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_lib_iconv=yes - am_cv_func_iconv=yes) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then - AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +}]])], + [am_cv_func_iconv_works=yes], + [am_cv_func_iconv_works=no], + [ +changequote(,)dnl + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +changequote([,])dnl + ]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) @@ -68,34 +205,64 @@ AC_DEFUN([AM_ICONV_LINK], LIBICONV= LTLIBICONV= fi - AC_SUBST(LIBICONV) - AC_SUBST(LTLIBICONV) + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) ]) -AC_DEFUN([AM_ICONV], +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) - AC_CACHE_VAL(am_cv_proto_iconv, [ - AC_TRY_COMPILE([ + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ #include #include extern #ifdef __cplusplus "C" #endif -#if defined(__STDC__) || defined(__cplusplus) +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif -], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` - AC_MSG_RESULT([$]{ac_t:- - }[$]am_cv_proto_iconv) - AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) fi ]) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 0000000..ab97d39 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,56 @@ +# intlmacosx.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2004-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on Mac OS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in Mac OS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFPreferencesCopyAppValue(NULL, NULL)]])], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in Mac OS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFLocaleCopyCurrent();]])], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 index 96c4e2c..c145e47 100644 --- a/m4/lib-ld.m4 +++ b/m4/lib-ld.m4 @@ -1,50 +1,56 @@ -# lib-ld.m4 serial 3 (gettext-0.13) -dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, -dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision -dnl with libtool.m4. +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. -dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], -[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, -[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } fi + ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by GCC]) + AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw @@ -54,12 +60,12 @@ if test "$GCC" = yes; then esac case $ac_prog in # Accept absolute paths. - [[\\/]* | [A-Za-z]:[\\/]*)] - [re_direlt='/[^/][^/]*/\.\./'] - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; @@ -77,33 +83,36 @@ elif test "$with_gnu_ld" = yes; then else AC_MSG_CHECKING([for non-GNU ld]) fi -AC_CACHE_VAL(acl_cv_path_LD, +AC_CACHE_VAL([acl_cv_path_LD], [if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do + IFS="$acl_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. + # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + case `"$acl_cv_path_LD" -v 2>&1 = 1.10 to complain if config.rpath is missing. @@ -101,7 +130,7 @@ AC_DEFUN([AC_LIB_RPATH], AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir - AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh @@ -109,35 +138,66 @@ AC_DEFUN([AC_LIB_RPATH], acl_cv_rpath=done ]) wl="$acl_cv_wl" - libext="$acl_cv_libext" - shlibext="$acl_cv_shlibext" - hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" - hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" - hardcode_direct="$acl_cv_hardcode_direct" - hardcode_minus_L="$acl_cv_hardcode_minus_L" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. - AC_ARG_ENABLE(rpath, + AC_ARG_ENABLE([rpath], [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) - AC_LIB_ARG_WITH([lib$1-prefix], -[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib - --without-lib$1-prefix don't search for lib$1 in includedir and libdir], + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], [ if test "X$withval" = "Xno"; then use_additional=no @@ -150,6 +210,10 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi fi fi ]) @@ -158,6 +222,10 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], LIB[]NAME= LTLIB[]NAME= INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= rpathdirs= ltrpathdirs= names_already_handled= @@ -177,7 +245,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then @@ -197,22 +265,55 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], found_la= found_so= found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi if test $use_additional = yes; then - if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then - found_dir="$additional_libdir" - found_so="$additional_libdir/lib$name.$shlibext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - else - if test -f "$additional_libdir/lib$name.$libext"; then - found_dir="$additional_libdir" - found_a="$additional_libdir/lib$name.$libext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done fi fi fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do @@ -220,21 +321,46 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then - found_dir="$dir" - found_so="$dir/lib$name.$shlibext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - else - if test -f "$dir/lib$name.$libext"; then + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then found_dir="$dir" - found_a="$dir/lib$name.$libext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done fi fi fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi ;; esac if test "X$found_dir" != "X"; then @@ -249,7 +375,9 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else @@ -268,12 +396,12 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. - if test "$hardcode_direct" = yes; then + if test "$acl_hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" @@ -304,13 +432,13 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi - if test "$hardcode_minus_L" != no; then + if test "$acl_hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else - dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. @@ -337,6 +465,16 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi additional_includedir="$basedir/include" ;; esac @@ -397,9 +535,11 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. - if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= - if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; @@ -498,18 +638,18 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], done done if test "X$rpathdirs" != "X"; then - if test -n "$hardcode_libdir_separator"; then + if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done - dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" + eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else @@ -517,7 +657,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" - eval flag=\"$hardcode_libdir_flag_spec\" + eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done @@ -530,6 +670,11 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, @@ -566,7 +711,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= @@ -575,7 +720,8 @@ AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. - if test "X$dir" != "X/usr/$acl_libdirstem"; then + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= @@ -584,7 +730,8 @@ AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. - if test "X$dir" != "X/usr/$acl_libdirstem"; then + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= ;; @@ -600,16 +747,16 @@ AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], done else dnl The linker is used for linking directly. - if test -n "$hardcode_libdir_separator"; then + if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$dir" + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" + eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else @@ -617,7 +764,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" - eval flag=\"$hardcode_libdir_flag_spec\" + eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 index a8684e1..60908e8 100644 --- a/m4/lib-prefix.m4 +++ b/m4/lib-prefix.m4 @@ -1,5 +1,5 @@ -# lib-prefix.m4 serial 5 (gettext-0.15) -dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -153,33 +153,72 @@ AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], prefix="$acl_save_prefix" ]) -dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing -dnl the basename of the libdir, either "lib" or "lib64". +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ - dnl There is no formal standard regarding lib and lib64. The current - dnl practice is that on a system supporting 32-bit and 64-bit instruction - dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit - dnl libraries go under $prefix/lib. We determine the compiler's default - dnl mode by looking at the compiler's library search path. If at least - dnl of its elements ends in /lib64 or points to a directory whose absolute - dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the - dnl default, namely "lib". + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) acl_libdirstem=lib - searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` - if test -n "$searchpath"; then - acl_save_IFS="${IFS= }"; IFS=":" - for searchdir in $searchpath; do - if test -d "$searchdir"; then - case "$searchdir" in - */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; - *) searchdir=`cd "$searchdir" && pwd` - case "$searchdir" in - */lib64 ) acl_libdirstem=lib64 ;; - esac ;; + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; esac fi - done - IFS="$acl_save_IFS" - fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" ]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 index d7c043f..a6d21ae 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -1,8 +1,6 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,36 +8,30 @@ # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. # -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . ]) -# serial 57 LT_INIT +# serial 58 LT_INIT # LT_PREREQ(VERSION) @@ -67,7 +59,7 @@ esac # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl @@ -91,7 +83,7 @@ dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -111,26 +103,43 @@ dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + # _LT_CC_BASENAME(CC) # ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} @@ -177,15 +186,16 @@ m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi @@ -198,7 +208,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -209,14 +219,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -269,14 +279,14 @@ no_glob_subst='s/\*/\\\*/g' # _LT_PROG_LTMAIN # --------------- -# Note that this code is called both from `configure', and `config.status' +# Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN @@ -286,7 +296,7 @@ ltmain="$ac_aux_dir/ltmain.sh" # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' +# in macros and then make a single call at the end using the 'libtool' # label. @@ -421,8 +431,8 @@ m4_define([_lt_decl_all_varnames], # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) @@ -446,7 +456,7 @@ m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl +available_tags='_LT_TAGS'dnl ]) @@ -474,7 +484,7 @@ m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], @@ -500,8 +510,8 @@ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], @@ -547,7 +557,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -560,7 +570,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -576,7 +586,7 @@ _LT_OUTPUT_LIBTOOL_INIT # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the -# `#!' sequence but before initialization text begins. After this +# '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). @@ -598,7 +608,7 @@ AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF -test $lt_write_fail = 0 && chmod +x $1[]dnl +test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT @@ -621,7 +631,7 @@ exec AS_MESSAGE_LOG_FD>>config.log } >&AS_MESSAGE_LOG_FD lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, +'$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. @@ -643,7 +653,7 @@ Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." -while test $[#] != 0 +while test 0 != $[#] do case $[1] in --version | --v* | -V ) @@ -656,10 +666,10 @@ do lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; esac shift done @@ -685,7 +695,7 @@ chmod +x "$CONFIG_LT" # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: -test "$silent" = yes && +test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false @@ -705,27 +715,30 @@ m4_defun([_LT_CONFIG], _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. -# + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + _LT_COPYING _LT_LIBTOOL_TAGS +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS @@ -733,13 +746,24 @@ _LT_LIBTOOL_TAG_VARS _LT_EOF + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -756,8 +780,6 @@ _LT_EOF sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - _LT_PROG_REPLACE_SHELLFNS - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -775,7 +797,6 @@ _LT_EOF [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS @@ -974,7 +995,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -992,7 +1013,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1010,7 +1031,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], @@ -1020,8 +1041,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD - echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD - $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF @@ -1032,7 +1053,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1042,32 +1063,32 @@ _LT_EOF ]) case $host_os in rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -1087,29 +1108,29 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else @@ -1129,7 +1150,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl -if test "${lt_cv_aix_libpath+set}" = set; then +if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], @@ -1147,7 +1168,7 @@ else _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) @@ -1167,8 +1188,8 @@ m4_define([_LT_SHELL_INIT], # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script which will find a shell with a builtin -# printf (which we can use as an echo command). +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO @@ -1196,10 +1217,10 @@ fi # Invoke $ECHO with all args, space-separated. func_echo_all () { - $ECHO "$*" + $ECHO "$*" } -case "$ECHO" in +case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; @@ -1225,16 +1246,17 @@ _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], -[ --with-sysroot[=DIR] Search for dependent libraries within DIR - (or the compiler's sysroot if not specified).], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -1244,14 +1266,14 @@ case ${with_sysroot} in #( no|'') ;; #( *) - AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and in which our libraries should be installed.])]) +[dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- @@ -1259,31 +1281,33 @@ m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -1312,9 +1336,46 @@ ia64-*-hpux*) rm -rf conftest* ;; +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1333,10 +1394,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ;; esac ;; - powerpc64le-*) + powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*) + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1355,10 +1416,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*) + powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*) + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -1376,19 +1437,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1396,7 +1458,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -1405,7 +1467,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -1421,7 +1483,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK @@ -1430,7 +1492,7 @@ need_locks="$enable_libtool_lock" m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} -: ${AR_FLAGS=cru} +: ${AR_FLAGS=cr} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) @@ -1440,11 +1502,11 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi @@ -1452,7 +1514,7 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], ]) ]) -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -1483,7 +1545,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -1519,7 +1581,7 @@ AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -1546,7 +1608,7 @@ AC_CACHE_CHECK([$1], [$2], $RM conftest* ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) @@ -1568,7 +1630,7 @@ AC_DEFUN([_LT_LINKER_OPTION], m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -1587,10 +1649,10 @@ AC_CACHE_CHECK([$1], [$2], fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) @@ -1611,7 +1673,7 @@ AC_DEFUN([LT_CMD_MAX_LEN], AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -1651,7 +1713,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -1702,22 +1764,22 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -1733,7 +1795,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl ;; esac ]) -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) @@ -1761,7 +1823,7 @@ m4_defun([_LT_HEADER_DLFCN], # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : +if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -1808,9 +1870,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -1836,7 +1898,7 @@ int main () return status; }] _LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in @@ -1857,7 +1919,7 @@ rm -fr conftest* # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then +if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -1867,44 +1929,52 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], + [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], + [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) @@ -1913,21 +1983,21 @@ else ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], @@ -1937,7 +2007,7 @@ else lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl @@ -1947,9 +2017,9 @@ else ]) fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -2041,8 +2111,8 @@ m4_defun([_LT_COMPILER_FILE_LOCKS], m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes @@ -2052,8 +2122,8 @@ if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else @@ -2080,8 +2150,8 @@ objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR @@ -2093,15 +2163,15 @@ m4_defun([_LT_LINKER_HARDCODE_LIBPATH], _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else @@ -2115,12 +2185,12 @@ else fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -2144,7 +2214,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP" ; then + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) @@ -2162,6 +2232,47 @@ _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics @@ -2172,17 +2283,18 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -2198,28 +2310,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -2233,7 +2352,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -2242,7 +2361,7 @@ fi]) library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -2259,14 +2378,17 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) @@ -2274,41 +2396,91 @@ aix[[4-9]]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -2318,18 +2490,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -2337,8 +2509,8 @@ beos*) bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -2350,7 +2522,7 @@ bsdi[[45]]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -2359,8 +2531,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -2376,17 +2548,17 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' @@ -2395,8 +2567,8 @@ m4_if([$1], [],[ *,cl*) # Native MSVC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -2423,7 +2595,7 @@ m4_if([$1], [],[ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -2436,8 +2608,8 @@ m4_if([$1], [],[ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -2450,7 +2622,7 @@ m4_if([$1], [],[ *) # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -2463,8 +2635,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -2477,8 +2649,8 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2496,12 +2668,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -2531,10 +2704,10 @@ haiku*) need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -2552,14 +2725,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -2567,8 +2741,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -2577,8 +2751,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -2591,8 +2765,8 @@ interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2603,7 +2777,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -2611,8 +2785,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -2631,8 +2805,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -2641,13 +2815,33 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2672,7 +2866,12 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) # before this can be enabled. hardcode_into_libs=yes - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -2704,12 +2903,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -2719,7 +2918,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -2728,58 +2927,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no else - shlibpath_overrides_runpath=yes + need_version=yes fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -2790,8 +2999,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -2801,11 +3010,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -2813,8 +3022,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -2835,24 +3044,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -2870,7 +3079,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -2878,8 +3087,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2888,20 +3097,30 @@ uts4*) ;; esac AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) @@ -2934,39 +3153,41 @@ _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- -# find a file program which can recognize shared library +# find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -2989,11 +3210,11 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else @@ -3011,7 +3232,7 @@ dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- -# find a file program which can recognize a shared library +# find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then @@ -3038,16 +3259,16 @@ m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], + [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -3061,7 +3282,7 @@ if test "$GCC" = yes; then while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -3072,37 +3293,37 @@ if test "$GCC" = yes; then with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies @@ -3188,13 +3446,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) @@ -3221,8 +3479,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -3318,8 +3575,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' @@ -3372,6 +3629,9 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac ]) @@ -3412,33 +3672,38 @@ AC_DEFUN([LT_PATH_NM], AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -3449,21 +3714,21 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -3471,8 +3736,8 @@ else esac fi AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -3518,8 +3783,8 @@ lt_cv_sharedlib_from_linklib_cmd, case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -3531,7 +3796,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) @@ -3558,13 +3823,28 @@ AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) -if test "x$lt_cv_path_mainfest_tool" != xyes; then +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + # LT_LIB_M # -------- # check for math library @@ -3576,11 +3856,11 @@ case $host in # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) - AC_CHECK_LIB(m, cos, LIBM="-lm") + AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) @@ -3599,7 +3879,7 @@ m4_defun([_LT_COMPILER_NO_RTTI], _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; @@ -3651,7 +3931,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; @@ -3684,14 +3964,44 @@ case `$NM -V 2>&1` in symcode='[[ABCDGIRSTW]]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -3709,21 +4019,24 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -3750,7 +4063,8 @@ _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD + if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -3763,11 +4077,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else @@ -3793,7 +4107,7 @@ lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -3813,9 +4127,9 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -3836,7 +4150,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -3863,12 +4177,16 @@ _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS @@ -3884,17 +4202,18 @@ _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -3905,8 +4224,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -3922,6 +4241,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -3971,7 +4295,7 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4012,14 +4336,14 @@ m4_if([$1], [CXX], [ case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default @@ -4056,7 +4380,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. + # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' @@ -4201,17 +4525,18 @@ m4_if([$1], [CXX], [ fi ], [ - if test "$GCC" = yes; then + if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4222,8 +4547,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -4240,6 +4565,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -4310,7 +4640,7 @@ m4_if([$1], [CXX], [ case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4318,11 +4648,30 @@ m4_if([$1], [CXX], [ fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -4338,7 +4687,7 @@ m4_if([$1], [CXX], [ ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -4349,12 +4698,18 @@ m4_if([$1], [CXX], [ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; + # flang / f18. f95 an alias for gfortran or flang on Debian + flang* | f18* | f95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) @@ -4374,6 +4729,12 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -4471,7 +4832,7 @@ m4_if([$1], [CXX], [ ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi @@ -4500,7 +4861,7 @@ m4_if([$1], [CXX], [ fi ]) case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; @@ -4566,17 +4927,21 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in @@ -4625,9 +4990,9 @@ m4_if([$1], [CXX], [ # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -4643,7 +5008,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test "$GCC" != yes; then + if test yes != "$GCC"; then with_gnu_ld=no fi ;; @@ -4651,7 +5016,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) @@ -4664,7 +5029,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -4686,24 +5051,24 @@ dnl Note also adjust exclude_expsyms for C++ above. esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -4716,7 +5081,7 @@ dnl Note also adjust exclude_expsyms for C++ above. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 @@ -4735,7 +5100,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -4751,7 +5116,7 @@ _LT_EOF _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4761,7 +5126,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -4769,61 +5134,89 @@ _LT_EOF _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -4834,42 +5227,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -4883,8 +5281,8 @@ _LT_EOF _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -4902,8 +5300,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4915,7 +5313,7 @@ _LT_EOF _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -4930,9 +5328,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4949,15 +5347,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= @@ -4973,7 +5371,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported @@ -4981,34 +5379,57 @@ _LT_EOF ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -5027,13 +5448,21 @@ _LT_EOF _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -5052,62 +5481,80 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi - _LT_TAGVAR(link_all_deplibs, $1)=no + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -5116,7 +5563,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -5146,16 +5593,17 @@ _LT_EOF # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5164,18 +5612,18 @@ _LT_EOF # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -5184,7 +5632,7 @@ _LT_EOF # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -5234,33 +5682,33 @@ _LT_EOF ;; hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -5268,25 +5716,25 @@ _LT_EOF ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ @@ -5294,14 +5742,14 @@ _LT_EOF # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in @@ -5312,7 +5760,7 @@ _LT_EOF *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -5323,16 +5771,16 @@ _LT_EOF ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], - [save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], @@ -5345,21 +5793,32 @@ _LT_EOF end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) - LDFLAGS="$save_LDFLAGS"]) - if test "$lt_cv_irix_exported_symbol" = yes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi + _LT_TAGVAR(link_all_deplibs, $1)=no else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -5374,7 +5833,7 @@ _LT_EOF newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; @@ -5382,27 +5841,19 @@ _LT_EOF *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no @@ -5413,33 +5864,53 @@ _LT_EOF _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5450,24 +5921,24 @@ _LT_EOF solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -5477,11 +5948,11 @@ _LT_EOF solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi @@ -5491,10 +5962,10 @@ _LT_EOF ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -5543,43 +6014,43 @@ _LT_EOF ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -5594,17 +6065,17 @@ _LT_EOF ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld @@ -5621,7 +6092,7 @@ x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -5701,12 +6172,12 @@ _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the + "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR @@ -5747,10 +6218,10 @@ dnl [Compiler flag to generate thread safe objects]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" +lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. @@ -5790,18 +6261,18 @@ if test -n "$compiler"; then LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB - # Report which library types will actually be built + # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -5809,8 +6280,12 @@ if test -n "$compiler"; then ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -5818,13 +6293,13 @@ if test -n "$compiler"; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP -CC="$lt_save_CC" +CC=$lt_save_CC ])# _LT_LANG_C_CONFIG @@ -5832,14 +6307,14 @@ CC="$lt_save_CC" # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes @@ -5881,7 +6356,7 @@ _LT_TAGVAR(objext, $1)=$objext # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then +if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" @@ -5923,35 +6398,35 @@ if test "$_lt_caught_CXX_error" != yes; then if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi - if test "$GXX" = yes; then + if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) - wlarc='${wl}' + wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi @@ -5970,7 +6445,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no @@ -5987,18 +6462,30 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in @@ -6008,6 +6495,13 @@ if test "$_lt_caught_CXX_error" != yes; then ;; esac done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -6026,13 +6520,21 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GXX" = yes; then + if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -6050,64 +6552,84 @@ if test "$_lt_caught_CXX_error" != yes; then fi esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -6117,7 +6639,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6145,57 +6667,58 @@ if test "$_lt_caught_CXX_error" != yes; then # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6206,6 +6729,34 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_DARWIN_LINKER_FEATURES($1) ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + dgux*) case $cc_basename in ec++*) @@ -6241,14 +6792,14 @@ if test "$_lt_caught_CXX_error" != yes; then ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default @@ -6260,7 +6811,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6269,11 +6820,11 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no @@ -6283,15 +6834,15 @@ if test "$_lt_caught_CXX_error" != yes; then ;; hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi @@ -6317,13 +6868,13 @@ if test "$_lt_caught_CXX_error" != yes; then aCC*) case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists @@ -6334,20 +6885,20 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -6362,22 +6913,22 @@ if test "$_lt_caught_CXX_error" != yes; then interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -6386,17 +6937,17 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; @@ -6409,8 +6960,8 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6419,10 +6970,10 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. @@ -6436,59 +6987,59 @@ if test "$_lt_caught_CXX_error" != yes; then # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -6502,18 +7053,18 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) @@ -6521,10 +7072,10 @@ if test "$_lt_caught_CXX_error" != yes; then *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on @@ -6582,22 +7133,17 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=yes ;; - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else @@ -6613,9 +7159,9 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using @@ -6633,17 +7179,17 @@ if test "$_lt_caught_CXX_error" != yes; then cxx*) case $host in osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac @@ -6658,27 +7204,27 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support @@ -6718,9 +7264,9 @@ if test "$_lt_caught_CXX_error" != yes; then # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -6728,7 +7274,7 @@ if test "$_lt_caught_CXX_error" != yes; then solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. + # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; @@ -6745,42 +7291,42 @@ if test "$_lt_caught_CXX_error" != yes; then ;; gcx*) # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else - # g++ 2.7 appears to require `-G' NOT `-shared' on this + # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi @@ -6789,52 +7335,52 @@ if test "$_lt_caught_CXX_error" != yes; then ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" + '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; @@ -6865,10 +7411,10 @@ if test "$_lt_caught_CXX_error" != yes; then esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -6895,7 +7441,7 @@ if test "$_lt_caught_CXX_error" != yes; then lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes +fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG @@ -6917,13 +7463,14 @@ AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF + # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose @@ -7007,13 +7554,13 @@ if AC_TRY_EVAL(ac_compile); then pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in + case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. - if test $p = "-L" || - test $p = "-R"; then + if test x-L = "$p" || + test x-R = "$p"; then prev=$p continue fi @@ -7029,16 +7576,16 @@ if AC_TRY_EVAL(ac_compile); then case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in + if test no = "$pre_test_object_deps_done"; then + case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being @@ -7046,9 +7593,9 @@ if AC_TRY_EVAL(ac_compile); then esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" + _LT_TAGVAR(postdeps, $1)=$prev$p else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= @@ -7063,15 +7610,15 @@ if AC_TRY_EVAL(ac_compile); then continue fi - if test "$pre_test_object_deps_done" = no; then + if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" + _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" + _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi @@ -7102,51 +7649,6 @@ interix[[3-9]]*) _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; esac ]) @@ -7155,7 +7657,7 @@ case " $_LT_TAGVAR(postdeps, $1) " in esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) @@ -7175,10 +7677,10 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1], # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test "X$F77" = "Xno"; then +if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi @@ -7215,7 +7717,7 @@ _LT_TAGVAR(objext, $1)=$objext # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then +if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7237,7 +7739,7 @@ if test "$_lt_disable_F77" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} @@ -7251,21 +7753,25 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7273,11 +7779,11 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7294,9 +7800,9 @@ if test "$_lt_disable_F77" != yes; then fi # test -n "$compiler" GCC=$lt_save_GCC - CC="$lt_save_CC" - CFLAGS="$lt_save_CFLAGS" -fi # test "$_lt_disable_F77" != yes + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG @@ -7306,11 +7812,11 @@ AC_LANG_POP # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) -if test -z "$FC" || test "X$FC" = "Xno"; then +if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi @@ -7347,7 +7853,7 @@ _LT_TAGVAR(objext, $1)=$objext # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then +if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7369,7 +7875,7 @@ if test "$_lt_disable_FC" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} @@ -7385,21 +7891,25 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7407,11 +7917,11 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7431,7 +7941,7 @@ if test "$_lt_disable_FC" != yes; then GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS -fi # test "$_lt_disable_FC" != yes +fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG @@ -7441,7 +7951,7 @@ AC_LANG_POP # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE @@ -7475,7 +7985,7 @@ CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. @@ -7512,7 +8022,7 @@ CFLAGS=$lt_save_CFLAGS # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE @@ -7546,7 +8056,7 @@ CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. @@ -7583,7 +8093,7 @@ CFLAGS=$lt_save_CFLAGS # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE @@ -7599,7 +8109,7 @@ _LT_TAGVAR(objext, $1)=$objext lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" +lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER @@ -7609,7 +8119,7 @@ _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. -lt_save_CC="$CC" +lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= @@ -7638,7 +8148,7 @@ AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) @@ -7749,7 +8259,7 @@ lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue + test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -7766,9 +8276,9 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break + test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then + if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi @@ -7792,27 +8302,7 @@ dnl AC_DEFUN([LT_AC_PROG_SED], []) # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false @@ -7836,102 +8326,9 @@ _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES -# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) -# ------------------------------------------------------ -# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and -# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. -m4_defun([_LT_PROG_FUNCTION_REPLACE], -[dnl { -sed -e '/^$1 ()$/,/^} # $1 /c\ -$1 ()\ -{\ -m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) -} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: -]) - - -# _LT_PROG_REPLACE_SHELLFNS -# ------------------------- -# Replace existing portable implementations of several shell functions with -# equivalent extended shell implementations where those features are available.. -m4_defun([_LT_PROG_REPLACE_SHELLFNS], -[if test x"$xsi_shell" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl - func_split_long_opt_name=${1%%=*} - func_split_long_opt_arg=${1#*=}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) - - _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) - - _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) - - _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) -fi - -if test x"$lt_shell_append" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) - - _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl - func_quote_for_eval "${2}" -dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ - eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) -fi -]) - # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- -# Determine which file name conversion functions should be used by +# Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 index 5d9acd8..94b0829 100644 --- a/m4/ltoptions.m4 +++ b/m4/ltoptions.m4 @@ -1,14 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 7 ltoptions.m4 +# serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -29,7 +29,7 @@ m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl + [m4_warning([Unknown $1 option '$2'])])[]dnl ]) @@ -75,13 +75,15 @@ m4_if([$1],[LT_INIT],[ dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS @@ -112,7 +114,7 @@ AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) +put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -148,7 +150,7 @@ AU_DEFUN([AC_LIBTOOL_WIN32_DLL], _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) +put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -157,9 +159,9 @@ dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], @@ -172,14 +174,14 @@ AC_ARG_ENABLE([shared], *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) @@ -211,9 +213,9 @@ dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], @@ -226,14 +228,14 @@ AC_ARG_ENABLE([static], *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) @@ -265,9 +267,9 @@ dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], @@ -280,14 +282,14 @@ AC_ARG_ENABLE([fast-install], *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) @@ -304,14 +306,14 @@ AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) +the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) +the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -319,11 +321,64 @@ dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + # _LT_WITH_PIC([MODE]) # -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], @@ -334,19 +389,17 @@ m4_define([_LT_WITH_PIC], *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC @@ -359,7 +412,7 @@ AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) +put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 index 9000a05..48bc934 100644 --- a/m4/ltsugar.m4 +++ b/m4/ltsugar.m4 @@ -1,6 +1,7 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives @@ -33,7 +34,7 @@ m4_define([_lt_join], # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. +# Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], @@ -44,7 +45,7 @@ m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 index 07a8602..fa04b52 100644 --- a/m4/ltversion.m4 +++ b/m4/ltversion.m4 @@ -1,6 +1,6 @@ # ltversion.m4 -- version numbers -*- Autoconf -*- # -# Copyright (C) 2004 Free Software Foundation, Inc. +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives @@ -9,15 +9,15 @@ # @configure_input@ -# serial 3337 ltversion.m4 +# serial 4179 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.2]) -m4_define([LT_PACKAGE_REVISION], [1.3337]) +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.2' -macro_revision='1.3337' +[macro_version='2.4.6' +macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 index c573da9..c6b26f8 100644 --- a/m4/lt~obsolete.m4 +++ b/m4/lt~obsolete.m4 @@ -1,6 +1,7 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives @@ -11,7 +12,7 @@ # These exist entirely to fool aclocal when bootstrapping libtool. # -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # @@ -25,7 +26,7 @@ # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until diff --git a/m4/nls.m4 b/m4/nls.m4 index 7967cc2..8f8a147 100644 --- a/m4/nls.m4 +++ b/m4/nls.m4 @@ -1,5 +1,6 @@ -# nls.m4 serial 3 (gettext-0.15) -dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2013 Free Software Foundation, +dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -17,15 +18,15 @@ dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. -AC_PREREQ(2.50) +AC_PREREQ([2.50]) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS - AC_ARG_ENABLE(nls, + AC_ARG_ENABLE([nls], [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) - AC_MSG_RESULT($USE_NLS) - AC_SUBST(USE_NLS) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) ]) diff --git a/m4/po.m4 b/m4/po.m4 index 00133ef..1c70b6c 100644 --- a/m4/po.m4 +++ b/m4/po.m4 @@ -1,5 +1,5 @@ -# po.m4 serial 13 (gettext-0.15) -dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +# po.m4 serial 21 (gettext-0.18.3) +dnl Copyright (C) 1995-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -17,16 +17,21 @@ dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. -AC_PREREQ(2.50) +AC_PREREQ([2.60]) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl - AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl AC_REQUIRE([AM_NLS])dnl + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) + dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. @@ -37,7 +42,7 @@ AC_DEFUN([AM_PO_SUBDIRS], [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) - AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) dnl Test whether it is GNU msgfmt >= 0.15. changequote(,)dnl @@ -84,6 +89,10 @@ changequote([,])dnl test -n "$localedir" || localedir='${datadir}/locale' AC_SUBST([localedir]) + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + AC_CONFIG_COMMANDS([po-directories], [[ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" @@ -94,7 +103,7 @@ changequote([,])dnl case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. @@ -110,7 +119,8 @@ changequote([,])dnl if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" - cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration @@ -121,12 +131,12 @@ changequote([,])dnl test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` - # Hide the ALL_LINGUAS assigment from automake < 1.5. + # Hide the ALL_LINGUAS assignment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. - # Hide the ALL_LINGUAS assigment from automake < 1.5. + # Hide the ALL_LINGUAS assignment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES @@ -218,7 +228,7 @@ AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], changequote(,)dnl # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. @@ -246,6 +256,7 @@ EOT fi # A sed script that extracts the value of VARIABLE from a Makefile. + tab=`printf '\t'` sed_x_variable=' # Test if the hold space is empty. x @@ -253,9 +264,9 @@ s/P/P/ x ta # Yes it was empty. Look if we have the expected variable definition. -/^[ ]*VARIABLE[ ]*=/{ +/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=/{ # Seen the first line of the variable definition. - s/^[ ]*VARIABLE[ ]*=// + s/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=// ba } bd @@ -307,7 +318,7 @@ changequote([,])dnl sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'` ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"` fi - # Hide the ALL_LINGUAS assigment from automake < 1.5. + # Hide the ALL_LINGUAS assignment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) @@ -397,14 +408,15 @@ changequote([,])dnl fi sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp" + tab=`printf '\t'` if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" <, 1996. -AC_PREREQ(2.50) +AC_PREREQ([2.50]) # Search path for a program which passes the given test. @@ -27,15 +27,14 @@ AC_DEFUN([AM_PATH_PROG_WITH_TEST], # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } fi # Find out how to test for executable files. Don't use a zero-byte file, @@ -55,7 +54,7 @@ rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) -AC_CACHE_VAL(ac_cv_path_$1, +AC_CACHE_VAL([ac_cv_path_$1], [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. @@ -84,9 +83,9 @@ ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then - AC_MSG_RESULT([$]$1) + AC_MSG_RESULT([$][$1]) else - AC_MSG_RESULT(no) + AC_MSG_RESULT([no]) fi -AC_SUBST($1)dnl +AC_SUBST([$1])dnl ]) diff --git a/man/Makefile.am b/man/Makefile.am deleted file mode 100644 index a364ff3..0000000 --- a/man/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -man8_MANS = cryptsetup.8 - -if VERITYSETUP -man8_MANS += veritysetup.8 -endif - -if REENCRYPT -man8_MANS += cryptsetup-reencrypt.8 -endif - -EXTRA_DIST = cryptsetup.8 veritysetup.8 cryptsetup-reencrypt.8 diff --git a/man/Makefile.in b/man/Makefile.in deleted file mode 100644 index b2e9bf3..0000000 --- a/man/Makefile.in +++ /dev/null @@ -1,559 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -@VERITYSETUP_TRUE@am__append_1 = veritysetup.8 -@REENCRYPT_TRUE@am__append_2 = cryptsetup-reencrypt.8 -subdir = man -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -man8dir = $(mandir)/man8 -am__installdirs = "$(DESTDIR)$(man8dir)" -NROFF = nroff -MANS = $(man8_MANS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CRYPTO_CFLAGS = @CRYPTO_CFLAGS@ -CRYPTO_LIBS = @CRYPTO_LIBS@ -CRYPTO_STATIC_LIBS = @CRYPTO_STATIC_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DEVMAPPER_CFLAGS = @DEVMAPPER_CFLAGS@ -DEVMAPPER_LIBS = @DEVMAPPER_LIBS@ -DEVMAPPER_STATIC_CFLAGS = @DEVMAPPER_STATIC_CFLAGS@ -DEVMAPPER_STATIC_LIBS = @DEVMAPPER_STATIC_LIBS@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLLIBS = @INTLLIBS@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCRYPTSETUP_VERSION = @LIBCRYPTSETUP_VERSION@ -LIBCRYPTSETUP_VERSION_INFO = @LIBCRYPTSETUP_VERSION_INFO@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -NSS_CFLAGS = @NSS_CFLAGS@ -NSS_LIBS = @NSS_LIBS@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OPENSSL_STATIC_CFLAGS = @OPENSSL_STATIC_CFLAGS@ -OPENSSL_STATIC_LIBS = @OPENSSL_STATIC_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POPT_LIBS = @POPT_LIBS@ -POSUB = @POSUB@ -PWQUALITY_CFLAGS = @PWQUALITY_CFLAGS@ -PWQUALITY_LIBS = @PWQUALITY_LIBS@ -PWQUALITY_STATIC_LIBS = @PWQUALITY_STATIC_LIBS@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -UUID_LIBS = @UUID_LIBS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -man8_MANS = cryptsetup.8 $(am__append_1) $(am__append_2) -EXTRA_DIST = cryptsetup.8 veritysetup.8 cryptsetup-reencrypt.8 -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu man/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-man8: $(man8_MANS) - @$(NORMAL_INSTALL) - @list1='$(man8_MANS)'; \ - list2=''; \ - test -n "$(man8dir)" \ - && test -n "`echo $$list1$$list2`" \ - || exit 0; \ - echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ - { for i in $$list1; do echo "$$i"; done; \ - if test -n "$$list2"; then \ - for i in $$list2; do echo "$$i"; done \ - | sed -n '/\.8[a-z]*$$/p'; \ - fi; \ - } | while read p; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; echo "$$p"; \ - done | \ - sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ - sed 'N;N;s,\n, ,g' | { \ - list=; while read file base inst; do \ - if test "$$base" = "$$inst"; then list="$$list $$file"; else \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ - fi; \ - done; \ - for i in $$list; do echo "$$i"; done | $(am__base_list) | \ - while read files; do \ - test -z "$$files" || { \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ - done; } - -uninstall-man8: - @$(NORMAL_UNINSTALL) - @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ - files=`{ for i in $$list; do echo "$$i"; done; \ - } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(MANS) -installdirs: - for dir in "$(DESTDIR)$(man8dir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-man - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: install-man8 - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-man - -uninstall-man: uninstall-man8 - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - cscopelist-am ctags-am distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-man8 install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am tags-am uninstall uninstall-am uninstall-man \ - uninstall-man8 - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/man/Makemodule.am b/man/Makemodule.am new file mode 100644 index 0000000..3f68441 --- /dev/null +++ b/man/Makemodule.am @@ -0,0 +1,15 @@ +EXTRA_DIST += man/cryptsetup.8 man/integritysetup.8 man/veritysetup.8 man/cryptsetup-reencrypt.8 + +man8_MANS += man/cryptsetup.8 + +if VERITYSETUP +man8_MANS += man/veritysetup.8 +endif + +if REENCRYPT +man8_MANS += man/cryptsetup-reencrypt.8 +endif + +if INTEGRITYSETUP +man8_MANS += man/integritysetup.8 +endif diff --git a/man/cryptsetup-reencrypt.8 b/man/cryptsetup-reencrypt.8 index bfb7e23..3dbb6e1 100644 --- a/man/cryptsetup-reencrypt.8 +++ b/man/cryptsetup-reencrypt.8 @@ -1,4 +1,4 @@ -.TH CRYPTSETUP-REENCRYPT "8" "January 2015" "cryptsetup-reencrypt" "Maintenance Commands" +.TH CRYPTSETUP-REENCRYPT "8" "January 2019" "cryptsetup-reencrypt" "Maintenance Commands" .SH NAME cryptsetup-reencrypt - tool for offline LUKS device re-encryption .SH SYNOPSIS @@ -14,18 +14,20 @@ unclocked by passphrase), \fBcipher\fR, \fBcipher mode\fR. Cryptsetup-reencrypt reencrypts data on LUKS device in-place. During reencryption process the LUKS device is marked unavailable. +\fINOTE\fR: If you're looking for LUKS2 online reencryption manual please read cryptsetup(8) +man page instead (see reencrypt action). This page is for legacy offline reencryption +utility only. + \fIWARNING\fR: The cryptsetup-reencrypt program is not resistant to hardware -or kernel failures during reencryption (you can lose you data in this case). +or kernel failures during reencryption (you can lose your data in this case). \fIALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL.\fR .br -\fITHIS TOOL IS EXPERIMENTAL.\fR - The reencryption can be temporarily suspended (by TERM signal or by using ctrl+c) but you need to retain temporary files named LUKS-.[log|org|new]. LUKS device is unavailable until reencryption is finished though. -Current working directory must by writable and temporary +Current working directory must be writable and temporary files created during reencryption must be present. For more info about LUKS see cryptsetup(8). @@ -36,68 +38,109 @@ To start (or continue) re-encryption for use: .PP \fIcryptsetup-reencrypt\fR -\fB\fR can be [\-\-batch-mode, \-\-block-size, \-\-cipher, \-\-debug, -\-\-device-size, \-\-hash, \-\-iter-time, \-\-use-random | \-\-use-urandom, -\-\-keep-key, \-\-key-size, \-\-key-file, \-\-key-slot, \-\-keyfile-offset, -\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-verbose, \-\-write-log] +\fB\fR can be [\-\-batch-mode, \-\-block-size, \-\-cipher | \-\-keep-key, +\-\-debug, \-\-device-size, \-\-hash, \-\-header, \-\-iter-time | \-\-pbkdf\-force\-iterations, +\-\-key-file, \-\-key-size, \-\-key-slot, \-\-keyfile-offset, \-\-keyfile-size, +\-\-master\-key\-file, \-\-tries, \-\-pbkdf, \-\-pbkdf\-memory, \-\-pbkdf\-parallel, +\-\-progress-frequency, \-\-use-directio, \-\-use-random | \-\-use-urandom, \-\-use-fsync, +\-\-uuid, \-\-verbose, \-\-write-log] -To encrypt data on (not yet encrypted) device, use \fI\-\-new\fR with combination -with \fI\-\-reduce-device-size\fR. +To encrypt data on (not yet encrypted) device, use \fI\-\-new\fR in combination +with \fI\-\-reduce-device-size\fR or with \fI\-\-header\fR option for detached header. To remove encryption from device, use \fI\-\-decrypt\fR. For detailed description of encryption and key file options see \fIcryptsetup(8)\fR man page. .TP -.B "\-\-verbose, \-v" -Print more information on command execution. +.B "\-\-batch-mode, \-q" +Suppresses all warnings and reencryption progress output. +.TP +.B "\-\-block-size, \-B \fIvalue\fR" +Use re-encryption block size of in MiB. + +Values can be between 1 and 64 MiB. +.TP +.B "\-\-cipher, \-c" \fI\fR +Set the cipher specification string. .TP .B "\-\-debug" Run in debug mode with full diagnostic logs. Debug output lines are always prefixed by '#'. .TP -.B "\-\-cipher, \-c" \fI\fR -Set the cipher specification string. +.B "\-\-decrypt" +Remove encryption (decrypt already encrypted device and remove LUKS header). + +\fBWARNING:\fR This is destructive operation and cannot be reverted. .TP -.B "\-\-key-size, \-s \fI\fR" -Set key size in bits. The argument has to be a multiple of 8. +.B "\-\-device-size \fIsize[units]\fR" +Instead of real device size, use specified value. -The possible key-sizes are limited by the cipher and mode used. +It means that only specified area (from the start of the device +to the specified size) will be reencrypted. -If you are increasing key size, there must be enough space in the LUKS header -for enlarged keyslots (data offset must be large enough) or reencryption -cannot be performed. +If no unit suffix is specified, the size is in bytes. -If there is not enough space for keyslots with new key size, -you can destructively shrink device with \-\-reduce-device-size option. +Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB) +for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale). + +\fBWARNING:\fR This is destructive operation. .TP .B "\-\-hash, \-h \fI\fR" -Specifies the hash used in the LUKS key setup scheme and volume key digest. +Specifies the hash used in the LUKS1 key setup scheme and volume key digest. \fBNOTE:\fR if this parameter is not specified, default hash algorithm is always used -for new device header. +for new LUKS1 device header. + +\fBNOTE:\fR with LUKS2 format this option is only relevant when new keyslot pbkdf algorithm +is set to PBKDF2 (see \fI\-\-pbkdf\fR). +.TP +.B "\-\-header\fR \fI\fR" +Use a detached (separated) metadata device or file where the +LUKS header is stored. This option allows one to store ciphertext +and LUKS header on different devices. + +\fBWARNING:\fR There is no check whether the ciphertext device specified +actually belongs to the header given. +If used with \fI\-\-new\fR option, the header file will created (or overwritten). +Use with care. .TP .B "\-\-iter-time, \-i \fI\fR" The number of milliseconds to spend with PBKDF2 passphrase processing for the new LUKS header. .TP -.B "\-\-use-random" -.TP -.B "\-\-use-urandom" -Define which kernel random number generator will be used to create the volume key. +.B "\-\-keep-key" +Do not change encryption key, just reencrypt the LUKS header and keyslots. + +This option can be combined only with \fI\-\-hash\fR, \fI\-\-iter-time\fR, +\fI\-\-pbkdf\-force\-iterations\fR, \fI\-\-pbkdf\fR (LUKS2 only), +\fI\-\-pbkdf\-memory\fR (Argon2i/id and LUKS2 only) and \fI\-\-pbkdf\-parallel\fR +(Argon2i/id and LUKS2 only) options. .TP .B "\-\-key-file, \-d \fIname\fR" Read the passphrase from file. -\fBWARNING:\fR \-\-key-file option can be used only if there only one active keyslot, +\fBWARNING:\fR \-\-key-file option can be used only if there is only one active keyslot, or alternatively, also if \-\-key-slot option is specified (then all other keyslots will be disabled in new LUKS device). If this option is not used, cryptsetup-reencrypt will ask for all active keyslot passphrases. .TP -.B "\-\-key-slot, \-S <0-7>" -Specify which key slot is used. +.B "\-\-key-size, \-s \fI\fR" +Set key size in bits. The argument has to be a multiple of 8. + +The possible key-sizes are limited by the cipher and mode used. + +If you are increasing key size, there must be enough space in the LUKS header +for enlarged keyslots (data offset must be large enough) or reencryption +cannot be performed. + +If there is not enough space for keyslots with new key size, +you can destructively shrink device with \-\-reduce-device-size option. +.TP +.B "\-\-key-slot, \-S <0-MAX>" +Specify which key slot is used. For LUKS1, max keyslot number is 7. For LUKS2, it's 31. \fBWARNING:\fR All other keyslots will be disabled if this option is used. .TP @@ -109,34 +152,39 @@ Read a maximum of \fIvalue\fR bytes from the key file. Default is to read the whole file up to the compiled-in maximum. .TP -.B "\-\-keep-key" -Do not change encryption key, just reencrypt the LUKS header and keyslots. - -This option can be combined only with \fI\-\-hash\fR or \fI\-\-iter-time\fR -options. -.TP -.B "\-\-tries, \-T" -Number of retries for invalid passphrase entry. +.B "\-\-master\-key\-file" +Use new volume (master) key stored in a file. .TP -.B "\-\-block-size, \-B \fIvalue\fR" -Use re-encryption block size of in MiB. - -Values can be between 1 and 64 MiB. -.TP -.B "\-\-device-size \fIsize[units]\fR" -Instead of real device size, use specified value. - -It means that only specified area (from the start of the device -to the specified size) will be reencrypted. - -\fBWARNING:\fR This is destructive operation. +.B "\-\-new, \-N" +Create new header (encrypt not yet encrypted device). -If no unit suffix is specified, the size is in bytes. +This option must be used together with \-\-reduce-device-size. -Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB) -for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale). +\fBWARNING:\fR This is destructive operation and cannot be reverted. +.TP +.B "\-\-pbkdf" +Set Password-Based Key Derivation Function (PBKDF) algorithm for LUKS keyslot. +The PBKDF can be: \fIpbkdf2\fR, \fIargon2i\fR for Argon2i or \fIargon2id\fR for Argon2id. -\fBWARNING:\fR This is destructive operation. +For LUKS1, only \fIpbkdf2\fR is accepted (no need to use this option). +.TP +.B "\-\-pbkdf\-force\-iterations " +Avoid PBKDF benchmark and set time cost (iterations) directly. +.TP +.B "\-\-pbkdf\-memory " +Set the memory cost for PBKDF (for Argon2i/id the number represents kilobytes). +Note that it is maximal value, PBKDF benchmark or available physical memory +can decrease it. +This option is not available for PBKDF2. +.TP +.B "\-\-pbkdf\-parallel " +Set the parallel cost for PBKDF (number of threads, up to 4). +Note that it is maximal value, it is decreased automatically if +CPU online count is lower. +This option is not available for PBKDF2. +.TP +.B "\-\-progress-frequency " +Print separate line every with reencryption progress. .TP .B "\-\-reduce-device-size \fIsize[units]\fR" Enlarge data offset to specified value by shrinking device size. @@ -150,22 +198,20 @@ partition (so last sectors contains no data). For units suffix see \-\-device-size parameter description. -\fBWARNING:\fR This is destructive operation and cannot be reverted. -Use with extreme care - shrinked filesystems are usually unrecoverable. - You cannot shrink device more than by 64 MiB (131072 sectors). -.TP -.B "\-\-new, N" -Create new header (encrypt not yet encrypted device). - -This option must be used together with \-\-reduce-device-size. \fBWARNING:\fR This is destructive operation and cannot be reverted. +Use with extreme care - shrunk filesystems are usually unrecoverable. .TP -.B "\-\-decrypt" -Remove encryption (decrypt already encrypted device and remove LUKS header). +.B "\-\-tries, \-T" +Number of retries for invalid passphrase entry. +.TP +.B "\-\-type " +Use only while encrypting not yet encrypted device (see \-\-new). -\fBWARNING:\fR This is destructive operation and cannot be reverted. +Specify LUKS version when performing in-place encryption. If the parameter +is omitted default value (LUKS1) is used. Type may be one of: \fBluks\fR (default), +\fBluks1\fR or \fBluks2\fR. .TP .B "\-\-use-directio" Use direct-io (O_DIRECT) for all read/write data operations related @@ -178,15 +224,27 @@ operations (e.g. in virtual environments). Use fsync call after every written block. This applies for reencryption log files as well. .TP -.B "\-\-write-log" -Update log file after every block write. This can slow down reencryption -but will minimize data loss in the case of system crash. +.B "\-\-use-random" .TP -.B "\-\-batch-mode, \-q" -Suppresses all warnings and reencryption progress output. +.B "\-\-use-urandom" +Define which kernel random number generator will be used to create the volume key. +.TP +.B "\-\-uuid" \fI\fR +Use only while resuming an interrupted decryption process (see \-\-decrypt). + +To find out what \fI\fR to pass look for temporary files LUKS-.[|log|org|new] +of the interrupted decryption process. +.TP +.B "\-\-verbose, \-v" +Print more information on command execution. .TP .B "\-\-version" Show the program version. +.TP +.B "\-\-write-log" +Update log file after every block write. This can slow down reencryption +but will minimize data loss in the case of system crash. + .SH RETURN CODES Cryptsetup-reencrypt returns 0 on success and a non-zero value on error. @@ -227,9 +285,9 @@ Please attach the output of the failed command with the .SH AUTHORS Cryptsetup-reencrypt was written by Milan Broz . .SH COPYRIGHT -Copyright \(co 2012-2015 Milan Broz +Copyright \(co 2012-2020 Milan Broz .br -Copyright \(co 2012-2013 Red Hat, Inc. +Copyright \(co 2012-2020 Red Hat, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index 16ecec0..bc3fff6 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -1,4 +1,4 @@ -.TH CRYPTSETUP "8" "December 2013" "cryptsetup" "Maintenance Commands" +.TH CRYPTSETUP "8" "January 2019" "cryptsetup" "Maintenance Commands" .SH NAME cryptsetup - manage plain dm-crypt and LUKS encrypted volumes .SH SYNOPSIS @@ -12,7 +12,7 @@ and can hence offer more features than plain dm-crypt. On the other hand, the header is visible and vulnerable to damage. In addition, cryptsetup provides limited support for the use of -historic loopaes volumes and for TrueCrypt compatible volumes. +loop-AES volumes, TrueCrypt, VeraCrypt and BitLocker compatible volumes. .SH PLAIN DM-CRYPT OR LUKS? .PP @@ -29,12 +29,12 @@ to be mentioned here. \fBBackup:\fR Storage media die. Encryption has no influence on that. Backup is mandatory for encrypted data as well, if the data has any -worth. See the Cryptsetup FAQ for advice on how to do backup of an +worth. See the Cryptsetup FAQ for advice on how to do a backup of an encrypted volume. \fBCharacter encoding:\fR If you enter a passphrase with special symbols, the passphrase can change -depending character encoding. Keyboard settings can also change, +depending on character encoding. Keyboard settings can also change, which can make blind input hard or impossible. For example, switching from some ASCII 8-bit variant to UTF-8 can lead to a different binary encoding and hence different @@ -57,10 +57,10 @@ secure wiping by just overwriting header and key-slot area. it is a very good idea to wipe filesystem signatures, data, etc. before creating a LUKS or plain dm-crypt container on it. For a quick removal of filesystem signatures, use "wipefs". Take care -though that this may not remove everything. In particular md (RAID) +though that this may not remove everything. In particular, MD RAID signatures at the end of a device may survive. It also does not remove data. For a full wipe, overwrite the whole partition before -container creation. If you do not know how to to that, the +container creation. If you do not know how to do that, the cryptsetup FAQ describes several options. .SH BASIC COMMANDS @@ -70,8 +70,8 @@ The following are valid actions for all supported device types. .IP Opens (creates a mapping with) backed by device . -Device type can be \fIplain\fR, \fIluks\fR (default), \fIloopaes\fR -or \fItcrypt\fR. +Device type can be \fIplain\fR, \fIluks\fR (default), \fIluks1\fR, \fIluks2\fR, +\fIloopaes\fR or \fItcrypt\fR. For backward compatibility there are \fBopen\fR command aliases: @@ -84,6 +84,8 @@ For backward compatibility there are \fBopen\fR command aliases: \fBloopaesOpen\fR: open \-\-type loopaes .br \fBtcryptOpen\fR: open \-\-type tcrypt +.br +\fBbitlkOpen\fR: open \-\-type bitlk \fB\fR are type specific and are described below for individual device types. For \fBcreate\fR, the order of the @@ -98,6 +100,9 @@ For backward compatibility there are \fBclose\fR command aliases: \fBremove\fR, \fBplainClose\fR, \fBluksClose\fR, \fBloopaesClose\fR, \fBtcryptClose\fR (all behaves exactly the same, device type is determined automatically from active device). + +\fB\fR can be [\-\-deferred] + .PP \fIstatus\fR .IP @@ -107,10 +112,95 @@ Reports the status for the mapping . .IP Resizes an active mapping . -If \-\-size (in sectors) is not specified, the size of the -underlying block device is used. Note that this does not -change the raw device geometry, it just changes how many -sectors of the raw device are represented in the mapped device. +If \-\-size (in 512-bytes sectors) or \-\-device\-size are not specified, +the size is computed from the underlying device. For LUKS it is the size +of the underlying device without the area reserved for LUKS header +(see data payload offset in \fBluksDump\fR command). +For plain crypt device, the whole device size is used. + +Note that this does not change the raw device geometry, it just +changes how many sectors of the raw device are represented +in the mapped device. + +If cryptsetup detected volume key for active device loaded in kernel keyring +service, resize action would first try to retrieve +the key using a token and only if it failed it'd ask for a passphrase +to unlock a keyslot (LUKS) or to derive a volume key again (plain mode). +The kernel keyring is used by default for LUKS2 devices. + +With LUKS2 device additional \fB\fR can be [\-\-token\-id, \-\-token\-only, +\-\-key\-slot, \-\-key\-file, \-\-keyfile\-size, \-\-keyfile\-offset, \-\-timeout, +\-\-disable\-locks, \-\-disable\-keyring]. + +.PP +\fIrefresh\fR +.IP +Refreshes parameters of active mapping . + +Updates parameters of active device without need to deactivate the device +(and umount filesystem). Currently it supports parameters refresh on following +devices: LUKS1, LUKS2 (including authenticated encryption), plain crypt +and loopaes. + +Mandatory parametrs are identical to those of an open action for respective +device type. + +You may change following parameters on all devices \-\-perf\-same_cpu_crypt, +\-\-perf\-submit_from_crypt_cpus and \-\-allow\-discards. + +Refreshing device without any optional parameter will refresh the device +with default setting (respective to device type). + +\fBLUKS2 only:\fR + +\-\-integrity\-no\-journal parameter affects only LUKS2 devices with +underlying dm-integrity device. + +Adding option \-\-persistent stores any combination of device parameters +above in LUKS2 metadata (only after successful refresh operation). + +\-\-disable\-keyring parameter refreshes a device with volume key passed +in dm-crypt driver. + +.PP +\fIreencrypt\fR or --active-name [] +.IP +Run resilient reencryption (LUKS2 device only). + +There are 3 basic modes of operation: + +\(bu device reencryption (\fIreencrypt\fR) + +\(bu device encryption (\fIreencrypt\fR \-\-encrypt) + +\(bu device decryption (\fIreencrypt\fR \-\-decrypt) + + or --active-name is mandatory parameter. + +With parameter cryptsetup looks up active dm mapping. +If no active mapping is detected, it starts offline reencryption otherwise online +reencryption takes place. + +Reencryption process may be safely interrupted by a user via SIGTERM signal (ctrl+c). + +To resume already initialized or interrupted reencryption, just run the cryptsetup +\fIreencrypt\fR command again to continue the reencryption operation. +Reencryption may be resumed with different \-\-resilience or \-\-hotzone\-size unless +implicit datashift resilience mode is used (reencrypt \-\-encrypt with \-\-reduce-device-size +option). + +If the reencryption process was interrupted abruptly (reencryption process crash, system crash, poweroff) +it may require recovery. The recovery is currently run automatically on next activation (action \fIopen\fR) +when needed. + +Optional parameter takes effect only with \-\-encrypt option and it activates device +immediately after encryption initialization gets finished. That's useful when device needs to be ready +as soon as possible and mounted (used) before full data area encryption is completed. + +Action supports following additional \fB\fR [\-\-encrypt, \-\-decrypt, \-\-device\-size, +\-\-resilience, \-\-resilience-hash, \-\-hotzone-size, \-\-init\-only, \-\-resume\-only, +\-\-reduce\-device\-size]. + .SH PLAIN MODE Plain dm-crypt encrypts the device sector-by-sector with a single, non-salted hash of the passphrase. No checks @@ -128,8 +218,9 @@ The following are valid plain device type actions: Opens (creates a mapping with) backed by device . \fB\fR can be [\-\-hash, \-\-cipher, \-\-verify-passphrase, -\-\-key-file, \-\-keyfile-offset, \-\-key-size, \-\-offset, \-\-skip, \-\-size, -\-\-readonly, \-\-shared, \-\-allow-discards] +\-\-sector\-size, \-\-key-file, \-\-keyfile-offset, \-\-key-size, +\-\-offset, \-\-skip, \-\-size, \-\-readonly, \-\-shared, \-\-allow\-discards, +\-\-refresh] Example: 'cryptsetup open \-\-type plain /dev/sda10 e1' maps the raw encrypted device /dev/sda10 to the mapped (decrypted) device @@ -141,7 +232,7 @@ It adds a standardized header at the start of the device, a key-slot area directly behind the header and the bulk data area behind that. The whole set is called a 'LUKS container'. The device that a LUKS container resides on is called a 'LUKS device'. -For most purposes both terms can be used interchangeably. But +For most purposes, both terms can be used interchangeably. But note that when the LUKS header is at a nonzero offset in a device, then the device is not a LUKS device anymore, but has a LUKS container stored in it at an offset. @@ -153,6 +244,12 @@ are protected against brute-force and dictionary attacks by PBKDF2, which implements hash iteration and salting in one function. +LUKS2 is a new version of header format that allows additional +extensions like different PBKDF algorithm or authenticated encryption. +You can format device with LUKS2 header if you specify +\fI\-\-type luks2\fR in \fIluksFormat\fR command. +For activation, the format is already recognized automatically. + Each passphrase, also called a .B key in this document, is associated with one of 8 key-slots. @@ -160,13 +257,13 @@ Key operations that do not specify a slot affect the first slot that matches the supplied passphrase or the first empty slot if a new passphrase is added. -The \fB\fR parameter can be also specified by a LUKS UUID in the +The \fB\fR parameter can also be specified by a LUKS UUID in the format UUID=. Translation to real device name uses symlinks in /dev/disk/by-uuid directory. To specify a detached header, the \fB\-\-header\fR parameter can be used -in all LUKS commands and always takes precedence over positional \fB\fR -parameter. +in all LUKS commands and always takes precedence over the positional +\fB\fR parameter. The following are valid LUKS actions: @@ -178,21 +275,32 @@ either via prompting or via . Note that if the second argument is present, then the passphrase is taken from the file given there, without the need to use the \-\-key-file option. Also note that for both forms -of reading the passphrase from file you can +of reading the passphrase from a file you can give '-' as file name, which results in the passphrase being read from stdin and the safety-question being skipped. You can only call luksFormat on a LUKS device that is not mapped. +To use LUKS2, specify \fI\-\-type luks2\fR. + \fB\fR can be [\-\-hash, \-\-cipher, \-\-verify\-passphrase, \-\-key\-size, \-\-key\-slot, \-\-key\-file (takes precedence over optional second argument), \-\-keyfile\-offset, \-\-keyfile\-size, \-\-use\-random | \-\-use\-urandom, \-\-uuid, \-\-master\-key\-file, \-\-iter\-time, \-\-header, -\-\-force\-password]. +\-\-pbkdf\-force\-iterations, +\-\-force\-password, \-\-disable-locks]. + +For LUKS2, additional \fB\fR can be +[\-\-integrity, \-\-integrity\-no\-wipe, \-\-sector\-size, +\-\-label, \-\-subsystem, +\-\-pbkdf, \-\-pbkdf\-memory, \-\-pbkdf\-parallel, +\-\-disable\-locks, \-\-disable\-keyring, +\-\-luks2\-metadata\-size, \-\-luks2\-keyslots\-size, +\-\-keyslot\-cipher, \-\-keyslot\-key\-size]. \fBWARNING:\fR Doing a luksFormat on an existing LUKS container will -make all data the old container permanently irretrievable, unless +make all data the old container permanently irretrievable unless you have a header backup. .PP \fIopen\fR \-\-type luks @@ -201,16 +309,20 @@ you have a header backup. .IP Opens the LUKS device and sets up a mapping after successful verification of the supplied passphrase. -If the passphrase is not supplied via \-\-key-file, the command -prompts for it interactively. + +First, the passphrase is searched in LUKS tokens. If it's not +found in any token and also the passphrase is not supplied via \-\-key-file, +the command prompts for it interactively. \fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, \-\-keyfile\-size, \-\-readonly, \-\-test\-passphrase, -\-\-allow\-discards, \-\-header, \-\-key-slot, \-\-master\-key\-file]. +\-\-allow\-discards, \-\-header, \-\-key-slot, \-\-master\-key\-file, \-\-token\-id, +\-\-token\-only, \-\-disable\-keyring, \-\-disable\-locks, \-\-type, \-\-refresh, +\-\-serialize\-memory\-hard\-pbkdf]. .PP \fIluksSuspend\fR .IP -Suspends an active device (all IO operations will blocked +Suspends an active device (all IO operations will block and accesses to the device will wait indefinitely) and wipes the encryption key from kernel memory. Needs kernel 2.6.19 or later. @@ -221,39 +333,48 @@ the mapped device. \fBWARNING:\fR never suspend the device on which the cryptsetup binary resides. -\fB\fR can be [\-\-header]. +\fB\fR can be [\-\-header, \-\-disable\-locks]. .PP \fIluksResume\fR .IP Resumes a suspended device and reinstates the encryption key. Prompts interactively for a passphrase if \-\-key-file is not given. -\fB\fR can be [\-\-key\-file, \-\-keyfile\-size, \-\-header] +\fB\fR can be [\-\-key\-file, \-\-keyfile\-size, \-\-header, +\-\-disable\-keyring, \-\-disable\-locks, \-\-type] .PP \fIluksAddKey\fR [] .IP -adds a new passphrase. An existing passphrase must be supplied +Adds a new passphrase. An existing passphrase must be supplied interactively or via \-\-key-file. The new passphrase to be added can be specified interactively or read from the file given as positional argument. +\fBNOTE:\fR with \-\-unbound option the action creates new unbound +LUKS2 keyslot. The keyslot cannot be used for device activation. +If you don't pass new key via \-\-master\-key\-file option, +new random key is generated. Existing passphrase for any active keyslot +is not required. + \fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, \-\-keyfile\-size, \-\-new\-keyfile\-offset, \-\-new\-keyfile\-size, \-\-key\-slot, \-\-master\-key\-file, -\-\-iter\-time, \-\-force\-password, \-\-header]. +\-\-force\-password, \-\-header, \-\-disable\-locks, +\-\-iter-time, \-\-pbkdf, \-\-pbkdf\-force\-iterations, +\-\-unbound, \-\-type, \-\-keyslot\-cipher, \-\-keyslot\-key\-size]. .PP \fIluksRemoveKey\fR [] .IP Removes the supplied passphrase from the LUKS device. The passphrase to be removed can be specified interactively, -as positional argument or via \-\-key-file. +as the positional argument or via \-\-key-file. \fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, -\-\-keyfile\-size, \-\-header] +\-\-keyfile\-size, \-\-header, \-\-disable\-locks, \-\-type] \fBWARNING:\fR If you read the passphrase from stdin -(without further argument or with '-' as argument -to \-\-key\-file), batch-mode (\-q) will be implicitely +(without further argument or with '-' as an argument +to \-\-key\-file), batch-mode (\-q) will be implicitly switched on and no warning will be given when you remove the last remaining passphrase from a LUKS container. Removing the last passphrase makes the LUKS container permanently @@ -282,26 +403,59 @@ inaccessible. \fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, \-\-keyfile\-size, \-\-new\-keyfile\-offset, -\-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password, \-\-header]. +\-\-iter-time, \-\-pbkdf, \-\-pbkdf\-force\-iterations, +\-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password, \-\-header, +\-\-disable\-locks, \-\-type, \-\-keyslot\-cipher, \-\-keyslot\-key\-size]. +.PP +.PP +\fIluksConvertKey\fR +.IP +Converts an existing LUKS2 keyslot to new pbkdf parameters. The +passphrase for keyslot to be converted must be supplied interactively +or via \-\-key\-file. If no \-\-pbkdf parameters are specified LUKS2 +default pbkdf values will apply. + +If a keyslot is specified (via \-\-key\-slot), the passphrase for that +keyslot must be given. If no keyslot is specified and there is still +a free keyslot, then the new parameters will be put into a free +keyslot before the keyslot containing the old parameters is +purged. If there is no free keyslot, then the keyslot with the old +parameters is overwritten directly. + +\fBWARNING:\fR If a keyslot is overwritten, a media failure during +this operation can cause the overwrite to fail after the old +parameters have been wiped and make the LUKS container inaccessible. + +\fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, +\-\-keyfile\-size, \-\-key\-slot, \-\-header, \-\-disable\-locks, +\-\-iter-time, \-\-pbkdf, \-\-pbkdf\-force\-iterations, +\-\-pbkdf\-memory, \-\-pbkdf\-parallel, +\-\-keyslot\-cipher, \-\-keyslot\-key\-size]. .PP \fIluksKillSlot\fR .IP -Wipe the key-slot number from the LUKS device. A remaining -passphrase must be supplied, either interactively or via \-\-key-file. +Wipe the key-slot number from the LUKS device. Except running +in batch-mode (\-q) a remaining passphrase must be supplied, +either interactively or via \-\-key-file. This command can remove the last remaining key-slot, but requires an interactive confirmation when doing so. Removing the last passphrase makes a LUKS container permanently inaccessible. \fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, -\-\-keyfile\-size, \-\-header]. +\-\-keyfile\-size, \-\-header, \-\-disable\-locks, \-\-type]. \fBWARNING:\fR If you read the passphrase from stdin -(without further argument or with '-' as argument -to \-\-key-file), batch-mode (\-q) will be implicitely +(without further argument or with '-' as an argument +to \-\-key-file), batch-mode (\-q) will be implicitly switched on and no warning will be given when you remove the last remaining passphrase from a LUKS container. Removing the last passphrase makes the LUKS container permanently inaccessible. + +\fBNOTE:\fR If there is no passphrase provided (on stdin or through +\-\-key-file argument) and batch-mode (\-q) is active, the +key-slot is removed without any other warning. + .PP \fIerase\fR .br @@ -323,23 +477,31 @@ Set new UUID if \fI\-\-uuid\fR option is specified. Returns true, if is a LUKS device, false otherwise. Use option \-v to get human-readable feedback. 'Command successful.' means the device is a LUKS device. + +By specifying \-\-type you may query for specific LUKS version. .PP \fIluksDump\fR .IP Dump the header information of a LUKS device. If the \-\-dump\-master\-key option is used, the LUKS device master key is -dumped instead of the keyslot info. Beware that the master key cannot be -changed and can be used to decrypt the data stored in the LUKS container -without a passphrase and even without the LUKS header. This means -that if the master key is compromised, the whole device has to be -erased to prevent further access. Use this option carefully. - -In order to dump the master key, a passphrase has to be supplied, +dumped instead of the keyslot info. Together with \-\-master\-key\-file option, +master key is dumped to a file instead of standard output. Beware that the +master key cannot be changed without reencryption and can be used to decrypt +the data stored in the LUKS container without a passphrase and even without the +LUKS header. This means that if the master key is compromised, the whole device +has to be erased or reencrypted to prevent further access. Use this option carefully. + +To dump the master key, a passphrase has to be supplied, either interactively or via \-\-key\-file. +To dump unbound key (LUKS2 format only), \-\-unbound parameter, specific \-\-key-slot +id and proper passphrase has to be supplied, either interactively or via \-\-key\-file. +Optional \-\-master\-key\-file parameter enables unbound keyslot dump to a file. + \fB\fR can be [\-\-dump\-master\-key, \-\-key\-file, -\-\-keyfile\-offset, \-\-keyfile\-size, \-\-header]. +\-\-keyfile\-offset, \-\-keyfile\-size, \-\-header, \-\-disable\-locks, +\-\-master\-key\-file, \-\-type, \-\-unbound, \-\-key-slot]. \fBWARNING:\fR If \-\-dump\-master\-key is used with \-\-key\-file and the argument to \-\-key\-file is '-', no validation question @@ -370,12 +532,68 @@ from the specified file. Note: Using '-' as filename reads the header backup from a file named '-'. \fBWARNING:\fR Header and keyslots will be replaced, only -the passphrases from the backup will work afterwards. +the passphrases from the backup will work afterward. This command requires that the master key size and data offset of the LUKS header already on the device and of the header backup match. Alternatively, if there is no LUKS header on the device, the backup will also be written to it. +.PP +\fItoken\fR +.IP +Action \fIadd\fR creates new keyring token to enable auto-activation of the device. +For the auto-activation, the passphrase must be stored in keyring with the specified +description. Usually, the passphrase should be stored in \fIuser\fR or +\fIuser-session\fR keyring. +The \fItoken\fR command is supported only for LUKS2. + +For adding new keyring token, option \-\-key\-description is mandatory. +Also, new token is assigned to key slot specified with \-\-key\-slot option or to all +active key slots in the case \-\-key\-slot option is omitted. + +To remove existing token, specify the token ID which should be removed with +\-\-token\-id option. + +\fBWARNING:\fR The action \fItoken remove\fR removes any token type, not just \fIkeyring\fR +type from token slot specified by \-\-token\-id option. + +Action \fIimport\fR can store arbitrary valid token json in LUKS2 header. It may be passed via +standard input or via file passed in \-\-json\-file option. If you specify \-\-key\-slot then +successfully imported token is also assigned to the key slot. + +Action \fIexport\fR writes requested token json to a file passed with \-\-json\-file or +to standard output. + +\fB\fR can be [\-\-header, \-\-token\-id, \-\-key\-slot, \-\-key\-description, +\-\-disable\-locks, \-\-disable\-keyring, \-\-json\-file]. +.PP +\fIconvert\fR \-\-type +.IP +Converts the device between LUKS1 and LUKS2 format (if possible). +The conversion will not be performed if there is an additional LUKS2 feature or LUKS1 has +unsupported header size. + +Conversion (both directions) must be performed on inactive device. There must not be active +dm-crypt mapping established for LUKS header requested for conversion. + +\fB\-\-type\fR option is mandatory with following accepted values: \fIluks1\fR or \fIluks2\fR. + +\fBWARNING:\fR The \fIconvert\fR action can destroy the LUKS header in the case of a crash +during conversion or if a media error occurs. +Always create a header backup before performing this operation! + +\fB\fR can be [\-\-header, \-\-type]. +.PP +\fIconfig\fR +.IP +Set permanent configuration options (store to LUKS header). +The \fIconfig\fR command is supported only for LUKS2. + +The permanent options can be \fI\-\-priority\fR to set priority (normal, prefer, ignore) +for keyslot (specified by \fI\-\-key\-slot\fR) or \fI\-\-label\fR and \fI\-\-subsystem\fR. + +\fB\fR can be [\-\-priority, \-\-label, \-\-subsystem, \-\-key\-slot, \-\-header]. + .SH loop-AES EXTENSION cryptsetup supports mapping loop-AES encrypted partition using a compatibility mode. @@ -392,7 +610,7 @@ If the key file is encrypted with GnuPG, then you have to use gpg \-\-decrypt | cryptsetup loopaesOpen \-\-key\-file=\- -\fBWARNING:\fR The loop-AES extension cannot use direct input of key file +\fBWARNING:\fR The loop-AES extension cannot use the direct input of key file on real terminal because the keys are separated by end-of-line and only part of the multi-key file would be read. .br @@ -415,7 +633,7 @@ passphrase hashing (otherwise it is detected according to key size). \fB\fR can be [\-\-key\-file, \-\-key\-size, \-\-offset, \-\-skip, -\-\-hash, \-\-readonly, \-\-allow\-discards]. +\-\-hash, \-\-readonly, \-\-allow\-discards, \-\-refresh]. .PP See also section 7 of the FAQ and \fBhttp://loop-aes.sourceforge.net\fR for more information regarding loop-AES. @@ -439,11 +657,20 @@ Cryptsetup should recognize all header variants, except legacy cipher chains using LRW encryption mode with 64 bits encryption block (namely Blowfish in LRW mode is not recognized, this is limitation of kernel crypto API). -To recognize VeraCrypt device use \fB\-\-veracrypt\fR option. +To recognize a VeraCrypt device use the \fB\-\-veracrypt\fR option. VeraCrypt is just extension of TrueCrypt header with increased iteration count so unlocking can take quite a lot of time (in comparison with TCRYPT device). +To open a VeraCrypt device with a custom Personal Iteration Multiplier (PIM) +value, \fBadditionally to \-\-veracrypt \fR use either the +\fB\-\-veracrypt\-pim=\fR option to directly specify the PIM on the command- +line or use \fB\-\-veracrypt\-query\-pim\fR to be prompted for the PIM. + +The PIM value affects the number of iterations applied during key derivation. Please refer to +\fBhttps://www.veracrypt.fr/en/Personal%20Iterations%20Multiplier%20%28PIM%29.html\fR +for more detailed information. + \fBNOTE:\fR Activation with \fBtcryptOpen\fR is supported only for cipher chains using LRW or XTS encryption modes. @@ -453,17 +680,17 @@ and doesn't require superuser privilege. To map system device (device with boot loader where the whole encrypted system resides) use \fB\-\-tcrypt\-system\fR option. You can use partition device as the parameter (parameter must be real partition -device, not image in file), then only this partition is mapped. +device, not an image in a file), then only this partition is mapped. -If you have whole TCRYPT device as a file image and you want to map multiple +If you have the whole TCRYPT device as a file image and you want to map multiple partition encrypted with system encryption, please create loopback mapping with partitions first (\fBlosetup \-P\fR, see \fPlosetup(8)\fR man page for more info), and use loop partition as the device parameter. -If you use whole base device as parameter, one device for the whole system +If you use the whole base device as a parameter, one device for the whole system encryption is mapped. This mode is available only for backward compatibility with older cryptsetup versions which mapped TCRYPT system encryption -using whole device. +using the whole device. To use hidden header (and map hidden device, if available), use \fB\-\-tcrypt\-hidden\fR option. @@ -487,15 +714,15 @@ a mapping . \fB\fR can be [\-\-key\-file, \-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup, \-\-readonly, \-\-test\-passphrase, -\-\-allow-discards]. +\-\-allow-discards, \-\-veracrypt, \-\-veracrypt\-pim, \-\-veracrypt\-query\-pim]. -The keyfile parameter allows combination of file content with the +The keyfile parameter allows a combination of file content with the passphrase and can be repeated. Note that using keyfiles is compatible with TCRYPT and is different from LUKS keyfile logic. \fBWARNING:\fR Option \fB\-\-allow\-discards\fR cannot be combined with -option \fB\-\-tcrypt\-hidden\fR. For normal mapping it can cause -\fBdestruction of hidden volume\fR (hidden volume appears as unused space +option \fB\-\-tcrypt\-hidden\fR. For normal mapping, it can cause +the \fBdestruction of hidden volume\fR (hidden volume appears as unused space for outer volume so this space can be discarded). .PP @@ -514,14 +741,55 @@ to be erased to prevent further access. Use this option carefully. \fB\fR can be [\-\-dump\-master\-key, \-\-key\-file, \-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup]. -The keyfile parameter allows combination of file content with the +The keyfile parameter allows a combination of file content with the passphrase and can be repeated. .PP -See also \fBhttp://www.truecrypt.org\fR for more information regarding +See also \fBhttps://en.wikipedia.org/wiki/TrueCrypt\fR for more information regarding TrueCrypt. Please note that cryptsetup does not use TrueCrypt code, please report -all problems related to this compatibility extension to cryptsetup project. +all problems related to this compatibility extension to the cryptsetup project. + +.SH BITLK (Windows BitLocker-compatible) EXTENSION (EXPERIMENTAL) +cryptsetup supports mapping of BitLocker and BitLocker to Go encrypted partition +using a native Linux kernel API. +Header formatting and BITLK header changes are not supported, cryptsetup +never changes BITLK header on-device. + +\fBWARNING:\fR This extension is EXPERIMENTAL. + +BITLK extension requires kernel userspace crypto API to be available +(for details see TCRYPT section). + +Cryptsetup should recognize all BITLK header variants, except legacy +header used in Windows Vista systems and partially decrypted BitLocker devices. +Activation of legacy devices encrypted in CBC mode requires at least +Linux kernel version 5.3 and for devices using Elephant diffuser kernel 5.6. + +The \fBbitlkDump\fR command should work for all recognized BITLK devices +and doesn't require superuser privilege. + +For unlocking with the \fBopen\fR a password or a recovery passphrase must +be provided. Other unlocking methods (TPM, SmartCard) are not supported. + +.PP +\fIopen\fR \-\-type bitlk +.br +\fIbitlkOpen\fR (\fBold syntax\fR) +.IP +Opens the BITLK (a BitLocker-compatible) and sets up +a mapping . + +\fB\fR can be [\-\-key\-file, \-\-readonly, \-\-test\-passphrase, +\-\-allow-discards]. + +.PP +\fIbitlkDump\fR +.IP +Dump the header information of a BITLK device. + +Please note that cryptsetup does not use any Windows BitLocker code, please report +all problems related to this compatibility extension to the cryptsetup project. .SH MISCELLANEOUS .PP \fIrepair\fR @@ -532,7 +800,8 @@ for LUKS device type. This command is useful to fix some known benign LUKS metadata header corruptions. Only basic corruptions of unused keyslot are fixable. This command will only change the LUKS header, not -any key-slot data. +any key-slot data. You may enforce LUKS version by adding \-\-type +option. \fBWARNING:\fR Always create a binary backup of the original header before calling this command. @@ -540,7 +809,7 @@ header before calling this command. \fIbenchmark\fR .IP Benchmarks ciphers and KDF (key derivation function). -Without parameters it tries to measure few common configurations. +Without parameters, it tries to measure few common configurations. To benchmark other ciphers or modes, you need to specify \fB\-\-cipher\fR and \fB\-\-key\-size\fR options or \fB\-\-hash\fR for KDF test. @@ -560,9 +829,14 @@ If you are configuring kernel yourself, enable .B "\-\-verbose, \-v" Print more information on command execution. .TP -.B "\-\-debug" +.B "\-\-debug or \-\-debug\-json" Run in debug mode with full diagnostic logs. Debug output lines are always prefixed by '#'. +If \-\-debug\-json is used, additional LUKS2 JSON data structures are printed. +.TP +.B "\-\-type +Specifies required device type, for more info +read \fIBASIC COMMANDS\fR section. .TP .B "\-\-hash, \-h \fI\fR" Specifies the passphrase hash for \fIopen\fR (for plain and @@ -593,7 +867,7 @@ The current default in the distributed sources is "aes-cbc-essiv:sha256" for plain dm-crypt and "aes-xts-plain64" for LUKS. -If a hash is part of the cipher spefification, then it is +If a hash is part of the cipher specification, then it is used as part of the IV generation. For example, ESSIV needs a hash function, while "plain64" does not and hence none is specified. @@ -630,18 +904,18 @@ See section \fBNOTES ON PASSPHRASE PROCESSING\fR for more information. .TP .B "\-\-keyfile\-offset \fIvalue\fR" Skip \fIvalue\fR bytes at the beginning of the key file. -Works with all commands that accepts key files. +Works with all commands that accept key files. .TP .B "\-\-keyfile\-size, \-l \fIvalue\fR" Read a maximum of \fIvalue\fR bytes from the key file. -Default is to read the whole file up to the compiled-in +The default is to read the whole file up to the compiled-in maximum that can be queried with \-\-help. Supplying more data than the compiled-in maximum aborts the operation. This option is useful to cut trailing newlines, for example. If \-\-keyfile\-offset is also given, the size count starts after the offset. -Works with all commands that accepts key files. +Works with all commands that accept key files. .TP .B "\-\-new\-keyfile\-offset \fIvalue\fR" Skip \fIvalue\fR bytes at the start when @@ -651,7 +925,7 @@ adding a new passphrase from key file with .B "\-\-new\-keyfile\-size \fIvalue\fR" Read a maximum of \fIvalue\fR bytes when adding a new passphrase from key file with \fIluksAddKey\fR. -Default is to read the whole file up to the compiled-in +The default is to read the whole file up to the compiled-in maximum length that can be queried with \-\-help. Supplying more than the compiled in maximum aborts the operation. @@ -668,13 +942,17 @@ LUKS header and all other parameters are the same, then the new header decrypts the data encrypted with the header the master key was taken from. +Action \fIluksDump\fR together with \-\-dump\-master\-key +option: The volume (master) key is stored in a file instead of +being printed out to standard output. + \fBWARNING:\fR If you create your own master key, you -need to make sure to do it right. Otherwise you can end +need to make sure to do it right. Otherwise, you can end up with a low-entropy or otherwise partially predictable master key which will compromise security. For \fIluksAddKey\fR this allows adding a new passphrase -without having to know an exiting one. +without having to know an existing one. For \fIopen\fR this allows one to open the LUKS device without giving a passphrase. @@ -684,6 +962,11 @@ For \fIluksDump\fR this option includes the master key in the displayed information. Use with care, as the master key can be used to bypass the passphrases, see also option \-\-master\-key\-file. .TP +.B "\-\-json\-file" +Read token json from a file or write token to it. See \fItoken\fR action for more +information. \-\-json\-file=- reads json from standard input or writes it to +standard output respectively. +.TP .B "\-\-use\-random" .TP .B "\-\-use\-urandom" @@ -726,14 +1009,18 @@ All other LUKS actions will use the key-size specified in the LUKS header. Use \fIcryptsetup \-\-help\fR to show the compiled-in defaults. .TP .B "\-\-size, \-b " -Force the size of the underlying device in sectors of 512 bytes. +Set the size of the device in sectors of 512 bytes. This option is only relevant for the \fIopen\fR and \fIresize\fR actions. .TP .B "\-\-offset, \-o " Start offset in the backend device in 512-byte sectors. This option is only relevant for the \fIopen\fR action with plain -or loopaes device types. +or loopaes device types or for LUKS devices in \fIluksFormat\fR. + +For LUKS, the \-\-offset option sets the data offset (payload) of data +device and must be be aligned to 4096-byte sectors (must be multiple of 8). +This option cannot be combined with \-\-align\-payload option. .TP .B "\-\-skip, \-p " Start offset used in IV calculation in 512-byte sectors @@ -742,9 +1029,25 @@ This option is only relevant for the \fIopen\fR action with plain or loopaes device types. Hence, if \-\-offset \fIn\fR, and \-\-skip \fIs\fR, sector \fIn\fR -(the first sector of encrypted device) will get a sector number +(the first sector of the encrypted device) will get a sector number of \fIs\fR for the IV calculation. .TP +.B "\-\-device\-size \fIsize[units]\fR" +Instead of real device size, use specified value. + +With \fIreencrypt\fR action it means that only specified area +(from the start of the device to the specified size) will be +reencrypted. + +With \fIresize\fR action it sets new size of the device. + +If no unit suffix is specified, the size is in bytes. + +Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB) +for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale). + +\fBWARNING:\fR This is destructive operation when used with reencrypt command. +.TP .B "\-\-readonly, \-r" set up a read-only mapping. .TP @@ -755,18 +1058,77 @@ This option is only relevant for the \fIopen \-\-type plain\fR action. Use \-\-offset, \-\-size and \-\-skip to specify the mapped area. .TP +.B "\-\-pbkdf " +Set Password-Based Key Derivation Function (PBKDF) algorithm for LUKS keyslot. +The PBKDF can be: \fIpbkdf2\fR (for PBKDF2 according to RFC2898), +\fIargon2i\fR for Argon2i or \fIargon2id\fR for Argon2id +(see https://www.cryptolux.org/index.php/Argon2 for more info). + +For LUKS1, only PBKDF2 is accepted (no need to use this option). +The default PBKDF2 for LUKS2 is set during compilation time +and is available in \fIcryptsetup \-\-help\fR output. + +A PBKDF is used for increasing dictionary and brute-force attack cost +for keyslot passwords. The parameters can be time, memory and parallel cost. + +For PBKDF2, only time cost (number of iterations) applies. +For Argon2i/id, there is also memory cost (memory required during +the process of key derivation) and parallel cost (number of threads +that run in parallel during the key derivation. + +Note that increasing memory cost also increases time, so the final +parameter values are measured by a benchmark. The benchmark +tries to find iteration time (\fI\-\-iter\-time\fR) with required +memory cost \fI\-\-pbkdf\-memory\fR. If it is not possible, +the memory cost is decreased as well. +The parallel cost \fI\-\-pbkdf\-parallel\fR is constant, is is checked +against available CPU cores (if not available, it is decreased) and the maximum +parallel cost is 4. + +You can see all PBKDF parameters for particular LUKS2 keyslot with +\fIluksDump\fR command. + +\fBNOTE:\fR If you do not want to use benchmark and want to specify +all parameters directly, use \fI\-\-pbkdf\-force\-iterations\fR with +\fI\-\-pbkdf\-memory\fR and \fI\-\-pbkdf\-parallel\fR. +This will override the values without benchmarking. +Note it can cause extremely long unlocking time. Use only is specified +cases, for example, if you know that the formatted device will +be used on some small embedded system. +In this case, the LUKS PBKDF2 digest will be set to the minimum iteration count. +.TP .B "\-\-iter\-time, \-i " -The number of milliseconds to spend with PBKDF2 passphrase processing. +The number of milliseconds to spend with PBKDF passphrase processing. This option is only relevant for LUKS operations that set or change passphrases, such as \fIluksFormat\fR or \fIluksAddKey\fR. Specifying 0 as parameter selects the compiled-in default. .TP +.B "\-\-pbkdf\-memory " +Set the memory cost for PBKDF (for Argon2i/id the number represents kilobytes). +Note that it is maximal value, PBKDF benchmark or available physical memory +can decrease it. +This option is not available for PBKDF2. +.TP +.B "\-\-pbkdf\-parallel " +Set the parallel cost for PBKDF (number of threads, up to 4). +Note that it is maximal value, it is decreased automatically if +CPU online count is lower. +This option is not available for PBKDF2. +.TP +.B "\-\-pbkdf\-force\-iterations " +Avoid PBKDF benchmark and set time cost (iterations) directly. +It can be used for LUKS/LUKS2 device only. +See \fI\-\-pbkdf\fR option for more info. +.TP .B "\-\-batch\-mode, \-q" Suppresses all confirmation questions. Use with care! If the \-y option is not specified, this option also switches off the passphrase verification for \fIluksFormat\fR. .TP +.B "\-\-progress-frequency " +Print separate line every with wipe progress. +.TP .B "\-\-timeout, \-t " The number of seconds to wait before timeout on passphrase input via terminal. It is relevant every time a passphrase is asked, @@ -790,24 +1152,30 @@ Align payload at a boundary of \fIvalue\fR 512-byte sectors. This option is relevant for \fIluksFormat\fR. If not specified, cryptsetup tries to use the topology info -provided by kernel for the underlying device to get optimal alignment. +provided by the kernel for the underlying device to get the optimal alignment. If not available (or the calculated value is a multiple of the default) data is by default aligned to a 1MiB boundary (i.e. 2048 512-byte sectors). -For a detached LUKS header this option specifies the offset on the +For a detached LUKS header, this option specifies the offset on the data device. See also the \-\-header option. + +\fBWARNING:\fR This option is DEPRECATED and has often unexpected impact +to the data offset and keyslot area size (for LUKS2) due to the complex rounding. +For fixed data device offset use \fI\-\-offset\fR option instead. + .TP .B "\-\-uuid=\fIUUID\fR" Use the provided \fIUUID\fR for the \fIluksFormat\fR command -instead of generating new one. Changes the existing UUID when +instead of generating a new one. Changes the existing UUID when used with the \fIluksUUID\fR command. The UUID must be provided in the standard UUID format, e.g. 12345678-1234-1234-1234-123456789abc. .TP .B "\-\-allow\-discards\fR" -Allow the use of discard (TRIM) requests for device. +Allow the use of discard (TRIM) requests for the device. This option is only relevant for \fIopen\fR action. +This is also not supported for LUKS2 devices with data integrity protection. \fBWARNING:\fR This command can have a negative security impact because it can make filesystem-level operations visible on @@ -816,7 +1184,7 @@ filesystem type, used space, etc. may be extractable from the physical device if the discarded blocks can be located later. If in doubt, do not use it. -A kernel version of 3.1 or later is needed. For earlier kernels +A kernel version of 3.1 or later is needed. For earlier kernels, this option is ignored. .TP .B "\-\-perf\-same_cpu_crypt\fR" @@ -842,21 +1210,21 @@ performance tuning, use only if you need a change to default dm-crypt behaviour. Needs kernel 4.0 or later. .TP .B "\-\-test\-passphrase\fR" -Do not activate device, just verify passphrase. +Do not activate the device, just verify passphrase. This option is only relevant for \fIopen\fR action (the device mapping name is not mandatory if this option is used). .TP .B "\-\-header\fR " Use a detached (separated) metadata device or file where the -LUKS header is stored. This options allows one to store ciphertext +LUKS header is stored. This option allows one to store ciphertext and LUKS header on different devices. This option is only relevant for LUKS devices and can be used with the \fIluksFormat\fR, \fIopen\fR, \fIluksSuspend\fR, \fIluksResume\fR, \fIstatus\fR and \fIresize\fR commands. -For \fIluksFormat\fR with a file name as argument to \-\-header, -it has to exist and be large enough to contain the LUKS header. +For \fIluksFormat\fR with a file name as the argument to \-\-header, +the file will be automatically created if it does not exist. See the cryptsetup FAQ for header size calculation. For other commands that change the LUKS header (e.g. \fIluksAddKey\fR), @@ -867,19 +1235,237 @@ If used with \fIluksFormat\fR, the \-\-align\-payload option is taken as absolute sector alignment on ciphertext device and can be zero. \fBWARNING:\fR There is no check whether the ciphertext device specified -actually belongs to the header given. In fact you can specify an +actually belongs to the header given. In fact, you can specify an arbitrary device as the ciphertext device for \fIopen\fR with the \-\-header option. Use with care. .TP -.B "\-\-force\-password\fR" +.B "\-\-header\-backup\-file " +Specify file with header backup for \fIluksHeaderBackup\fR or +\fIluksHeaderRestore\fR actions. +.TP +.B "\-\-force\-password" Do not use password quality checking for new LUKS passwords. This option applies only to \fIluksFormat\fR, \fIluksAddKey\fR and \fIluksChangeKey\fR and is ignored if cryptsetup is built without password quality checking support. -For more info about password quality check, see manual page -for \fBpwquality.conf(5)\fR. +For more info about password quality check, see the manual page +for \fBpwquality.conf(5)\fR and \fBpasswdqc.conf(5)\fR. +.TP +.B "\-\-deferred" +Defers device removal in \fIclose\fR command until the last user closes it. +.TP +.B "\-\-disable\-locks" +Disable lock protection for metadata on disk. +This option is valid only for LUKS2 and ignored for other formats. + +\fBWARNING:\fR Do not use this option unless you run cryptsetup in +a restricted environment where locking is impossible to perform +(where /run directory cannot be used). +.TP +.B "\-\-disable\-keyring" +Do not load volume key in kernel keyring and store it directly +in the dm-crypt target instead. +This option is supported only for the LUKS2 format. +.TP +.B "\-\-key\-description " +Set key description in keyring for use with \fItoken\fR command. +.TP +.B "\-\-priority " +Set a priority for LUKS2 keyslot. +The \fIprefer\fR priority marked slots are tried before \fInormal\fR priority. +The \fIignored\fR priority means, that slot is never used, if not explicitly +requested by \fI\-\-key\-slot\fR option. +.TP +.B "\-\-token\-id" +Specify what token to use in actions \fItoken\fR, \fIopen\fR or \fIresize\fR. +If omitted, all available tokens will be checked before proceeding further with +passphrase prompt. +.TP +.B "\-\-token\-only" +Do not proceed further with action (any of \fItoken\fR, \fIopen\fR or +\fIresize\fR) if token activation failed. Without the option, +action asks for passphrase to proceed further. +.TP +.B "\-\-sector\-size " +Set sector size for use with disk encryption. It must be power of two +and in range 512 - 4096 bytes. The default is 512 bytes sectors. +This option is available only in the LUKS2 mode. + +Note that if sector size is higher than underlying device hardware sector +and there is not integrity protection that uses data journal, using +this option can increase risk on incomplete sector writes during a power fail. + +If used together with \fI\-\-integrity\fR option and dm-integrity journal, +the atomicity of writes is guaranteed in all cases (but it cost write +performance - data has to be written twice). + +Increasing sector size from 512 bytes to 4096 bytes can provide better +performance on most of the modern storage devices and also with some +hw encryption accelerators. +.TP +.B "\-\-iv-large-sectors" +Count Initialization Vector (IV) in larger sector size (if set) instead +of 512 bytes sectors. This option can be used only for \fIopen\fR command +and \fIplain\fR encryption type. + +\fBNOTE:\fR This option does not have any performance or security impact, +use it only for accessing incompatible existing disk images from other systems +that require this option. +.TP +.B "\-\-persistent" +If used with LUKS2 devices and activation commands like \fIopen\fR or \fIrefresh\fR, +the specified activation flags are persistently written into metadata +and used next time automatically even for normal activation. +(No need to use cryptab or other system configuration files.) + +If you need to remove a persistent flag, use \fI\-\-persistent\fR without +the flag you want to remove (e.g. to disable persistently stored discard flag, +use \fI\-\-persistent\fR without \fI\-\-allow-discards\fR). + +Only \fI\-\-allow-discards\fR, \fI\-\-perf\-same_cpu_crypt\fR, +\fI\-\-perf\-submit_from_crypt_cpus\fR and \fI\-\-integrity\-no\-journal\fR +can be stored persistently. +.TP +.B "\-\-refresh" +Refreshes an active device with new set of parameters. See action \fIrefresh\fR description +for more details. +.TP +.B "\-\-label