bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

md4 and md4-tests


From: Simon Josefsson
Subject: md4 and md4-tests
Date: Tue, 18 Oct 2005 17:12:22 +0200
User-agent: Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.50 (gnu/linux)

Ok to install?

This is more or less a copy of the md5 module.  At some point, it may
be useful to modularize the non-cryptographic portions of
md4/md5/sha1, to simplify maintenance.

Index: ChangeLog
===================================================================
RCS file: /cvsroot/gnulib/gnulib/ChangeLog,v
retrieving revision 1.427
diff -u -p -r1.427 ChangeLog
--- ChangeLog   18 Oct 2005 14:10:27 -0000      1.427
+++ ChangeLog   18 Oct 2005 15:10:34 -0000
@@ -1,5 +1,11 @@
 2005-10-18  Simon Josefsson  <address@hidden>
 
+       * tests/test-md4.c: New file.
+
+       * modules/md4, modules/md4-tests: New files.
+
+2005-10-18  Simon Josefsson  <address@hidden>
+
        * tests/test-md5.c: New file.
 
        * modules/md5-tests: New file.
Index: m4/md4.m4
===================================================================
RCS file: m4/md4.m4
diff -N m4/md4.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/md4.m4   18 Oct 2005 15:10:34 -0000
@@ -0,0 +1,14 @@
+# md4.m4 serial 1
+dnl Copyright (C) 2002, 2003, 2004, 2005 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.
+
+AC_DEFUN([gl_MD4],
+[
+  AC_LIBSOURCES([md4.c, md4.h])
+  AC_LIBOBJ([md4])
+
+  dnl Prerequisites of lib/md4.c.
+  AC_REQUIRE([AC_C_BIGENDIAN])
+])
Index: modules/md4
===================================================================
RCS file: modules/md4
diff -N modules/md4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/md4 18 Oct 2005 15:10:34 -0000
@@ -0,0 +1,24 @@
+Description:
+Compute MD4 checksum.
+
+Files:
+lib/md4.h
+lib/md4.c
+m4/md4.m4
+
+Depends-on:
+stdint
+
+configure.ac:
+gl_MD4
+
+Makefile.am:
+
+Include:
+"md4.h"
+
+License:
+LGPL
+
+Maintainer:
+Simon Josefsson
Index: modules/md4-tests
===================================================================
RCS file: modules/md4-tests
diff -N modules/md4-tests
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/md4-tests   18 Oct 2005 15:10:34 -0000
@@ -0,0 +1,11 @@
+Files:
+tests/test-md4.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-md4
+noinst_PROGRAMS += test-md4
+test_md4_SOURCES = test-md4.c
Index: lib/ChangeLog
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/ChangeLog,v
retrieving revision 1.1019
diff -u -p -r1.1019 ChangeLog
--- lib/ChangeLog       17 Oct 2005 14:33:14 -0000      1.1019
+++ lib/ChangeLog       18 Oct 2005 15:10:35 -0000
@@ -1,3 +1,7 @@
+2005-10-18  Simon Josefsson  <address@hidden>
+
+       * md4.h, md4.c: New files, based on md5.?.
+
 2005-10-17  Simon Josefsson  <address@hidden>
 
        * gc-libgcrypt.c (gc_hmac_sha1): Fix assert.
