Skip to content
Browse files

Adding sha1, sha256, sha512 and md6 hashes

  • Loading branch information...
1 parent 4f02645 commit d79aad2ecc052d1b6a85cb09b18b495854eef618 @brainfucker committed Jan 14, 2010
View
9 .lock-wscript
@@ -0,0 +1,9 @@
+argv = ['/usr/local/bin/node-waf', 'configure', 'build']
+blddir = '/home/brainfucker/Projects/hashlib/build'
+commands = {'dist': 0, 'configure': True, 'distcheck': 0, 'install': 0, 'build': True, 'clean': 0, 'distclean': 0, 'check': 0, 'uninstall': 0}
+cwd = '/home/brainfucker/Projects/hashlib'
+environ = {'GDM_KEYBOARD_LAYOUT': 'us', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'LESSOPEN': '| /usr/bin/lesspipe %s', 'LOGNAME': 'brainfucker', 'USER': 'brainfucker', 'PATH': '/var/lib/gems/1.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/brainfucker/Dropbox/Bin', 'HOME': '/home/brainfucker', 'DISPLAY': ':0.0', 'SSH_AGENT_PID': '2165', 'LANG': 'en_US.UTF-8', 'SPEECHD_PORT': '7560', 'TERM': 'xterm', 'SHELL': '/bin/bash', 'XDG_SESSION_COOKIE': '8143f1ef8b2173edae5c4ea34aed6323-1263460248.734008-24927218', 'SESSION_MANAGER': 'local/brainfucker-laptop:@/tmp/.ICE-unix/1990,unix/brainfucker-laptop:/tmp/.ICE-unix/1990', 'SHLVL': '1', '_': '/usr/local/bin/node-waf', 'DESKTOP_AUTOSTART_ID': '107978dae8fb34ab126346025650407300000019900000', 'USERNAME': 'brainfucker', 'SSH_AUTH_SOCK': '/tmp/keyring-jtkWgy/socket.ssh', 'GNOME_KEYRING_SOCKET': '/tmp/keyring-jtkWgy/socket', 'GDMSESSION': 'gnome', 'DBUS_SESSION_BUS_ADDRESS': 'unix:abstract=/tmp/dbus-jBVVX0EYEA,guid=d3f01e347305d102686b68af4b4edf9b', 'ORBIT_SOCKETDIR': '/tmp/orbit-brainfucker', 'XAUTHORITY': '/var/run/gdm/auth-for-brainfucker-9Sn1Pn/database', 'DESKTOP_SESSION': 'gnome', 'LESSCLOSE': '/usr/bin/lesspipe %s %s', 'GTK_MODULES': 'canberra-gtk-module', 'OLDPWD': '/home/brainfucker/Projects/hashlib', 'GDM_LANG': 'en_US.UTF-8', 'HISTCONTROL': 'ignoreboth', 'XDG_DATA_DIRS': '/usr/share/gnome:/usr/local/share/:/usr/share/', 'PWD': '/home/brainfucker/Projects/hashlib', 'GTK_RC_FILES': '/etc/gtk/gtkrc:/home/brainfucker/.gtkrc-1.2-gnome2', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:'}
+files = []
+hash = 0
+options = {'compile_targets': None, 'force': False, 'verbose': 0, 'nocache': False, 'progress_bar': 0, 'destdir': '', 'keep': False, 'zones': '', 'blddir': '', 'prefix': '/usr/local/', 'jobs': 2, 'srcdir': '', 'check_cxx_compiler': 'g++ icpc sunc++'}
+srcdir = '/home/brainfucker/Projects/hashlib'
View
21 README
@@ -1,7 +1,18 @@
+# Hashlib
Its an library for making hashes
-===========
- install:
- 1) go to the directory whith this library
- 2) make: node-waf configure build
-
+## Install:
+ 1) go to the directory whith this library
+ 2) make: node-waf configure build
+ 3) module will be here ./build/default/hashlib.node
+
+## Functions:
+ md5([sting] str); // Returns md5 hash from sting
+ sha1([sting] str); // Returns sha1 hash from sting
+ sha256([sting] str); // Returns sha256 hash from sting
+ sha512([sting] str); // Returns sha512 hash from sting
+ md6([sting] str, [int] length); // Returns md6 hash from sting, second parametr is optional
+
+## Using:
+ var hashlib = require("__path_to_hashlib_module__/hashlib");
+ hashlib.md5('text');
View
BIN build/.wafpickle-7
Binary file not shown.
View
2 build/c4che/build.config.py
@@ -0,0 +1,2 @@
+version = 0x105010
+tools = [{'tool': 'ar', 'tooldir': None, 'funs': None}, {'tool': 'cxx', 'tooldir': None, 'funs': None}, {'tool': 'gxx', 'tooldir': None, 'funs': None}, {'tool': 'compiler_cxx', 'tooldir': None, 'funs': None}, {'tool': 'node_addon', 'tooldir': None, 'funs': None}]
View
43 build/c4che/default.cache.py
@@ -0,0 +1,43 @@
+AR = '/usr/bin/ar'
+ARFLAGS = 'rcs'
+CCFLAGS_MACBUNDLE = ['-fPIC']
+CC_VERSION = ('4', '4', '1')
+COMPILER_CXX = 'g++'
+CPP = '/usr/bin/cpp'
+CPPFLAGS_NODE = '-DEV_MULTIPLICITY=0'
+CPPPATH_NODE = '/usr/local/include/node'
+CPPPATH_ST = '-I%s'
+CXX = ['/usr/bin/g++']
+CXXDEFINES_ST = '-D%s'
+CXXFLAGS_DEBUG = ['-g']
+CXXFLAGS_RELEASE = ['-O2']
+CXXLNK_SRC_F = ''
+CXXLNK_TGT_F = ['-o', '']
+CXX_NAME = 'gcc'
+CXX_SRC_F = ''
+CXX_TGT_F = ['-c', '-o', '']
+DEST_BINFMT = 'elf'
+DEST_CPU = 'x86_64'
+DEST_OS = 'linux'
+FULLSTATIC_MARKER = '-static'
+LIBPATH_NODE = '/usr/local/lib'
+LIBPATH_ST = '-L%s'
+LIB_ST = '-l%s'
+LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup']
+LINK_CXX = ['/usr/bin/g++']
+PREFIX = '/usr/local'
+PREFIX_NODE = '/usr/local'
+RANLIB = '/usr/bin/ranlib'
+RPATH_ST = '-Wl,-rpath,%s'
+SHLIB_MARKER = '-Wl,-Bdynamic'
+SONAME_ST = '-Wl,-h,%s'
+STATICLIBPATH_ST = '-L%s'
+STATICLIB_MARKER = '-Wl,-Bstatic'
+STATICLIB_ST = '-l%s'
+macbundle_PATTERN = '%s.bundle'
+program_PATTERN = '%s'
+shlib_CXXFLAGS = ['-fPIC', '-DPIC']
+shlib_LINKFLAGS = ['-shared']
+shlib_PATTERN = 'lib%s.so'
+staticlib_LINKFLAGS = ['-Wl,-Bstatic']
+staticlib_PATTERN = 'lib%s.a'
View
24 build/config.log
@@ -0,0 +1,24 @@
+# project configured on Thu Jan 14 13:43:34 2010 by
+# waf 1.5.10 (abi 7, python 20604f0 on linux2)
+# using /usr/local/bin/node-waf configure build
+#
+Checking for program g++,c++
+
+find program=['g++', 'c++'] paths=[] var='CXX' -> '/usr/bin/g++'
+
+Checking for program cpp
+
+find program=['cpp'] paths=[] var='CPP' -> '/usr/bin/cpp'
+
+Checking for program ar
+
+find program=['ar'] paths=[] var='AR' -> '/usr/bin/ar'
+
+Checking for program ranlib
+
+find program=['ranlib'] paths=[] var='RANLIB' -> '/usr/bin/ranlib'
+
+Checking for g++
+
+Checking for node prefix
+
View
BIN build/default/hashlib.node
Binary file not shown.
View
BIN build/default/hashlib_1.o
Binary file not shown.
View
156 hashlib.cc
@@ -1,47 +1,171 @@
#include <v8.h>
-//#include "lib/md5/md5.cpp"
-//#include "lib/md5/arc4.h"
+
#include "lib/md5/md5.c"
+#include "lib/sha/shamodule.c"
+#include "lib/sha/sha256module.c"
+#include "lib/sha/sha512module.c"
+
+#include "lib/md6/md6.h"
+#include "lib/md6/md6_compress.c"
+#include "lib/md6/md6_mode.c"
+
+//
+
#include <iostream>
-#include <string>
using namespace v8;
+Handle<Value>
+sha1(const Arguments& args)
+{
+ HandleScope scope;
+ using namespace sha1module;
+ String::Utf8Value data(args[0]->ToString());
+ unsigned char digest[40];
+ unsigned char hexdigest[40];
+ SHAobject *sha;
+ sha=new SHAobject;
+ sha_init(sha);
+ sha_update(sha, (unsigned char*) *data, data.length());
+ sha_final(digest, sha);
+ char chr;
+ int i, j;
+ for(i=j=0; i<20; i++) {
+ chr = (digest[i] >> 4) & 0xf;
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ chr = (digest[i] & 0xf);
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ }
+
+ return String::New((char*)hexdigest,40);
+}
+
Handle<Value>
-md5(const Arguments& args)
+sha256(const Arguments& args)
+{
+ HandleScope scope;
+ using namespace sha256module;
+ String::Utf8Value data(args[0]->ToString());
+ unsigned char digest[64];
+ unsigned char hexdigest[64];
+ SHAobject *sha;
+ sha=new SHAobject;
+ sha_init(sha);
+ sha_update(sha, (unsigned char*) *data, data.length());
+ sha_final(digest, sha);
+ char chr;
+ int i, j;
+ for(i=j=0; i<32; i++) {
+ chr = (digest[i] >> 4) & 0xf;
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ chr = (digest[i] & 0xf);
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ }
+
+ return String::New((char*)hexdigest,64);
+}
+
+Handle<Value>
+sha512(const Arguments& args)
+{
+ HandleScope scope;
+ using namespace sha512module;
+ String::Utf8Value data(args[0]->ToString());
+ unsigned char digest[128];
+ unsigned char hexdigest[128];
+ SHAobject *sha;
+ sha=new SHAobject;
+ sha512_init(sha);
+ sha512_update(sha, (unsigned char*) *data, data.length());
+ sha512_final(digest, sha);
+ char chr;
+ int i, j;
+ for(i=j=0; i<64; i++) {
+ chr = (digest[i] >> 4) & 0xf;
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ chr = (digest[i] & 0xf);
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ }
+
+ return String::New((char*)hexdigest,128);
+}
+
+
+Handle<Value>
+md6(const Arguments& args)
{
HandleScope scope;
String::Utf8Value data(args[0]->ToString());
+
+ int len(32);
+ if (!args[1]->IsUndefined()) {
+ len=args[1]->ToInteger()->Value();
+ }
+ unsigned char digest[len];
+ unsigned char hexdigest[len];
+ md6_hash(len*8, (unsigned char*) *data, data.length(), digest);
+ char chr;
+ int i, j;
+ int half_len=len/2;
+ if (len%2!=0) half_len++;
+
+ for(i=j=0; i<half_len; i++) {
+ chr = (digest[i] >> 4) & 0xf;
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ chr = (digest[i] & 0xf);
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ }
+
+ return String::New((char*)hexdigest,len);
+}
+
+Handle<Value>
+md5(const Arguments& args)
+{
+ HandleScope scope;
+
+ String::Utf8Value data(args[0]->ToString());
md5_state_t mdContext;
unsigned char digest[16];
unsigned char hexdigest[32];
- int i, j;
/* make an hash */
md5_init(&mdContext);
- md5_append(&mdContext,(unsigned char*) *data,data.length());
+ md5_append(&mdContext,(unsigned char*)*data,data.length());
md5_finish(&mdContext, digest);
-
- /* Make hex version of the digest */
+
+ int i, j;
for(i=j=0; i<16; i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hexdigest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hexdigest[j++] = c;
+ char chr;
+ chr = (digest[i] >> 4) & 0xf;
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
+ chr = (digest[i] & 0xf);
+ chr = (chr>9) ? chr+'a'-10 : chr + '0';
+ hexdigest[j++] = chr;
}
return String::New((char*)hexdigest,32);
}
-
extern "C" void init (Handle<Object> target)
{
HandleScope scope;
target->Set(String::New("md5"), FunctionTemplate::New(md5)->GetFunction());
+ target->Set(String::New("md6"), FunctionTemplate::New(md6)->GetFunction());
+ target->Set(String::New("sha"), FunctionTemplate::New(sha1)->GetFunction());
+ target->Set(String::New("sha1"), FunctionTemplate::New(sha1)->GetFunction());
+ target->Set(String::New("sha256"), FunctionTemplate::New(sha256)->GetFunction());
+ target->Set(String::New("sha512"), FunctionTemplate::New(sha512)->GetFunction());
}
View
16 lib/md6/README_Reference.txt
@@ -0,0 +1,16 @@
+Filename: README_Reference.txt
+Author: Ronald L. Rivest
+Date: 8/31/08
+
+This directory (Reference_Implementation) contains the
+required reference implementation for our NIST SHA-3
+submission, "MD6".
+
+The files included here are:
+ md6.h
+ md6_compress.c
+ md6_mode.c
+ md6_nist.h
+ md6_nist.c
+ inttypes.h
+ stdint.h
View
305 lib/md6/inttypes.h
@@ -0,0 +1,305 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]
View
443 lib/md6/md6.h
@@ -0,0 +1,443 @@
+/* File: md6.h
+** Author: Ronald L. Rivest
+** Address: Room 32G-692 Stata Center
+** 32 Vassar Street
+** Cambridge, MA 02139
+** Email: rivest@mit.edu
+** Date: 1/15/2009 (see changelog below)
+**
+** (The following license is known as "The MIT License")
+**
+** Copyright (c) 2008 Ronald L. Rivest
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+** (end of license)
+**
+** This file is part of the definition of the MD6 hash function.
+** The files defining the MD6 hash function are:
+** md6.h
+** md6_compress.c
+** md6_mode.
+** (Note that md6.h includes inttypes.h, which includes stdint.h;
+** versions of these header files compatible with MS Visual Studio
+** are available, as noted below.)
+**
+** The files defining the interface between MD6 and the NIST SHA-3
+** API are:
+** md6_nist.h
+** md6_nist.c
+** The NIST SHA-3 API is defined in:
+** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf
+**
+** See http://groups.csail.mit.edu/cis/md6 for more information.
+**
+** These files define the ``standard'' version of MD6. However,
+** they are written in such a way that one may relatively easily
+** define and experiment with ``variant'' versions.
+**
+** Changelog:
+** 1/15/2009: length of md6_state.hashval doubled (to 128 bytes)
+** to avoid buffer overflow issue found by Fortify.
+** (Change does not affect hash values computed, though.)
+*/
+
+/* Prevent multiple includes
+** Matching endif is at end of md6.h
+*/
+#ifndef MD6_H_INCLUDED
+#define MD6_H_INCLUDED
+
+
+ /* inttypes.h (which includes stdint.h)
+** inttypes.h and stdint.h are part of the normal environment
+** for gcc, but not for MS Visual Studio. Fortunately,
+** compatible implementations are available from Google at:
+** http://msinttypes.googlecode.com/svn/trunk/stdint.h
+** http://msinttypes.googlecode.com/svn/trunk/inttypes.h
+** If these two files are in the same directory as md6.h, then
+** MD6 will compile OK with MS Visual Studio.
+*/
+#if defined _MSC_VER
+#include "inttypes.h"
+#else
+#include <inttypes.h>
+#endif
+
+ /* MD6 wordsize.
+**
+** Define md6 wordsize md6_w, in bits.
+** Note that this is the "word size" relevant to the
+** definition of md6 (it defines how many bits in an
+** "md6_word"); it does *not* refer to the word size
+** on the platform for which this is being compiled.
+*/
+
+#define md6_w 64
+
+/* Define "md6_word" appropriately for given value of md6_w.
+** Also define PR_MD6_WORD to be the appropriate hex format string,
+** using the format strings from inttypes.h .
+** The term `word' in comments means an `md6_word'.
+*/
+
+#if (md6_w==64) /* standard md6 */
+typedef uint64_t md6_word;
+#define PR_MD6_WORD "%.16" PRIx64
+
+#elif (md6_w==32) /* nonstandard variant */
+typedef uint32_t md6_word;
+#define PR_MD6_WORD "%.8" PRIx32
+
+#elif (md6_w==16) /* nonstandard variant */
+typedef uint16_t md6_word;
+#define PR_MD6_WORD "%.4" PRIx16
+
+#elif (md6_w==8) /* nonstandard variant */
+typedef uint8_t md6_word;
+#define PR_MD6_WORD "%.2" PRIx8
+
+#endif
+
+ /* MD6 compression function.
+**
+** MD6 compression function is defined in file md6_compress.c
+*/
+
+/* MD6 compression function constants */
+
+#define md6_n 89 /* size of compression input block, in words */
+#define md6_c 16 /* size of compression output, in words */
+ /* a c-word block is also called a "chunk" */
+#define md6_max_r 255 /* max allowable value for number r of rounds */
+
+/* Compression function routines
+** These are ``internal'' routines that need not be called for
+** ordinary md6 usage.
+*/
+
+extern int md6_default_r( int d, /* returns default r for given d */
+ int keylen /* and keylen */
+ );
+
+void md6_main_compression_loop( md6_word *A, /* working array */
+ int r /* number of rounds */
+ );
+
+int md6_compress( md6_word *C, /* output */
+ md6_word *N, /* input */
+ int r, /* number rounds */
+ md6_word *A /* (optional) working array, may be NULL */
+ );
+
+
+typedef uint64_t md6_control_word; /* (r,L,z,p,d) */
+md6_control_word md6_make_control_word( int r, /* number rounds */
+ int L, /* parallel passes */
+ int z, /* final node flag */
+ int p, /* padding bits */
+ int keylen, /* bytes in key */
+ int d /* digest size */
+ );
+
+typedef uint64_t md6_nodeID; /* (ell,i) */
+md6_nodeID md6_make_nodeID( int ell, /* level number */
+ int i /* index (0,1,2,...) within level */
+ );
+
+void md6_pack( md6_word* N, /* output */
+ const md6_word* Q, /* fractional part sqrt(6) */
+ md6_word* K, /* key */
+ int ell, int i, /* for U */
+ int r, int L, int z, int p, int keylen, int d, /* for V */
+ md6_word* B /* data input */
+ );
+
+int md6_standard_compress(
+ md6_word *C, /* output */
+ const md6_word *Q, /* fractional part sqrt(6) */
+ md6_word *K, /* key */
+ int ell, int i, /* for U */
+ int r, int L, int z, int p, int keylen, int d, /* for V */
+ md6_word* B /* data input */
+ );
+
+ /* MD6 mode of operation.
+**
+** MD6 mode of operation is defined in file md6_mode.c
+*/
+
+/* MD6 constants related to standard mode of operation */
+
+/* These five values give lengths of the components of compression */
+/* input block; they should sum to md6_n. */
+#define md6_q 15 /* # Q words in compression block (>=0) */
+#define md6_k 8 /* # key words per compression block (>=0) */
+#define md6_u (64/md6_w) /* # words for unique node ID (0 or 64/w) */
+#define md6_v (64/md6_w) /* # words for control word (0 or 64/w) */
+#define md6_b 64 /* # data words per compression block (>0) */
+
+#define md6_default_L 64 /* large so that MD6 is fully hierarchical */
+
+#define md6_max_stack_height 29
+ /* max_stack_height determines the maximum number of bits that
+ ** can be processed by this implementation (with default L) to be:
+ ** (b*w) * ((b/c) ** (max_stack_height-3)
+ ** = 2 ** 64 for b = 64, w = 64, c = 16, and max_stack_height = 29
+ ** (We lose three off the height since level 0 is unused,
+ ** level 1 contains the input data, and C has 0-origin indexing.)
+ ** The smallest workable value for md6_max_stack_height is 3.
+ ** (To avoid stack overflow for non-default L values,
+ ** we should have max_stack_height >= L + 2.)
+ ** (One level of storage could be saved by letting st->N[] use
+ ** 1-origin indexing, since st->N[0] is now unused.)
+ */
+
+ /* MD6 state.
+**
+** md6_state is the main data structure for the MD6 hash function.
+*/
+
+typedef struct {
+
+ int d; /* desired hash bit length. 1 <= d <= 512. */
+ int hashbitlen; /* hashbitlen is the same as d; for NIST API */
+
+ unsigned char hashval[ md6_c*(md6_w/8) ];
+ /* e.g. unsigned char hashval[128] */
+ /* contains hashval after call to md6_final */
+ /* hashval appears in first floor(d/8) bytes, with */
+ /* remaining (d mod 8) bits (if any) appearing in */
+ /* high-order bit positions of hashval[1+floor(d/8)]. */
+
+ unsigned char hexhashval[(md6_c*(md6_w/8))+1];
+ /* e.g. unsigned char hexhashval[129]; */
+ /* zero-terminated string representing hex value of hashval */
+
+ int initialized; /* zero, then one after md6_init called */
+ uint64_t bits_processed; /* bits processed so far */
+ uint64_t compression_calls; /* compression function calls made*/
+ int finalized; /* zero, then one after md6_final called */
+
+ md6_word K[ md6_k ];
+ /* k-word (8 word) key (aka "salt") for this instance of md6 */
+ int keylen;
+ /* number of bytes in key K. 0<=keylen<=k*(w/8) */
+
+ int L;
+ /* md6 mode specification parameter. 0 <= L <= 255 */
+ /* L == 0 means purely sequential (Merkle-Damgaard) */
+ /* L >= 29 means purely tree-based */
+ /* Default is md6_default_L = 64 (hierarchical) */
+
+ int r;
+ /* Number of rounds. 0 <= r <= 255 */
+
+ int top;
+ /* index of block corresponding to top of stack */
+
+ md6_word B[ md6_max_stack_height ][ md6_b ];
+ /* md6_word B[29][64] */
+ /* stack of 29 64-word partial blocks waiting to be */
+ /* completed and compressed. */
+ /* B[1] is for compressing text data (input); */
+ /* B[ell] corresponds to node at level ell in the tree. */
+
+ unsigned int bits[ md6_max_stack_height ];
+ /* bits[ell] = */
+ /* number of bits already placed in B[ell] */
+ /* for 1 <= ell < max_stack_height */
+ /* 0 <= bits[ell] <= b*w */
+
+ uint64_t i_for_level[ md6_max_stack_height ];
+ /* i_for_level[ell] = */
+ /* index of the node B[ ell ] on this level (0,1,...) */
+ /* when it is output */
+
+} md6_state;
+ /* MD6 main interface routines
+**
+** These routines are defined in md6_mode.c
+*/
+
+/* The next routines are used according to the pattern:
+** md6_init (or md6_full_init if you use additional parameters)
+** md6_update (once for each portion of the data to be hashed)
+** md6_final (to finish up hash computation)
+** Note: md6_final can return the hash value to a desired location, but
+** hash value also remains available inside the md6_state, in both binary
+** and hex formats (st->hashval and st->hexhashval).
+*/
+
+extern int md6_init( md6_state *st, /* state to initialize */
+ int d /* hash bit length */
+ );
+
+extern int md6_full_init( md6_state *st, /* state to initialize */
+ int d, /* hash bit length */
+ unsigned char *key, /* OK to give NULL */
+ int keylen, /* (in bytes) OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r /* number of rounds */
+ );
+
+extern int md6_update( md6_state *st, /* initialized state */
+ unsigned char *data, /* data portion */
+ uint64_t databitlen /* its length in bits */
+ );
+
+extern int md6_final( md6_state *st, /* initialized/updated */
+ unsigned char *hashval /* output; NULL OK */
+ );
+
+ /* MD6 main interface routines
+**
+** These routines are defined in md6_mode.c
+**
+** These routines compute a hash for a message given all at once.
+** The resulting hash value is returned to a specified location.
+** Only one call is needed. Use md6_hash for the standard md6 hash,
+** and md6_full_hash if you want to specify additional parameters.
+*/
+
+extern int md6_hash( int d, /* hash bit length */
+ unsigned char *data, /* complete data to hash */
+ uint64_t databitlen, /* its length in bits */
+ unsigned char *hashval /* output */
+ );
+
+extern int md6_full_hash( int d, /* hash bit length */
+ unsigned char *data,/* complete data to hash */
+ uint64_t databitlen, /* its length in bits */
+ unsigned char *key, /* OK to give NULL */
+ int keylen, /* (in bytes) OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r, /* number of rounds */
+ unsigned char *hashval /* output */
+ );
+
+
+ /* MD6 return codes.
+**
+** The interface routines defined in md6_mode.c always return a
+** "return code": an integer giving the status of the call.
+** The codes
+** SUCCESS, FAIL, and BADHASHLEN same as for NIST API
+*/
+
+/* SUCCESS: */
+#define MD6_SUCCESS 0
+
+/* ERROR CODES: */
+#define MD6_FAIL 1 /* some other problem */
+#define MD6_BADHASHLEN 2 /* hashbitlen<1 or >512 bits */
+#define MD6_NULLSTATE 3 /* null state passed to MD6 */
+#define MD6_BADKEYLEN 4 /* key length is <0 or >512 bits */
+#define MD6_STATENOTINIT 5 /* state was never initialized */
+#define MD6_STACKUNDERFLOW 6 /* MD6 stack underflows (shouldn't happen)*/
+#define MD6_STACKOVERFLOW 7 /* MD6 stack overflow (message too long) */
+#define MD6_NULLDATA 8 /* null data pointer */
+#define MD6_NULL_N 9 /* compress: N is null */
+#define MD6_NULL_B 10 /* standard compress: null B pointer */
+#define MD6_BAD_ELL 11 /* standard compress: ell not in {0,255} */
+#define MD6_BAD_p 12 /* standard compress: p<0 or p>b*w */
+#define MD6_NULL_K 13 /* standard compress: K is null */
+#define MD6_NULL_Q 14 /* standard compress: Q is null */
+#define MD6_NULL_C 15 /* standard compress: C is null */
+#define MD6_BAD_L 16 /* standard compress: L <0 or > 255 */
+ /* md6_init: L<0 or L>255 */
+#define MD6_BAD_r 17 /* compress: r<0 or r>255 */
+ /* md6_init: r<0 or r>255 */
+#define MD6_OUT_OF_MEMORY 18 /* compress: storage allocation failed */
+
+
+/* The following code confirms that the defined MD6 constants satisfy
+** some expected properties. These tests should never fail; consider
+** these tests to be documentation. Failure of these tests would cause
+** compilation to fail.
+*/
+
+#if ( (md6_w!=8) && (md6_w!=16) && (md6_w!=32) && (md6_w!=64) )
+ #error "md6.h Fatal error: md6_w must be one of 8,16,32, or 64."
+#elif ( md6_n<=0 )
+ #error "md6.h Fatal error: md6_n must be positive."
+#elif ( md6_b<=0 )
+ #error "md6.h Fatal error: md6_b must be positive."
+#elif ( md6_c<=0 )
+ #error "md6.h Fatal error: md6_c must be positive."
+#elif ( md6_v<0 )
+ #error "md6.h Fatal error: md6_v must be nonnegative."
+#elif ( md6_u<0 )
+ #error "md6.h Fatal error: md6_u must be nonnegative."
+#elif ( md6_k<0 )
+ #error "md6.h Fatal error: md6_k must be nonnegative."
+#elif ( md6_q<0 )
+ #error "md6.h Fatal error: md6_q must be nonnegative."
+#elif ( md6_b>=md6_n )
+ #error "md6.h Fatal error: md6_b must be smaller than md6_n."
+#elif ( md6_c>=md6_b )
+ #error "md6.h Fatal error: md6_c must be smaller than md6_b."
+#elif ( (md6_b%md6_c)!=0 )
+ #error "md6.h Fatal error: md6_b must be a multiple of md6_c."
+#elif ( md6_n != md6_b + md6_v + md6_u + md6_k + md6_q )
+ #error "md6.h Fatal error: md6_n must = md6_b + md6_v + md6_u + md6_k + md6_q."
+#elif ( md6_max_stack_height < 3 )
+ #error "md6.h Fatal error: md6_max_stack_height must be at least 3."
+#elif ( md6_r * md6_c + md6_n >= 5000 )
+ /* since md6_standard_compress allocates fixed-size array A[5000] */
+ #error "md6.h Fatal error: r*c+n must be < 5000."
+#if 0
+ /* "sizeof" doesn't work in preprocessor, these checks don't work */
+ #elif ( (md6_v != 0) && (md6_v != (sizeof(md6_control_word)/(md6_w/8))) )
+ #error "md6.h Fatal error: md6_v must be 0 or match md6_control_word size."
+ #elif ( (md6_u != 0) && (md6_u != (sizeof(md6_nodeID)/(md6_w/8))) )
+ #error "md6.h Fatal error: md6_u must be 0 or match md6_nodeID size."
+#endif
+#endif
+
+
+/* Debugging and testing.
+*/
+
+/* compression hook, if defined, points to a function that is
+** called after each compression operation.
+**
+** compression hook must be set *after* md6_init or md6_full_init
+** is called.
+*/
+
+void (* compression_hook)(md6_word *C,
+ const md6_word *Q,
+ md6_word *K,
+ int ell,
+ int i,
+ int r,
+ int L,
+ int z,
+ int p,
+ int keylen,
+ int d,
+ md6_word *N
+ );
+
+/* end of #ifndef MD6_H_INCLUDED for multiple inclusion protection
+*/
+#endif
+
+/* end of md6.h */
View
444 lib/md6/md6_compress.c
@@ -0,0 +1,444 @@
+/* File: md6_compress.c
+** Author: Ronald L. Rivest
+** (with optimizations by Jayant Krishnamurthy)
+** Address: Room 32G-692 Stata Center
+** 32 Vassar Street
+** Cambridge, MA 02139
+** Email: rivest@mit.edu
+** Date: 9/25/2008
+**
+** (The following license is known as "The MIT License")
+**
+** Copyright (c) 2008 Ronald L. Rivest and Jayant Krishnamurthy
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+** (end of license)
+**
+** This is part of the definition of the MD6 hash function.
+** The files defining the md6 hash function are:
+** md6.h
+** md6_compress.c
+** md6_mode.c
+**
+** The files defining the interface between MD6 and the NIST SHA-3
+** API are:
+** md6_nist.h
+** md6_nist.c
+** The NIST SHA-3 API is defined in:
+** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf
+**
+** See http://groups.csail.mit.edu/cis/md6 for more information.
+**
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "md6.h"
+
+/* Useful macros: min and max */
+#ifndef min
+#define min(a,b) ((a)<(b)? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a)>(b)? (a) : (b))
+#endif
+
+/* Variables defining lengths of various values */
+#define w md6_w /* # bits in a word (64) */
+#define n md6_n /* # words in compression input (89) */
+#define c md6_c /* # words in compression output (16) */
+#define b md6_b /* # message words per compression input block (64) */
+#define v md6_v /* # words in control word (1) */
+#define u md6_u /* # words in unique nodeID (1) */
+#define k md6_k /* # key words per compression input block (8) */
+#define q md6_q /* # Q words per compression input block (15) */
+
+
+/* "Tap positions" for feedback shift-register */
+
+#if (n==89)
+#define t0 17 /* index for linear feedback */
+#define t1 18 /* index for first input to first and */
+#define t2 21 /* index for second input to first and */
+#define t3 31 /* index for first input to second and */
+#define t4 67 /* index for second input to second and */
+#define t5 89 /* last tap */
+#endif
+
+/* Loop-unrolling setup.
+**
+** Define macros for loop-unrolling within compression function
+** These expand to: loop_body(right-shift,left-shift,step)
+** These are given for word sizes 64, 32, 16, and 8, although
+** only w=64 is needed for the standard MD6 definition.
+**
+** Also given for each word size are the constants S0 and Smask
+** needed in the recurrence for round constants.
+*/
+
+#if (w==64) /* for standard word size */
+#define RL00 loop_body(10,11, 0)
+#define RL01 loop_body( 5,24, 1)
+#define RL02 loop_body(13, 9, 2)
+#define RL03 loop_body(10,16, 3)
+#define RL04 loop_body(11,15, 4)
+#define RL05 loop_body(12, 9, 5)
+#define RL06 loop_body( 2,27, 6)
+#define RL07 loop_body( 7,15, 7)
+#define RL08 loop_body(14, 6, 8)
+#define RL09 loop_body(15, 2, 9)
+#define RL10 loop_body( 7,29,10)
+#define RL11 loop_body(13, 8,11)
+#define RL12 loop_body(11,15,12)
+#define RL13 loop_body( 7, 5,13)
+#define RL14 loop_body( 6,31,14)
+#define RL15 loop_body(12, 9,15)
+
+const md6_word S0 = (md6_word)0x0123456789abcdefULL;
+const md6_word Smask = (md6_word)0x7311c2812425cfa0ULL;
+
+#elif (w==32) /* for variant word size */
+#define RL00 loop_body( 5, 4, 0)
+#define RL01 loop_body( 3, 7, 1)
+#define RL02 loop_body( 6, 7, 2)
+#define RL03 loop_body( 5, 9, 3)
+#define RL04 loop_body( 4,13, 4)
+#define RL05 loop_body( 6, 8, 5)
+#define RL06 loop_body( 7, 4, 6)
+#define RL07 loop_body( 3,14, 7)
+#define RL08 loop_body( 5, 7, 8)
+#define RL09 loop_body( 6, 4, 9)
+#define RL10 loop_body( 5, 8,10)
+#define RL11 loop_body( 5,11,11)
+#define RL12 loop_body( 4, 5,12)
+#define RL13 loop_body( 6, 8,13)
+#define RL14 loop_body( 7, 2,14)
+#define RL15 loop_body( 5,11,15)
+
+const md6_word S0 = (md6_word)0x01234567UL;
+const md6_word Smask = (md6_word)0x7311c281UL;
+
+/* Loop-unrolling setup (continued).
+**
+*/
+
+#elif (w==16) /* for variant word size */
+
+#define RL00 loop_body( 5, 6, 0)
+#define RL01 loop_body( 4, 7, 1)
+#define RL02 loop_body( 3, 2, 2)
+#define RL03 loop_body( 5, 4, 3)
+#define RL04 loop_body( 7, 2, 4)
+#define RL05 loop_body( 5, 6, 5)
+#define RL06 loop_body( 5, 3, 6)
+#define RL07 loop_body( 2, 7, 7)
+#define RL08 loop_body( 4, 5, 8)
+#define RL09 loop_body( 3, 7, 9)
+#define RL10 loop_body( 4, 6,10)
+#define RL11 loop_body( 3, 5,11)
+#define RL12 loop_body( 4, 5,12)
+#define RL13 loop_body( 7, 6,13)
+#define RL14 loop_body( 7, 4,14)
+#define RL15 loop_body( 2, 3,15)
+
+const md6_word S0 = (md6_word)0x01234;
+const md6_word Smask = (md6_word)0x7311;
+
+#elif (w==8) /* for variant word size */
+
+#define RL00 loop_body( 3, 2, 0)
+#define RL01 loop_body( 3, 4, 1)
+#define RL02 loop_body( 3, 2, 2)
+#define RL03 loop_body( 4, 3, 3)
+#define RL04 loop_body( 3, 2, 4)
+#define RL05 loop_body( 3, 2, 5)
+#define RL06 loop_body( 3, 2, 6)
+#define RL07 loop_body( 3, 4, 7)
+#define RL08 loop_body( 2, 3, 8)
+#define RL09 loop_body( 2, 3, 9)
+#define RL10 loop_body( 3, 2,10)
+#define RL11 loop_body( 2, 3,11)
+#define RL12 loop_body( 2, 3,12)
+#define RL13 loop_body( 3, 4,13)
+#define RL14 loop_body( 2, 3,14)
+#define RL15 loop_body( 3, 4,15)
+
+const md6_word S0 = (md6_word)0x01;
+const md6_word Smask = (md6_word)0x73;
+
+#endif
+
+/* Main compression loop.
+**
+*/
+
+void md6_main_compression_loop( md6_word* A , int r )
+/*
+** Perform the md6 "main compression loop" on the array A.
+** This is where most of the computation occurs; it is the "heart"
+** of the md6 compression algorithm.
+** Input:
+** A input array of length t+n already set up
+** with input in the first n words.
+** r number of rounds to run (178); each is c steps
+** Modifies:
+** A A[n..r*c+n-1] filled in.
+*/
+{ md6_word x, S;
+ int i,j;
+
+ /*
+ ** main computation loop for md6 compression
+ */
+ S = S0;
+ for (j = 0, i = n; j<r*c; j+=c)
+ {
+
+/* ***************************************************************** */
+#define loop_body(rs,ls,step) \
+ x = S; /* feedback constant */ \
+ x ^= A[i+step-t5]; /* end-around feedback */ \
+ x ^= A[i+step-t0]; /* linear feedback */ \
+ x ^= ( A[i+step-t1] & A[i+step-t2] ); /* first quadratic term */ \
+ x ^= ( A[i+step-t3] & A[i+step-t4] ); /* second quadratic term */ \
+ x ^= (x >> rs); /* right-shift */ \
+ A[i+step] = x ^ (x << ls); /* left-shift */
+/* ***************************************************************** */
+
+ /*
+ ** Unroll loop c=16 times. (One "round" of computation.)
+ ** Shift amounts are embedded in macros RLnn.
+ */
+ RL00 RL01 RL02 RL03 RL04 RL05 RL06 RL07
+ RL08 RL09 RL10 RL11 RL12 RL13 RL14 RL15
+
+ /* Advance round constant S to the next round constant. */
+ S = (S << 1) ^ (S >> (w-1)) ^ (S & Smask);
+ i += 16;
+ }
+}
+
+/* ``Bare'' compression routine.
+**
+** Compresses n-word input to c-word output.
+*/
+
+int md6_compress( md6_word *C,
+ md6_word *N,
+ int r,
+ md6_word *A
+ )
+/* Assumes n-word input array N has been fully set up.
+** Input:
+** N input array of n w-bit words (n=89)
+** A working array of a = rc+n w-bit words
+** A is OPTIONAL, may be given as NULL
+** (then md6_compress allocates and uses its own A).
+** r number of rounds
+** Modifies:
+** C output array of c w-bit words (c=16)
+** Returns one of the following:
+** MD6_SUCCESS (0)
+** MD6_NULL_N
+** MD6_NULL_C
+** MD6_BAD_r
+** MD6_OUT_OF_MEMORY
+*/
+{ md6_word* A_as_given = A;
+
+ /* check that input is sensible */
+ if ( N == NULL) return MD6_NULL_N;
+ if ( C == NULL) return MD6_NULL_C;
+ if ( r<0 || r > md6_max_r) return MD6_BAD_r;
+
+ if ( A == NULL) A = (md6_word*)calloc(r*c+n,sizeof(md6_word));
+ if ( A == NULL) return MD6_OUT_OF_MEMORY;
+
+ memcpy( A, N, n*sizeof(md6_word) ); /* copy N to front of A */
+
+ md6_main_compression_loop( A, r ); /* do all the work */
+
+ memcpy( C, A+(r-1)*c+n, c*sizeof(md6_word) ); /* output into C */
+
+ if ( A_as_given == NULL ) /* zero and free A if nec. */
+ { memset(A,0,(r*c+n)*sizeof(md6_word)); /* contains key info */
+ free(A);
+ }
+
+ return MD6_SUCCESS;
+}
+
+/* Control words.
+*/
+
+md6_control_word md6_make_control_word( int r,
+ int L,
+ int z,
+ int p,
+ int keylen,
+ int d
+ )
+/* Construct control word V for given inputs.
+** Input:
+** r = number of rounds
+** L = mode parameter (maximum tree height)
+** z = 1 iff this is final compression operation
+** p = number of pad bits in a block to be compressed
+** keylen = number of bytes in key
+** d = desired hash output length
+** Does not check inputs for validity.
+** Returns:
+** V = constructed control word
+*/
+{ md6_control_word V;
+ V = ( (((md6_control_word) 0) << 60) | /* reserved, width 4 bits */
+ (((md6_control_word) r) << 48) | /* width 12 bits */
+ (((md6_control_word) L) << 40) | /* width 8 bits */
+ (((md6_control_word) z) << 36) | /* width 4 bits */
+ (((md6_control_word) p) << 20) | /* width 16 bits */
+ (((md6_control_word) keylen) << 12 ) | /* width 8 bits */
+ (((md6_control_word) d)) ); /* width 12 bits */
+ return V;
+}
+
+/* Node ID's.
+*/
+
+md6_nodeID md6_make_nodeID( int ell, /* level number */
+ int i /* index (0,1,2,...) within level */
+ )
+/* Make "unique nodeID" U based on level ell and position i
+** within level; place it at specified destination.
+** Inputs:
+** dest = address of where nodeID U should be placed
+** ell = integer level number, 1 <= ell <= ...
+** i = index within level, i = 0, 1, 2,...
+** Returns
+** U = constructed nodeID
+*/
+{ md6_nodeID U;
+ U = ( (((md6_nodeID) ell) << 56) |
+ ((md6_nodeID) i) );
+ return U;
+}
+
+/* Assembling components of compression input.
+*/
+
+void md6_pack( md6_word*N,
+ const md6_word* Q,
+ md6_word* K,
+ int ell, int i,
+ int r, int L, int z, int p, int keylen, int d,
+ md6_word* B )
+/* Pack data before compression into n-word array N.
+*/
+{ int j;
+ int ni;
+ md6_nodeID U;
+ md6_control_word V;
+
+ ni = 0;
+
+ for (j=0;j<q;j++) N[ni++] = Q[j]; /* Q: Q in words 0--14 */
+
+ for (j=0;j<k;j++) N[ni++] = K[j]; /* K: key in words 15--22 */
+
+ U = md6_make_nodeID(ell,i); /* U: unique node ID in 23 */
+ /* The following also works for variants
+ ** in which u=0.
+ */
+ memcpy((unsigned char *)&N[ni],
+ &U,
+ min(u*(w/8),sizeof(md6_nodeID)));
+ ni += u;
+
+ V = md6_make_control_word(
+ r,L,z,p,keylen,d);/* V: control word in 24 */
+ /* The following also works for variants
+ ** in which v=0.
+ */
+ memcpy((unsigned char *)&N[ni],
+ &V,
+ min(v*(w/8),sizeof(md6_control_word)));
+ ni += v;
+
+ memcpy(N+ni,B,b*sizeof(md6_word)); /* B: data words 25--88 */
+}
+
+/* Standard compress: assemble components and then compress
+*/
+
+int md6_standard_compress( md6_word* C,
+ const md6_word* Q,
+ md6_word* K,
+ int ell, int i,
+ int r, int L, int z, int p, int keylen, int d,
+ md6_word* B
+ )
+/* Perform md6 block compression using all the "standard" inputs.
+** Input:
+** Q q-word (q=15) approximation to (sqrt(6)-2)
+** K k-word key input (k=8)
+** ell level number
+** i index within level
+** r number of rounds in this compression operation
+** L mode parameter (max tree height)
+** z 1 iff this is the very last compression
+** p number of padding bits of input in payload B
+** keylen number of bytes in key
+** d desired output hash bit length
+** B b-word (64-word) data input block (with zero padding)
+** Modifies:
+** C c-word output array (c=16)
+** Returns one of the following:
+** MD6_SUCCESS (0) MD6_BAD_p
+** MD6_NULL_B MD6_BAD_HASHLEN
+** MD6_NULL_C MD6_NULL_K
+** MD6_BAD_r MD6_NULL_Q
+** MD6_BAD_ELL MD6_OUT_OF_MEMORY
+*/
+{ md6_word N[md6_n];
+ md6_word A[5000]; /* MS VS can't handle variable size here */
+
+ /* check that input values are sensible */
+ if ( (C == NULL) ) return MD6_NULL_C;
+ if ( (B == NULL) ) return MD6_NULL_B;
+ if ( (r<0) | (r>md6_max_r) ) return MD6_BAD_r;
+ if ( (L<0) | (L>255) ) return MD6_BAD_L;
+ if ( (ell < 0) || (ell > 255) ) return MD6_BAD_ELL;
+ if ( (p < 0) || (p > b*w ) ) return MD6_BAD_p;
+ if ( (d <= 0) || (d > c*w/2) ) return MD6_BADHASHLEN;
+ if ( (K == NULL) ) return MD6_NULL_K;
+ if ( (Q == NULL) ) return MD6_NULL_Q;
+
+ /* pack components into N for compression */
+ md6_pack(N,Q,K,ell,i,r,L,z,p,keylen,d,B);
+
+ /* call compression hook if it is defined. */
+ /* -- for testing and debugging. */
+ if (compression_hook != NULL)
+ compression_hook(C,Q,K,ell,i,r,L,z,p,keylen,d,B);
+
+ return md6_compress(C,N,r,A);
+}
+/* end of md6_compress.c */
View
881 lib/md6/md6_mode.c
@@ -0,0 +1,881 @@
+/* File: md6_mode.c
+** Author: Ronald L. Rivest
+** Address: Room 32G-692 Stata Center
+** 32 Vassar Street
+** Cambridge, MA 02139
+** Email: rivest@mit.edu
+** Date: 9/25/2008
+** revised 4/15/09 (see changelog below)
+**
+** (The following license is known as "The MIT License")
+**
+** Copyright (c) 2008 Ronald L. Rivest
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+** (end of license)
+**
+** This is part of the definition of the MD6 hash function.
+** The files defining the md6 hash function are:
+** md6.h
+** md6_compress.c
+** md6_mode.c
+**
+** The files defining the interface between MD6 and the NIST SHA-3
+** API are:
+** md6_nist.h
+** md6_nist.c
+** The NIST SHA-3 API is defined in:
+** http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf
+**
+** See http://groups.csail.mit.edu/cis/md6 for more information.
+**
+** Changelog:
+** 4/15/09: In routine "md6_final", transposed two lines so that
+** they are now in the correct order, which is:
+**
+** trim_hashval( st );
+** if (hashval != NULL) memcpy( hashval, st->hashval, (st->d+7)/8 );
+**
+** This fixes problem that caller could get incorrect output
+** if it took output from parameter hashval rather than from
+** state variable st->hashval. If caller used the nist api
+** (md6_nist.c), or used the md6 api with a non-NULL second
+** argument to md6_final, or used md6_hash or md6_full_hash,
+** caller would have obtained an incorrect value (basically,
+** the first d bits of the final root chaining value rather
+** than the last d bits). If the caller used md6sum, or used
+** md6_final with a NULL second argument, the correct value
+** is obtained. See changelog file for more discussion.
+**
+** Thanks to Piotr Krysiuk for finding and reporting
+** this error!
+*/
+ /* MD6 standard mode of operation
+**
+** Defines the following interfaces (documentation copied from md6.h)
+*/
+#if 0
+
+/* The next routines are used according to the pattern:
+** md6_init (or md6_full_init if you use additional parameters)
+** md6_update (once for each portion of the data to be hashed)
+** md6_final (to finish up hash computation)
+** Note: md6_final can return the hash value to a desired location, but
+** hash value also remains available inside the md6_state, in both binary
+** and hex formats (state->hashval and state->hexhashval).
+*/
+
+extern int md6_init( md6_state *st, /* state to initialize */
+ int d /* hash bit length */
+ );
+
+extern int md6_full_init( md6_state *st, /* state to initialize */
+ int d, /* hash bit length */
+ unsigned char *key, /* OK to give NULL */
+ int keylen, /* (in bytes) OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r /* number of rounds */
+ );
+
+extern int md6_update( md6_state *st, /* initialized state */
+ unsigned char *data, /* data portion */
+ uint64_t datalen /* its length in bits */
+ );
+
+extern int md6_final( md6_state *st, /* initialized/updated */
+ unsigned char *hashval, /* output; NULL OK */
+ );
+
+/* The next routines compute a hash for a message given all at once.
+** The resulting hash value is returned to a specified location.
+** Only one call is needed. Use md6_hash for the standard md6 hash,
+** and md6_full_hash if you want to specify additional parameters.
+*/
+
+extern int md6_hash( int d, /* hash bit length */
+ unsigned char *data, /* complete data to hash */
+ uint64_t datalen /* its length in bits */
+ unsigned char *hashval, /* output */
+ );
+
+extern int md6_full_hash( int d, /* hash bit length */
+ unsigned char *data,/* complete data to hash */
+ uint64_t datalen, /* its length in bits */
+ unsigned char *key, /* OK to give NULL */
+ int keylen, /* (in bytes) OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r, /* number of rounds */
+ unsigned char *hashval, /* output */
+ );
+#endif
+
+ #include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "md6.h"
+
+/* MD6 constants independent of mode of operation (from md6.h) */
+#define w md6_w /* # bits in a word (64) */
+#define n md6_n /* # words in compression input (89) */
+#define c md6_c /* # words in compression output (16) */
+
+/* MD6 constants needed for mode of operation */
+#define q md6_q /* # words in Q (15) */
+#define k md6_k /* # words in key (aka salt) (8) */
+#define u md6_u /* # words in unique node ID (1) */
+#define v md6_v /* # words in control word (1) */
+#define b md6_b /* # data words per compression block (64) */
+
+/* Useful macros: min and max */
+#ifndef min
+#define min(a,b) ((a)<(b)? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a)>(b)? (a) : (b))
+#endif
+
+/* Default number of rounds */
+/* (as a function of digest size d and keylen */
+int md6_default_r( int d ,
+ int keylen )
+{ int r;
+ /* Default number of rounds is forty plus floor(d/4) */
+ r = 40 + (d/4);
+ /* unless keylen > 0, in which case it must be >= 80 as well */
+ if (keylen>0)
+ r = max(80,r);
+ return r;
+}
+
+
+/* MD6 Constant Vector Q
+** Q = initial 960 bits of fractional part of sqrt(6)
+**
+** Given here for w = 64, 32, 16, and 8, although only
+** w = 64 is needed for the standard version of MD6.
+*/
+
+#if (w==64) /* for standard version */
+/* 15 64-bit words */
+static const md6_word Q[15] =
+ {
+ 0x7311c2812425cfa0ULL,
+ 0x6432286434aac8e7ULL,
+ 0xb60450e9ef68b7c1ULL,
+ 0xe8fb23908d9f06f1ULL,
+ 0xdd2e76cba691e5bfULL,
+ 0x0cd0d63b2c30bc41ULL,
+ 0x1f8ccf6823058f8aULL,
+ 0x54e5ed5b88e3775dULL,
+ 0x4ad12aae0a6d6031ULL,
+ 0x3e7f16bb88222e0dULL,
+ 0x8af8671d3fb50c2cULL,
+ 0x995ad1178bd25c31ULL,
+ 0xc878c1dd04c4b633ULL,
+ 0x3b72066c7a1552acULL,
+ 0x0d6f3522631effcbULL,
+ };
+#endif
+
+#if (w==32) /* for variant version */
+/* 30 32-bit words */
+static const md6_word Q[30] =
+ {
+ 0x7311c281UL, 0x2425cfa0UL,
+ 0x64322864UL, 0x34aac8e7UL,
+ 0xb60450e9UL, 0xef68b7c1UL,
+ 0xe8fb2390UL, 0x8d9f06f1UL,
+ 0xdd2e76cbUL, 0xa691e5bfUL,
+ 0x0cd0d63bUL, 0x2c30bc41UL,
+ 0x1f8ccf68UL, 0x23058f8aUL,
+ 0x54e5ed5bUL, 0x88e3775dUL,
+ 0x4ad12aaeUL, 0x0a6d6031UL,
+ 0x3e7f16bbUL, 0x88222e0dUL,
+ 0x8af8671dUL, 0x3fb50c2cUL,
+ 0x995ad117UL, 0x8bd25c31UL,
+ 0xc878c1ddUL, 0x04c4b633UL,
+ 0x3b72066cUL, 0x7a1552acUL,
+ 0x0d6f3522UL, 0x631effcbUL,
+ };
+#endif
+
+ /* MD6 Constant Vector Q (continued).
+*/
+
+#if (w==16) /* for variant version */
+/* 60 16-bit words */
+static const md6_word Q[60] =
+ {
+ 0x7311, 0xc281, 0x2425, 0xcfa0,
+ 0x6432, 0x2864, 0x34aa, 0xc8e7,
+ 0xb604, 0x50e9, 0xef68, 0xb7c1,
+ 0xe8fb, 0x2390, 0x8d9f, 0x06f1,
+ 0xdd2e, 0x76cb, 0xa691, 0xe5bf,
+ 0x0cd0, 0xd63b, 0x2c30, 0xbc41,
+ 0x1f8c, 0xcf68, 0x2305, 0x8f8a,
+ 0x54e5, 0xed5b, 0x88e3, 0x775d,
+ 0x4ad1, 0x2aae, 0x0a6d, 0x6031,
+ 0x3e7f, 0x16bb, 0x8822, 0x2e0d,
+ 0x8af8, 0x671d, 0x3fb5, 0x0c2c,
+ 0x995a, 0xd117, 0x8bd2, 0x5c31,
+ 0xc878, 0xc1dd, 0x04c4, 0xb633,
+ 0x3b72, 0x066c, 0x7a15, 0x52ac,
+ 0x0d6f, 0x3522, 0x631e, 0xffcb,
+ };
+#endif
+
+#if (w==8) /* for variant version */
+/* 120 8-bit words */
+static const md6_word Q[120] =
+ {
+ 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0,
+ 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, 0xc8, 0xe7,
+ 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1,
+ 0xe8, 0xfb, 0x23, 0x90, 0x8d, 0x9f, 0x06, 0xf1,
+ 0xdd, 0x2e, 0x76, 0xcb, 0xa6, 0x91, 0xe5, 0xbf,
+ 0x0c, 0xd0, 0xd6, 0x3b, 0x2c, 0x30, 0xbc, 0x41,
+ 0x1f, 0x8c, 0xcf, 0x68, 0x23, 0x05, 0x8f, 0x8a,
+ 0x54, 0xe5, 0xed, 0x5b, 0x88, 0xe3, 0x77, 0x5d,
+ 0x4a, 0xd1, 0x2a, 0xae, 0x0a, 0x6d, 0x60, 0x31,
+ 0x3e, 0x7f, 0x16, 0xbb, 0x88, 0x22, 0x2e, 0x0d,
+ 0x8a, 0xf8, 0x67, 0x1d, 0x3f, 0xb5, 0x0c, 0x2c,
+ 0x99, 0x5a, 0xd1, 0x17, 0x8b, 0xd2, 0x5c, 0x31,
+ 0xc8, 0x78, 0xc1, 0xdd, 0x04, 0xc4, 0xb6, 0x33,
+ 0x3b, 0x72, 0x06, 0x6c, 0x7a, 0x15, 0x52, 0xac,
+ 0x0d, 0x6f, 0x35, 0x22, 0x63, 0x1e, 0xff, 0xcb,
+ };
+#endif
+
+ /* Endianness.
+*/
+
+/* routines for dealing with byte ordering */
+
+int md6_byte_order = 0;
+/* md6_byte_order describes the endianness of the
+** underlying machine:
+** 0 = unknown
+** 1 = little-endian
+** 2 = big-endian
+*/
+
+/* Macros to detect machine byte order; these
+** presume that md6_byte_order has been setup by
+** md6_detect_byte_order()
+*/
+#define MD6_LITTLE_ENDIAN (md6_byte_order == 1)
+#define MD6_BIG_ENDIAN (md6_byte_order == 2)
+
+void md6_detect_byte_order( void )
+/* determine if underlying machine is little-endian or big-endian
+** set global variable md6_byte_order to reflect result
+** Written to work for any w.
+*/
+{ md6_word x = 1 | (((md6_word)2)<<(w-8));
+ unsigned char *cp = (unsigned char *)&x;
+ if ( *cp == 1 ) md6_byte_order = 1; /* little-endian */
+ else if ( *cp == 2 ) md6_byte_order = 2; /* big-endian */
+ else md6_byte_order = 0; /* unknown */
+}
+
+md6_word md6_byte_reverse( md6_word x )
+/* return byte-reversal of md6_word x.
+** Written to work for any w, w=8,16,32,64.
+*/
+{
+#define mask8 ((md6_word)0x00ff00ff00ff00ffULL)
+#define mask16 ((md6_word)0x0000ffff0000ffffULL)
+#if (w==64)
+ x = (x << 32) | (x >> 32);
+#endif
+#if (w >= 32)
+ x = ((x & mask16) << 16) | ((x & ~mask16) >> 16);
+#endif
+#if (w >= 16)
+ x = ((x & mask8) << 8) | ((x & ~mask8) >> 8);
+#endif
+ return x;
+}
+
+void md6_reverse_little_endian( md6_word *x, int count )
+/* Byte-reverse words x[0...count-1] if machine is little_endian */
+{
+ int i;
+ if (MD6_LITTLE_ENDIAN)
+ for (i=0;i<count;i++)
+ x[i] = md6_byte_reverse(x[i]);
+}
+
+ /* Appending one bit string onto another.
+*/
+
+void append_bits( unsigned char *dest, unsigned int destlen,
+ unsigned char *src, unsigned int srclen )
+/* Append bit string src to the end of bit string dest
+** Input:
+** dest a bit string of destlen bits, starting in dest[0]
+** if destlen is not a multiple of 8, the high-order
+** bits are used first
+** src a bit string of srclen bits, starting in src[0]
+** if srclen is not a multiple of 8, the high-order
+** bits are used first
+** Modifies:
+** dest when append_bits returns, dest will be modified to
+** be a bit-string of length (destlen+srclen).
+** zeros will fill any unused bit positions in the
+** last byte.
+*/
+{ int i, di, accumlen;
+ uint16_t accum;
+ int srcbytes;
+
+ if (srclen == 0) return;
+
+ /* Initialize accum, accumlen, and di */
+ accum = 0; /* accumulates bits waiting to be moved, right-justified */
+ accumlen = 0; /* number of bits in accumulator */
+ if (destlen%8 != 0)
+ { accumlen = destlen%8;
+ accum = dest[destlen/8]; /* grab partial byte from dest */
+ accum = accum >> (8-accumlen); /* right-justify it in accumulator */
+ }
+ di = destlen/8; /* index of where next byte will go within dest */
+
+ /* Now process each byte of src */
+ srcbytes = (srclen+7)/8; /* number of bytes (full or partial) in src */
+ for (i=0;i<srcbytes;i++)
+ { /* shift good bits from src[i] into accum */
+ if (i != srcbytes-1) /* not last byte */
+ { accum = (accum << 8) ^ src[i];
+ accumlen += 8;
+ }
+ else /* last byte */
+ { int newbits = ((srclen%8 == 0) ? 8 : (srclen%8));
+ accum = (accum << newbits) | (src[i] >> (8-newbits));
+ accumlen += newbits;
+ }
+ /* do as many high-order bits of accum as you can (or need to) */
+ while ( ( (i != srcbytes-1) & (accumlen >= 8) ) ||
+ ( (i == srcbytes-1) & (accumlen > 0) ) )
+ { int numbits = min(8,accumlen);
+ unsigned char bits;
+ bits = accum >> (accumlen - numbits); /* right justified */
+ bits = bits << (8-numbits); /* left justified */
+ bits &= (0xff00 >> numbits); /* mask */
+ dest[di++] = bits; /* save */
+ accumlen -= numbits;
+ }
+ }
+}
+
+ /* State initialization. (md6_full_init, with all parameters specified)
+**
+*/
+
+int md6_full_init( md6_state *st, /* uninitialized state to use */
+ int d, /* hash bit length */
+ unsigned char *key, /* key; OK to give NULL */
+ int keylen, /* keylength (bytes); OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r /* number of rounds */
+ )
+/* Initialize md6_state
+** Input:
+** st md6_state to be initialized
+** d desired hash bit length 1 <= d <= w*(c/2) (<=512 bits)
+** key key (aka salt) for this hash computation (byte array)
+** defaults to all-zero key if key==NULL or keylen==0
+** keylen length of key in bytes; 0 <= keylen <= (k*8) (<=64 bytes)
+** L md6 mode parameter; 0 <= L <= 255
+** md6.h defines md6_default_L for when you want default
+** r number of rounds; 0 <= r <= 255
+** Output:
+** updates components of state
+** returns one of the following:
+** MD6_SUCCESS
+** MD6_NULLSTATE
+** MD6_BADKEYLEN
+** MD6_BADHASHLEN
+*/
+{ /* check that md6_full_init input parameters make some sense */
+ if (st == NULL) return MD6_NULLSTATE;
+ if ( (key != NULL) && ((keylen < 0) || (keylen > k*(w/8))) )
+ return MD6_BADKEYLEN;
+ if ( d < 1 || d > 512 || d > w*c/2 ) return MD6_BADHASHLEN;
+
+ md6_detect_byte_order();
+ memset(st,0,sizeof(md6_state)); /* clear state to zero */
+ st->d = d; /* save hashbitlen */
+ if (key != NULL && keylen > 0) /* if no key given, use memset zeros*/
+ { memcpy(st->K,key,keylen); /* else save key (with zeros added) */
+ st->keylen = keylen;
+ /* handle endian-ness */ /* first byte went into high end */
+ md6_reverse_little_endian(st->K,k);
+ }
+ else
+ st->keylen = 0;
+ if ( (L<0) | (L>255) ) return MD6_BAD_L;
+ st->L = L;
+ if ( (r<0) | (r>255) ) return MD6_BAD_r;
+ st->r = r;
+ st->initialized = 1;
+ st->top = 1;
+ /* if SEQ mode for level 1; use IV=0 */
+ /* zero bits already there by memset; */
+ /* we just need to set st->bits[1] */
+ if (L==0) st->bits[1] = c*w;
+ compression_hook = NULL; /* just to be sure default is "not set" */
+ return MD6_SUCCESS;
+}
+
+ /* State initialization. (md6_init, which defaults most parameters.)
+**
+*/
+
+int md6_init( md6_state *st,
+ int d
+ )
+/* Same as md6_full_init, but with default key, L, and r */
+{ return md6_full_init(st,
+ d,
+ NULL,
+ 0,
+ md6_default_L,
+ md6_default_r(d,0)
+ );
+}
+
+ /* Data structure notes.
+*/
+
+/*
+Here are some notes on the data structures used (inside state).
+
+* The variable B[] is a stack of length-b (b-64) word records,
+ each corresponding to a node in the tree. B[ell] corresponds
+ to a node at level ell. Specifically, it represents the record which,
+ when compressed, will yield the value at that level. (It only
+ contains the data payload, not the auxiliary information.)
+ Note that B[i] is used to store the *inputs* to the computation at
+ level i, not the output for the node at that level.
+ Thus, for example, the message input is stored in B[1], not B[0].
+
+* Level 0 is not used. The message bytes are placed into B[1].
+
+* top is the largest ell for which B[ell] has received data,
+ or is equal to 1 in case no data has been received yet at all.
+
+* top is never greater than L+1. If B[L+1] is
+ compressed, the result is put back into B[L+1] (this is SEQ).
+
+* bits[ell] says how many bits have been placed into
+ B[ell]. An invariant maintained is that of the bits in B[ell],
+ only the first bits[ell] may be nonzero; the following bits must be zero.
+
+* The B nodes may have somewhat different formats, depending on the level:
+ -- Level 1 node contains a variable-length bit-string, and so
+ 0 <= bits[1] <= b*w is all we can say.
+ -- Levels 2...top always receive data in c-word chunks (from
+ children), so for them bits[ell] is between 0 and b*w,
+ inclusive, but is also a multiple of cw. We can think of these
+ nodes as have (b/c) (i.e. 4) "slots" for chunks.
+ -- Level L+1 is special, in that the first c words of B are dedicated
+ to the "chaining variable" (or IV, for the first node on the level).
+
+* When the hashing is over, B[top] will contain the
+ final hash value, in the first or second (if top = L+1) slot.
+
+*/
+ /* Compress one block -- compress data at a node (md6_compress_block).
+*/
+
+int md6_compress_block( md6_word *C,
+ md6_state *st,
+ int ell,
+ int z
+ )
+/* compress block at level ell, and put c-word result into C.
+** Input:
+** st current md6 computation state
+** ell 0 <= ell < max_stack_height-1
+** z z = 1 if this is very last compression; else 0
+** Output:
+** C c-word array to put result in
+** Modifies:
+** st->bits[ell] (zeroed)
+** st->i_for_level[ell] (incremented)
+** st->B[ell] (zeroed)
+** st->compression_calls (incremented)
+** Returns one of the following:
+** MD6_SUCCESS
+** MD6_NULLSTATE
+** MD6_STATENOTINIT
+** MD6_STACKUNDERFLOW
+** MD6_STACKOVERFLOW
+*/
+{ int p, err;
+
+ /* check that input values are sensible */
+ if ( st == NULL) return MD6_NULLSTATE;
+ if ( st->initialized == 0 ) return MD6_STATENOTINIT;
+ if ( ell < 0 ) return MD6_STACKUNDERFLOW;
+ if ( ell >= md6_max_stack_height-1 ) return MD6_STACKOVERFLOW;
+
+ st->compression_calls++;
+
+ if (ell==1) /* leaf; hashing data; reverse bytes if nec. */
+ { if (ell<(st->L + 1)) /* PAR (tree) node */
+ md6_reverse_little_endian(&(st->B[ell][0]),b);
+ else /* SEQ (sequential) node; don't reverse chaining vars */
+ md6_reverse_little_endian(&(st->B[ell][c]),b-c);
+ }
+
+ p = b*w - st->bits[ell]; /* number of pad bits */
+
+ err =
+ md6_standard_compress(
+ C, /* C */
+ Q, /* Q */
+ st->K, /* K */
+ ell, st->i_for_level[ell], /* -> U */
+ st->r, st->L, z, p, st->keylen, st->d, /* -> V */
+ st->B[ell] /* B */
+ );
+ if (err) return err;
+
+ st->bits[ell] = 0; /* clear bits used count this level */
+ st->i_for_level[ell]++;
+
+ memset(&(st->B[ell][0]),0,b*sizeof(md6_word)); /* clear B[ell] */
+ return MD6_SUCCESS;
+}
+
+ /* Process (compress) a node and its compressible ancestors.
+*/
+
+int md6_process( md6_state *st,
+ int ell,
+ int final )
+/*
+** Do processing of level ell (and higher, if necessary) blocks.
+**
+** Input:
+** st md6 state that has been accumulating message bits
+** and/or intermediate results
+** ell level number of block to process
+** final true if this routine called from md6_final
+** (no more input will come)
+** false if more input will be coming
+** (This is not same notion as "final bit" (i.e. z)
+** indicating the last compression operation.)
+** Output (by side effect on state):
+** Sets st->hashval to final chaining value on final compression.
+** Returns one of the following:
+** MD6_SUCCESS
+** MD6_NULLSTATE
+** MD6_STATENOTINIT
+*/
+{ int err, z, next_level;
+ md6_word C[c];
+
+ /* check that input values are sensible */
+ if ( st == NULL) return MD6_NULLSTATE;
+ if ( st->initialized == 0 ) return MD6_STATENOTINIT;
+
+ if (!final) /* not final -- more input will be coming */
+ { /* if not final and block on this level not full, nothing to do */
+ if ( st->bits[ell] < b*w )
+ return MD6_SUCCESS;
+ /* else fall through to compress this full block,
+ ** since more input will be coming
+ */
+ }
+ else /* final -- no more input will be coming */
+ { if ( ell == st->top )
+ { if (ell == (st->L + 1)) /* SEQ node */
+ { if ( st->bits[ell]==c*w && st->i_for_level[ell]>0 )
+ return MD6_SUCCESS;
+ /* else (bits>cw or i==0, so fall thru to compress */
+ }
+ else /* st->top == ell <= st->L so we are at top tree node */
+ { if ( ell>1 && st->bits[ell]==c*w)
+ return MD6_SUCCESS;
+ /* else (ell==1 or bits>cw, so fall thru to compress */
+ }
+ }
+ /* else (here ell < st->top so fall through to compress */
+ }
+
+ /* compress block at this level; result goes into C */
+ /* first set z to 1 iff this is the very last compression */
+ z = 0; if (final && (ell == st->top)) z = 1;
+ if ((err = md6_compress_block(C,st,ell,z)))
+ return err;
+ if (z==1) /* save final chaining value in st->hashval */
+ { memcpy( st->hashval, C, md6_c*(w/8) );
+ return MD6_SUCCESS;
+ }
+
+ /* where should result go? To "next level" */
+ next_level = min(ell+1,st->L+1);
+ /* Start sequential mode with IV=0 at that level if necessary
+ ** (All that is needed is to set bits[next_level] to c*w,
+ ** since the bits themselves are already zeroed, either
+ ** initially, or at the end of md6_compress_block.)
+ */
+ if (next_level == st->L + 1
+ && st->i_for_level[next_level]==0
+ && st->bits[next_level]==0 )
+ st->bits[next_level] = c*w;
+ /* now copy C onto next level */
+ memcpy((char *)st->B[next_level] + st->bits[next_level]/8,
+ C,
+ c*(w/8));
+ st->bits[next_level] += c*w;
+ if (next_level > st->top) st->top = next_level;
+
+ return md6_process(st,next_level,final);
+}
+ /* Update -- incorporate data string into hash computation.
+*/
+
+int md6_update( md6_state *st,
+ unsigned char *data,
+ uint64_t databitlen )
+/* Process input byte string data, updating state to reflect result
+** Input:
+** st already initialized state to be updated
+** data byte string of length databitlen bits
+** to be processed (aka "M")
+** databitlen number of bits in string data (aka "m")
+** Modifies:
+** st updated to reflect input of data
+*/
+{ unsigned int j, portion_size;
+ int err;
+
+ /* check that input values are sensible */
+ if ( st == NULL ) return MD6_NULLSTATE;
+ if ( st->initialized == 0 ) return MD6_STATENOTINIT;
+ if ( data == NULL ) return MD6_NULLDATA;
+
+ j = 0; /* j = number of bits processed so far with this update */
+ while (j<databitlen)
+ { /* handle input string in portions (portion_size in bits)
+ ** portion_size may be zero (level 1 data block might be full,
+ ** having size b*w bits) */
+ portion_size = min(databitlen-j,
+ (unsigned int)(b*w-(st->bits[1])));
+
+ if ((portion_size % 8 == 0) &&
+ (st->bits[1] % 8 == 0) &&
+ (j % 8 == 0))
+ { /* use mempy to handle easy, but most common, case */
+ memcpy((char *)st->B[1] + st->bits[1]/8,
+ &(data[j/8]),
+ portion_size/8);
+ }
+ else /* handle messy case where shifting is needed */
+ { append_bits((unsigned char *)st->B[1], /* dest */
+ st->bits[1], /* dest current bit size */
+ &(data[j/8]), /* src */
+ portion_size); /* src size in bits */
+ }
+ j += portion_size;
+ st->bits[1] += portion_size;
+ st->bits_processed += portion_size;
+
+ /* compress level-1 block if it is now full
+ but we're not done yet */
+ if (st->bits[1] == b*w && j<databitlen)
+ { if ((err=md6_process(st,
+ 1, /* ell */
+ 0 /* final */
+ )))
+ return err;
+ }
+ } /* end of loop body handling input portion */
+ return MD6_SUCCESS;
+}
+
+ /* Convert hash value to hexadecimal, and store it in state.
+*/
+
+int md6_compute_hex_hashval( md6_state *st )
+/*
+** Convert hashval in st->hashval into hexadecimal, and
+** save result in st->hexhashval
+** This will be a zero-terminated string of length ceil(d/4).
+** Assumes that hashval has already been "trimmed" to correct
+** length.
+**
+** Returns one of the following:
+** MD6_SUCCESS
+** MD6_NULLSTATE (if input state pointer was NULL)
+*/
+{ int i;
+ static unsigned char hex_digits[] = "0123456789abcdef";
+
+ /* check that input is sensible */
+ if ( st == NULL ) return MD6_NULLSTATE;
+
+ for (i=0;i<((st->d+7)/8);i++)
+ { st->hexhashval[2*i]
+ = hex_digits[ ((st->hashval[i])>>4) & 0xf ];
+ st->hexhashval[2*i+1]
+ = hex_digits[ (st->hashval[i]) & 0xf ];
+ }
+
+ /* insert zero string termination byte at position ceil(d/4) */
+ st->hexhashval[(st->d+3)/4] = 0;
+ return MD6_SUCCESS;
+}
+
+ /* Extract last d bits of chaining variable as hash value.
+*/
+
+void trim_hashval(md6_state *st)
+{ /* trim hashval to desired length d bits by taking only last d bits */
+ /* note that high-order bit of a byte is considered its *first* bit */
+ int full_or_partial_bytes = (st->d+7)/8;
+ int bits = st->d % 8; /* bits in partial byte */
+ int i;
+
+ /* move relevant bytes to the front */
+ for ( i=0; i<full_or_partial_bytes; i++ )
+ st->hashval[i] = st->hashval[c*(w/8)-full_or_partial_bytes+i];
+
+ /* zero out following bytes */
+ for ( i=full_or_partial_bytes; i<c*(w/8); i++ )
+ st->hashval[i] = 0;
+
+ /* shift result left by (8-bits) bit positions, per byte, if needed */
+ if (bits>0)
+ { for ( i=0; i<full_or_partial_bytes; i++ )
+ { st->hashval[i] = (st->hashval[i] << (8-bits));
+ if ( (i+1) < c*(w/8) )
+ st->hashval[i] |= (st->hashval[i+1] >> bits);
+ }
+ }
+}
+
+ /* Final -- no more data; finish up and produce hash value.
+*/
+
+int md6_final( md6_state *st , unsigned char *hashval)
+/* Do final processing to produce md6 hash value
+** Input:
+** st md6 state that has been accumulating message bits
+** and/or intermediate results
+** Output (by side effect on state):
+** hashval If this is non-NULL, final hash value copied here.
+** (NULL means don't copy.) In any case, the hash
+** value remains in st->hashval.
+** st->hashval this is a 64-byte array; the first st->d
+** bits of which will be the desired hash value
+** (with high-order bits of a byte used first), and
+** remaining bits set to zero (same as hashval)
+** st->hexhashval this is a 129-byte array which contains the
+** zero-terminated hexadecimal version of the hash
+** Returns one of the following:
+** MD6_SUCCESS
+** MD6_NULLSTATE
+** MD6_STATENOTINIT
+*/
+{ int ell, err;
+
+ /* check that input values are sensible */
+ if ( st == NULL) return MD6_NULLSTATE;
+ if ( st->initialized == 0 ) return MD6_STATENOTINIT;
+
+ /* md6_final was previously called */
+ if ( st->finalized == 1 ) return MD6_SUCCESS;
+
+ /* force any processing that needs doing */
+ if (st->top == 1) ell = 1;
+ else for (ell=1; ell<=st->top; ell++)
+ if (st->bits[ell]>0) break;
+ /* process starting at level ell, up to root */
+ err = md6_process(st,ell,1);
+ if (err) return err;
+
+ /* md6_process has saved final chaining value in st->hashval */
+
+ md6_reverse_little_endian( (md6_word*)st->hashval, c );
+
+ /* 4/15/09: Following two lines were previously out of order, which
+ ** caused errors depending on whether caller took hash output
+ ** from st->hashval (which was correct) or from
+ ** hashval parameter (which was incorrect, since it
+ ** missed getting "trimmed".)
+ */
+ trim_hashval( st );
+ if (hashval != NULL) memcpy( hashval, st->hashval, (st->d+7)/8 );
+
+ md6_compute_hex_hashval( st );
+
+ st->finalized = 1;
+ return MD6_SUCCESS;
+}
+
+ /* Routines for hashing message given "all at once".
+*/
+
+int md6_full_hash( int d, /* hash bit length */
+ unsigned char *data,/* complete data to hash */
+ uint64_t databitlen, /* its length in bits */
+ unsigned char *key, /* OK to give NULL */
+ int keylen, /* (in bytes) OK to give 0 */
+ int L, /* mode; OK to give md6_default_L */
+ int r, /* number of rounds */
+ unsigned char *hashval /* output */
+ )
+{ md6_state st;
+ int err;
+
+ err = md6_full_init(&st,d,key,keylen,L,r);
+ if (err) return err;
+ err = md6_update(&st,data,databitlen);
+ if (err) return err;
+ md6_final(&st,hashval);
+ if (err) return err;
+ return MD6_SUCCESS;
+}
+
+int md6_hash( int d, /* hash bit length */
+ unsigned char *data, /* complete data to hash */
+ uint64_t databitlen, /* its length in bits */
+ unsigned char *hashval /* output */
+ )
+{ int err;
+
+ err = md6_full_hash(d,data,databitlen,
+ NULL,0,md6_default_L,md6_default_r(d,0),hashval);
+ if (err) return err;
+ return MD6_SUCCESS;
+}
+
+
+/*
+** end of md6_mode.c
+*/
+
+
View
96 lib/md6/md6_nist.c
@@ -0,0 +1,96 @@
+/* File: md6_nist.c
+** Author: Ronald L. Rivest
+** Address: Room 32G-692 Stata Center
+** 32 Vassar Street