From 7e2fa89fceb638cdbe976805b9085049abd42110 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sun, 3 Feb 2013 00:17:28 -0500 Subject: [PATCH] Write the data file header in big endian format. To prevent portability issues when transferring the data file between little and big endian systems. This breaks data file compatibility with previous commits. --- configure.ac | 1 + doc/magic | 44 ++++++------- m4/ax_c_bigendian_cross.m4 | 122 ++++++++++++++++++++++++++++++++++ src/crypto.c | 160 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 297 insertions(+), 30 deletions(-) create mode 100644 m4/ax_c_bigendian_cross.m4 diff --git a/configure.ac b/configure.ac index 0381019a..22723c11 100644 --- a/configure.ac +++ b/configure.ac @@ -20,6 +20,7 @@ if test "$ac_cv_prog_cc_c99" = "no"; then AC_MSG_WARN("Unable to find a C99 compatible compiler.") fi +AX_C_BIGENDIAN_CROSS AC_PROG_AWK AC_PROG_LN_S AC_PROG_INSTALL diff --git a/doc/magic b/doc/magic index bda077cf..3cb4119e 100644 --- a/doc/magic +++ b/doc/magic @@ -2,31 +2,31 @@ 0x00 string \177PWMD PWMD data file, # Version 3.x.x ->0x05 ulong >0x02ffff ->>0x07 ubyte x \b version=%x. ->>0x06 ubyte x \b%x. ->>0x05 ubyte x \b%x +>0x05 belong >0x02ffff +>>0x06 ubyte x \b version=%x. +>>0x07 ubyte x \b%x. +>>0x08 ubyte x \b%x # Cipher iterations ->>0x09 uquad x \b, iterations=%llu +>>0x09 bequad x \b, iterations=%llu # Flags (cipher) ->>0x11 uquad >0 \b, cipher= ->>>0x11 uquad &0x01 \baes128 ->>>0x11 uquad &0x02 \baes192 ->>>0x11 uquad &0x04 \baes256 ->>>0x11 uquad &0x08 \bserpent128 ->>>0x11 uquad &0x10 \bserpent192 ->>>0x11 uquad &0x20 \bserpent256 ->>>0x11 uquad &0x40 \bcamellia128 ->>>0x11 uquad &0x80 \bcamellia192 ->>>0x11 uquad &0x100 \bcamellia256 ->>>0x11 uquad &0x200 \b3des ->>>0x11 uquad &0x400 \bcast5 ->>>0x11 uquad &0x800 \bblowfish ->>>0x11 uquad &0x1000 \btwofish256 ->>>0x11 uquad &0x2000 \btwofish128 ->>0x31 ulong x \b, datalen=%li +>>0x11 bequad >0 \b, cipher= +>>>0x11 bequad &0x01 \baes128 +>>>0x11 bequad &0x02 \baes192 +>>>0x11 bequad &0x04 \baes256 +>>>0x11 bequad &0x08 \bserpent128 +>>>0x11 bequad &0x10 \bserpent192 +>>>0x11 bequad &0x20 \bserpent256 +>>>0x11 bequad &0x40 \bcamellia128 +>>>0x11 bequad &0x80 \bcamellia192 +>>>0x11 bequad &0x100 \bcamellia256 +>>>0x11 bequad &0x200 \b3des +>>>0x11 bequad &0x400 \bcast5 +>>>0x11 bequad &0x800 \bblowfish +>>>0x11 bequad &0x1000 \btwofish256 +>>>0x11 bequad &0x2000 \btwofish128 +>>0x31 belong x \b, datalen=%li # Keygrips. ->>0x11 uquad >0xFFFF +>>0x11 bequad >0xFFFF >>>0x35 ubyte x \b, keygrip=%02X >>>>&0x00 ubyte x \b%02X >>>>&0x01 ubyte x \b%02X diff --git a/m4/ax_c_bigendian_cross.m4 b/m4/ax_c_bigendian_cross.m4 new file mode 100644 index 00000000..e6a1840d --- /dev/null +++ b/m4/ax_c_bigendian_cross.m4 @@ -0,0 +1,122 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_c_bigendian_cross.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_C_BIGENDIAN_CROSS +# +# DESCRIPTION +# +# Check endianess even when crosscompiling (partially based on the +# original AC_C_BIGENDIAN). +# +# The implementation will create a binary, but instead of running the +# binary it will be grep'ed for some symbols that differ for different +# endianess of the binary. +# +# NOTE: The upcoming autoconf 2.53 does include the idea of this macro, +# what makes it superfluous by then. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 5 + +AU_ALIAS([AC_C_BIGENDIAN_CROSS], [AX_C_BIGENDIAN_CROSS]) +AC_DEFUN([AX_C_BIGENDIAN_CROSS], +[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian, +[ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +AC_TRY_COMPILE([#include +#include ], [ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif], [# It does; now see whether it defined to BIG_ENDIAN or not. +AC_TRY_COMPILE([#include +#include ], [ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)]) +if test $ac_cv_c_bigendian = unknown; then +AC_TRY_RUN([main () { + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes, +[ echo $ac_n "cross-compiling... " 2>&AC_FD_MSG ]) +fi]) +if test $ac_cv_c_bigendian = unknown; then +AC_MSG_CHECKING(to probe for byte ordering) +[ +cat >conftest.c <&AC_FD_MSG + ac_cv_c_bigendian=yes + fi + if test `grep -l LiTTleEnDian conftest.o` ; then + echo $ac_n ' little endian probe OK, ' 1>&AC_FD_MSG + if test $ac_cv_c_bigendian = yes ; then + ac_cv_c_bigendian=unknown; + else + ac_cv_c_bigendian=no + fi + fi + echo $ac_n 'guessing bigendian ... ' >&AC_FD_MSG + fi + fi +AC_MSG_RESULT($ac_cv_c_bigendian) +fi +if test $ac_cv_c_bigendian = yes; then + AC_DEFINE(WORDS_BIGENDIAN, 1, [whether byteorder is bigendian]) + BYTEORDER=4321 +else + BYTEORDER=1234 +fi +AC_DEFINE_UNQUOTED(BYTEORDER, $BYTEORDER, [1234 = LIL_ENDIAN, 4321 = BIGENDIAN]) +if test $ac_cv_c_bigendian = unknown; then + AC_MSG_ERROR(unknown endianess - sorry, please pre-set ac_cv_c_bigendian) +fi +]) diff --git a/src/crypto.c b/src/crypto.c index 429dc796..13d38c43 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -64,6 +64,79 @@ set_header_defaults (file_header_t * hdr) #endif } +static gpg_error_t +read_header (file_header_t *hdr, int fd) +{ + ssize_t len; + uint32_t i; + uint64_t n, x; + +#ifdef WORDS_BIGENDIAN + len = read (fd, &hdr->magic, sizeof(hdr->magic)); + if (len == -1) + goto done; + + len = read (fd, &hdr->version, sizeof(hdr->version)); + if (len == -1) + goto done; + + len = read (fd, &hdr->iterations, sizeof(hdr->iterations)); + if (len == -1) + goto done; + + len = read (fd, &hdr->flags, sizeof(hdr->flags)); + if (len == -1) + goto done; + + len = read (fd, &hdr->iv, sizeof(hdr->iv)); + if (len == -1) + goto done; + + len = read (fd, &hdr->salt, sizeof(hdr->salt)); + if (len == -1) + goto done; + + len = read (fd, &hdr->datalen, sizeof(hdr->datalen)); + if (len == -1) + goto done; +#else + len = read (fd, &hdr->magic, sizeof(hdr->magic)); + if (len == -1) + goto done; + + len = read (fd, &i, sizeof(hdr->version)); + if (len == -1) + goto done; + hdr->version = ntohl (i); + + len = read (fd, &n, sizeof(hdr->iterations)); + if (len == -1) + goto done; + hdr->iterations = (((uint64_t) ntohl (n)) << 32) + ntohl (n >> 32); + + len = read (fd, &n, sizeof(hdr->flags)); + if (len == -1) + goto done; + hdr->flags = (((uint64_t) ntohl (n)) << 32) + ntohl (n >> 32); + + len = read (fd, &hdr->iv, sizeof(hdr->iv)); + if (len == -1) + goto done; + + len = read (fd, &hdr->salt, sizeof(hdr->salt)); + if (len == -1) + goto done; + + len = read (fd, &i, sizeof(hdr->datalen)); + if (len == -1) + goto done; + hdr->datalen = ntohl (i); +#endif + + done: + return len == -1 ? gpg_error_from_syserror () : 0; +} + gpg_error_t read_data_header (const char *filename, file_header_t * rhdr, struct stat *rst, int *rfd) @@ -84,10 +157,7 @@ read_data_header (const char *filename, file_header_t * rhdr, if (fd == -1) return gpg_error_from_syserror (); - len = read (fd, &hdr, sizeof (file_header_t)); - if (len != sizeof (file_header_t)) - rc = rc == -1 ? gpg_error_from_syserror () : GPG_ERR_BAD_DATA; - + rc = read_header (&hdr, fd); if (!rc && memcmp (hdr.magic, pwmd_magic, sizeof (hdr.magic))) rc = GPG_ERR_BAD_DATA; else if (hdr.version < 0x030000) @@ -907,6 +977,82 @@ cleanup_acl (void *arg) } #endif +static gpg_error_t +write_header (struct crypto_s *crypto, int fd) +{ + ssize_t len; + uint64_t n, x; + uint32_t i; + +#ifdef WORDS_BIGENDIAN + len = write (fd, &crypto->save.hdr.magic, sizeof(crypto->save.hdr.magic)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.version, sizeof(crypto->save.hdr.version)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.iterations, + sizeof(crypto->save.hdr.iterations)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.flags, sizeof(crypto->save.hdr.flags)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.iv, sizeof(crypto->save.hdr.iv)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.salt, sizeof(crypto->save.hdr.salt)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.datalen, sizeof(crypto->save.hdr.datalen)); + if (len == -1) + goto done; +#else + len = write (fd, &crypto->save.hdr.magic, sizeof(crypto->save.hdr.magic)); + if (len == -1) + goto done; + + i = htonl (crypto->save.hdr.version); + len = write (fd, &i, sizeof(i)); + if (len == -1) + goto done; + + n = crypto->save.hdr.iterations; + x = (((uint64_t) htonl (n)) << 32) + htonl (n >> 32); + len = write (fd, &x, sizeof(x)); + if (len == -1) + goto done; + + n = crypto->save.hdr.flags; + x = (((uint64_t) htonl (n)) << 32) + htonl (n >> 32); + len = write (fd, &x, sizeof(x)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.iv, sizeof(crypto->save.hdr.iv)); + if (len == -1) + goto done; + + len = write (fd, &crypto->save.hdr.salt, sizeof(crypto->save.hdr.salt)); + if (len == -1) + goto done; + + i = htonl (crypto->save.hdr.datalen); + len = write (fd, &i, sizeof(i)); + if (len == -1) + goto done; +#endif + + done: + return len == -1 ? gpg_error_from_syserror () : 0; +} + gpg_error_t write_file (struct crypto_s *crypto, const char *filename, void *data, size_t data_len, void *sexp, size_t sexp_len, @@ -951,8 +1097,8 @@ write_file (struct crypto_s *crypto, const char *filename, pthread_cleanup_push (cleanup_unlink_cb, tmp); crypto->save.hdr.version = VERSION_HEX; - len = write (fd, &crypto->save.hdr, sizeof (file_header_t)); - if (len == sizeof (file_header_t)) + rc = write_header (crypto, fd); + if (!rc) { if (crypto->save.hdr.flags & PWMD_FLAG_PKCS) { @@ -987,8 +1133,6 @@ write_file (struct crypto_s *crypto, const char *filename, rc = gpg_error_from_syserror (); } } - else - rc = gpg_error_from_syserror (); #ifdef WITH_LIBACL pthread_cleanup_push (cleanup_acl, &acl); -- 2.11.4.GIT