Index: lib/md4.h
===================================================================
RCS file: lib/md4.h
diff -N lib/md4.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/md4.h   18 Oct 2005 15:10:35 -0000
@@ -0,0 +1,88 @@
+/* Declarations of functions and data types used for MD4 sum
+   library functions.
+   Copyright (C) 2000, 2001, 2003, 2005 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef MD4_H
+# define MD4_H 1
+
+# include <stdio.h>
+# include <stdint.h>
+
+#define MD4_DIGEST_SIZE 16
+
+/* Structure to save state of computation between the single steps.  */
+struct md4_ctx
+{
+  uint32_t A;
+  uint32_t B;
+  uint32_t C;
+  uint32_t D;
+
+  uint32_t total[2];
+  uint32_t buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
+};
+
+
+/* Initialize structure containing state of computation. */
+extern void md4_init_ctx (struct md4_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void md4_process_block (const void *buffer, size_t len,
+                              struct md4_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md4_process_bytes (const void *buffer, size_t len,
+                              struct md4_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF be correctly
+   aligned for a 32 bits value.  */
+extern void *md4_finish_ctx (struct md4_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md4_read_ctx (const struct md4_ctx *ctx, void *resbuf);
+
+
+/* Compute MD4 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md4_stream (FILE * stream, void *resblock);
+
+/* Compute MD4 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *md4_buffer (const char *buffer, size_t len, void *resblock);
+
+#endif
Index: lib/md4.c
===================================================================
RCS file: lib/md4.c
diff -N lib/md4.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/md4.c   18 Oct 2005 15:10:35 -0000
@@ -0,0 +1,381 @@
+/* Functions to compute MD4 message digest of files or memory blocks.
+   according to the definition of MD4 in RFC 1320 from April 1992.
+   Copyright (C) 1995,1996,1997,1999,2000,2001,2002,2003,2005
+   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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Adapted by Simon Josefsson from gnulib md5.? and Libgcrypt
+   cipher/md4.c . */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "md4.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)                                                       \
+  (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+#define BLOCKSIZE 4096
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#endif
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1320, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */  };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1320, 3.3: Step 3)  */
+void
+md4_init_ctx (struct md4_ctx *ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md4_read_ctx (const struct md4_ctx *ctx, void *resbuf)
+{
+  ((uint32_t *) resbuf)[0] = SWAP (ctx->A);
+  ((uint32_t *) resbuf)[1] = SWAP (ctx->B);
+  ((uint32_t *) resbuf)[2] = SWAP (ctx->C);
+  ((uint32_t *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md4_finish_ctx (struct md4_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  uint32_t bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(uint32_t *) & ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(uint32_t *) & ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+                                                      (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md4_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md4_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD4 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md4_stream (FILE * stream, void *resblock)
+{
+  struct md4_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md4_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+         computation function processes the whole buffer so that with the
+         next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      while (1)
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+
+         if (sum == BLOCKSIZE)
+           break;
+
+         if (n == 0)
+           {
+             /* Check for the error flag IFF N == 0, so that we don't
+                exit the loop after a partial read due to e.g., EAGAIN
+                or EWOULDBLOCK.  */
+             if (ferror (stream))
+               return 1;
+             goto process_partial_block;
+           }
+
+         /* We've read at least one byte, so ignore errors.  But always
+            check for EOF, since feof may be true even though N > 0.
+            Otherwise, we could end up calling fread after EOF.  */
+         if (feof (stream))
+           goto process_partial_block;
+       }
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+         BLOCKSIZE % 64 == 0
+       */
+      md4_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+process_partial_block:;
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    md4_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md4_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md4_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct md4_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md4_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md4_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md4_finish_ctx (&ctx, resblock);
+}
+
+void
+md4_process_bytes (const void *buffer, size_t len, struct md4_ctx *ctx)
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         md4_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+      /* To check alignment gcc has an appropriate operator.  Other
+         compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
+# else
+#  define alignof(type) offsetof (struct { char c; type x; }, x)
+#  define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           md4_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         md4_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         md4_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
+
+/* --- Code below is the primary difference between md5.c and md4.c --- */
+
+/* MD4 round constants */
+#define K1 0x5a827999L
+#define K2 0x6ed9eba1L
+
+/* Round functions.  */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#define R1(a,b,c,d,k,s) a=rol(a+F(b,c,d)+x[k],s);
+#define R2(a,b,c,d,k,s) a=rol(a+G(b,c,d)+x[k]+K1,s);
+#define R3(a,b,c,d,k,s) a=rol(a+H(b,c,d)+x[k]+K2,s);
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md4_process_block (const void *buffer, size_t len, struct md4_ctx *ctx)
+{
+  const uint32_t *words = buffer;
+  size_t nwords = len / sizeof (uint32_t);
+  const uint32_t *endp = words + nwords;
+  uint32_t x[16];
+  uint32_t A = ctx->A;
+  uint32_t B = ctx->B;
+  uint32_t C = ctx->C;
+  uint32_t D = ctx->D;
+
+  /* First increment the byte count.  RFC 1320 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      uint32_t tm;
+      int t;
+      for (t = 0; t < 16; t++)
+       {
+         x[t] = SWAP (*words);
+         words++;
+       }
+
+      /* Round 1.  */
+      R1 (A, B, C, D, 0, 3);
+      R1 (D, A, B, C, 1, 7);
+      R1 (C, D, A, B, 2, 11);
+      R1 (B, C, D, A, 3, 19);
+      R1 (A, B, C, D, 4, 3);
+      R1 (D, A, B, C, 5, 7);
+      R1 (C, D, A, B, 6, 11);
+      R1 (B, C, D, A, 7, 19);
+      R1 (A, B, C, D, 8, 3);
+      R1 (D, A, B, C, 9, 7);
+      R1 (C, D, A, B, 10, 11);
+      R1 (B, C, D, A, 11, 19);
+      R1 (A, B, C, D, 12, 3);
+      R1 (D, A, B, C, 13, 7);
+      R1 (C, D, A, B, 14, 11);
+      R1 (B, C, D, A, 15, 19);
+
+      /* Round 2.  */
+      R2 (A, B, C, D, 0, 3);
+      R2 (D, A, B, C, 4, 5);
+      R2 (C, D, A, B, 8, 9);
+      R2 (B, C, D, A, 12, 13);
+      R2 (A, B, C, D, 1, 3);
+      R2 (D, A, B, C, 5, 5);
+      R2 (C, D, A, B, 9, 9);
+      R2 (B, C, D, A, 13, 13);
+      R2 (A, B, C, D, 2, 3);
+      R2 (D, A, B, C, 6, 5);
+      R2 (C, D, A, B, 10, 9);
+      R2 (B, C, D, A, 14, 13);
+      R2 (A, B, C, D, 3, 3);
+      R2 (D, A, B, C, 7, 5);
+      R2 (C, D, A, B, 11, 9);
+      R2 (B, C, D, A, 15, 13);
+
+      /* Round 3.  */
+      R3 (A, B, C, D, 0, 3);
+      R3 (D, A, B, C, 8, 9);
+      R3 (C, D, A, B, 4, 11);
+      R3 (B, C, D, A, 12, 15);
+      R3 (A, B, C, D, 2, 3);
+      R3 (D, A, B, C, 10, 9);
+      R3 (C, D, A, B, 6, 11);
+      R3 (B, C, D, A, 14, 15);
+      R3 (A, B, C, D, 1, 3);
+      R3 (D, A, B, C, 9, 9);
+      R3 (C, D, A, B, 5, 11);
+      R3 (B, C, D, A, 13, 15);
+      R3 (A, B, C, D, 3, 3);
+      R3 (D, A, B, C, 11, 9);
+      R3 (C, D, A, B, 7, 11);
+      R3 (B, C, D, A, 15, 15);
+
+      A = ctx->A += A;
+      B = ctx->B += B;
+      C = ctx->C += C;
+      D = ctx->D += D;
+    }
+}
Index: tests/test-md4.c
===================================================================
RCS file: tests/test-md4.c
diff -N tests/test-md4.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/test-md4.c    18 Oct 2005 15:10:35 -0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.  */
+
+/* Written by Simon Josefsson. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "md4.h"
+
+int
+main (int argc, char *argv[])
+{
+  const char *in1 = "abc";
+  const char *out1 =
+    "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d";
+  const char *in2 = "abcdefghijklmnopqrstuvwxyz";
+  const char *out2 =
+    "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d\xa9";
+  char buf[MD4_DIGEST_SIZE];
+
+  if (memcmp (md4_buffer (in1, strlen (in1), buf), out1, MD4_DIGEST_SIZE) !=
+      0)
+    {
+      size_t i;
+      printf ("expected:\n");
+      for (i = 0; i < MD4_DIGEST_SIZE; i++)
+       printf ("%02x ", out1[i] & 0xFF);
+      printf ("\ncomputed:\n");
+      for (i = 0; i < MD4_DIGEST_SIZE; i++)
+       printf ("%02x ", buf[i] & 0xFF);
+      printf ("\n");
+      return 1;
+    }
+
+  if (memcmp (md4_buffer (in2, strlen (in2), buf), out2, MD4_DIGEST_SIZE) !=
+      0)
+    {
+      size_t i;
+      printf ("expected:\n");
+      for (i = 0; i < MD4_DIGEST_SIZE; i++)
+       printf ("%02x ", out2[i] & 0xFF);
+      printf ("\ncomputed:\n");
+      for (i = 0; i < MD4_DIGEST_SIZE; i++)
+       printf ("%02x ", buf[i] & 0xFF);
+      printf ("\n");
+      return 1;
+    }
+
+  return 0;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]