canlock2b/0040755000175000017500000000000007737752642012651 5ustar laurentlaurentcanlock2b/.DS_Store0100755000175000017500000001400407726521325014321 0ustar laurentlaurentBud1  GESIlocbl CHANGESIlocblobdocIlocblobdocdsclboolincludeIlocblobtincludedsclboolMakefileIlocblobPREADMEIlocblobsrcIlocblobPsrcdsclbooltIlocblobtdsclbool  @ @ @ @ E DSDB ` @ @ @canlock2b/Build0100700000175000017500000000003207737747054013615 0ustar laurentlaurent#!/bin/sh make make clean canlock2b/CHANGES0100644000175000017500000000361107717614246013635 0ustar laurentlaurentVERSION 2a: 11 Aug 2003 - Only very minor changes. The makefile was tweaked slightly for increased portability, and a typo in lock_strip was fixed. VERSION 2: 10 Aug 2003 - Replaced the SHA-1 library with the source code from RFC 1374. The old code had problems on PowerPC that I was too lazy to hunt down and fix. - Replaced the ISC version of Base64 with an implementation produced by Sweden's Royal Institute of Technology (KTH). The old functions carried a weird patent disclaimer from IBM, while the new ones use a nice simple non-scary BSD license. - The md5_key(), md5_lock() and md5_verify() functions have been removed. As far as I can tell they weren't being used. - Added a Makefile instead of the Build thingy. - Did a bunch of cleanup to get rid of various warnings. VERSION 1: 24 Sep 1998 - Now trying to be compatible with an updated cancel lock draft. - We now generate the lock by hashing the Base64 encoding of the cancel key, instead of the underlying binary digest. - the xxx_key() and xxx_lock() functions now add the md5: or sha1: tag to the lock. - lock_strip_alpha() now discards pesky clue strings and normalizes the case of type codes. - the old lock_strip() that returned numeric codes will be going away. VERSION 0: 21 Sep 1998 - Endianness is now automatically figured out by build. 19 Sep 1998 - Added MD5 hashes. - We now accommodate the possibility that strings will be identified by name instead of number, those darned drafts will get you every time. - Make changes to the hmac stuff to account for GCC weirdness; some check values were not coming out correctly, but they are now. 15 Sep 1998 - Initial, just SHA-1. canlock2b/doc/0040755000175000017500000000000010011460406013363 5ustar laurentlaurentcanlock2b/doc/.DS_Store0100755000175000017500000001400407726642064015072 0ustar laurentlaurentBud1%  @ @ @ @ E%DSDB` @ @ @canlock2b/doc/HOWTO0100644000175000017500000000464007717613257014236 0ustar laurentlaurentHere are some sort-of plain language descriptions of how to use the library. First, your news posting program needs to generate its own Message-ID headers, or some other unique per-article header if IDs aren't allowed by your server. If this isn't already the case, fix that first. You will also need to add a facility for storing a user password; see the included RFCs about recommended lengths. This can be user-generated or built automatically from random cruft, but however you generate the password you do have to save it. This password is the only thing that will allow you to cancel articles later. An alternative approach is to generate a unique password for each article, but then you would need to build a whole little database monster. POSTING: Generate a Message-ID. Now, pass the pointers and lengths of the password and message id to sha_lock(). It will return a pointer to your cancel lock. For example: fprintf(art, "Message-ID: %s\n", msgid); fprintf(art, "Cancel-Lock: sha1:%s\n", sha_lock(password, strlen(password), msgid, strlen(msgid)); CANCELING: This time, you use the Message-ID of the article to be canceled. We use sha_key this time to complete the cycle. fprintf(art, "Control: cancel %s\n", msg_can); fprintf(art, "Cancel-Key: sha1:%s\n", sha_key(password, strlen(password), msgid, strlen(msgid)); VERIFYING: This is purely optional at the newsreader level; only servers should really need to bother. Extract the Cancel-Key: header from the cancel message. Fetch the original article from the server and extract its Cancel-Lock: header. Chop off the keywords; we are only interested in the Base64 thingies. - If the original article has no lock (or is missing), you can ignore the cancel key and use traditional verification, or abort the cancel operation if you don't want to trust unauthenticated cancels. - If the original article has a lock and the cancel has no key, abort the cancel operation. - If both a key and lock are present, strip off the type numbers and make sure they're both type sha1 (the only kind this library handles). You can use the lock_strip() function to make this a bit easier. - Finally, you can send pointers to each stripped lock on to sha_verify(). If it returns zero, your may delete the article. Remember that there may be more than one lock in the header. Be sure to check all locks against the key before giving up. canlock2b/include/0040755000175000017500000000000010011460433014241 5ustar laurentlaurentcanlock2b/include/base64.h0100644000175000017500000000352107715522265015517 0ustar laurentlaurent/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * 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. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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. */ /* $Id: base64.h,v 1.2 1999/12/02 16:58:45 joda Exp $ */ #ifndef _BASE64_H_ #define _BASE64_H_ size_t base64_encode(const void *data, int size, char **str); size_t base64_decode(const char *str, void *data); #endif canlock2b/include/canlock.h0100644000175000017500000000060607737746571016062 0ustar laurentlaurentchar *sha_key(const unsigned char *secret, size_t seclen, const unsigned char *message, size_t msglen); char *sha_lock(const unsigned char *secret, size_t seclen, const unsigned char *message, size_t msglen); int sha_verify(const char *key, const char *lock); char *lock_strip_alpha(const char *key, char *type); char *lock_strip(const char *key, char *type); canlock2b/include/hmac_sha1.h0100644000175000017500000000016707737744500016264 0ustar laurentlaurentunsigned char *hmac_sha1(const unsigned char *K, int Klen, const unsigned char *T, int Tlen); canlock2b/Makefile0100755000175000017500000000347007737747724014322 0ustar laurentlaurentANALFLAGS= -pg -W -Wall -pedantic -Wcast-align \ -Wcast-qual -Wchar-subscripts -Winline \ -Wmissing-prototypes -Wpointer-arith \ -Wredundant-decls -Wshadow -Wstrict-prototypes -Wwrite-strings CFLAGS = -O -Iinclude LDFLAGS = -L. -lcanlock LIBOBJS = src/sha1.o src/hmac_sha1.o src/base64.o src/canlock.o LOCKLIB = libcanlock.a .c.o: $(CC) $(CFLAGS) -c $< -o $@ all: sha1test hmactest canlocktest anal: $(MAKE) CFLAGS="$(CFLAGS) $(ANALFLAGS)" sha1test: t/sha1test.c $(LOCKLIB) $(CC) $(CFLAGS) t/$@.c -o $@ $(LDFLAGS) hmactest: t/hmactest.c $(LOCKLIB) $(CC) $(CFLAGS) t/$@.c -o $@ $(LDFLAGS) canlocktest: t/canlocktest.c $(LOCKLIB) $(CC) $(CFLAGS) t/$@.c -o $@ $(LDFLAGS) src/base64.o: src/base64.c include/base64.h src/canlock.o: src/canlock.c include/canlock.h src/hmac_sha1.o: src/hmac_sha1.c include/hmac_sha1.h src/sha1.o: src/sha1.c include/sha1.h libs: $(LOCKLIB) $(LOCKLIB): $(LIBOBJS) @echo "Arr, ye be makin' the library matey!" ar r $@ $(LIBOBJS) ranlib $@ ln -s include/canlock.h . clean: rm -f src/*.o t/*.o t/*.out *.gmon gmon.* nuke: clean rm -f *.a canlocktest hmactest sha1test *.exe *.h test: all @echo "sha1test: " @./sha1test > t/sha1test.out @diff t/sha1test.shouldbe t/sha1test.out && echo " Pass." || echo " **FAIL**" @echo "=-=-=-=" @echo "hmactest: " @./hmactest > t/hmactest.out || echo hmm @diff t/hmactest.shouldbe t/hmactest.out && echo " Pass." || echo " **FAIL**" @echo "=-=-=-=" @echo "canlocktest: " @./canlocktest > t/canlocktest.out @diff t/canlocktest.shouldbe t/canlocktest.out && echo " Pass." || echo " **FAIL**" @echo "=-=-=-=" help: @echo make options: @echo ' anal compile with lots of warnings enabled.' @echo ' libs build only the library.' @echo ' clean delete stray object files.' @echo ' nuke clean up everything.' canlock2b/README0100644000175000017500000000235307717613675013531 0ustar laurentlaurentlibcanlock - a library for creating and verifying cancel locks. Copyright stuff: sha1.c is basically the sample code from RFC 3174 from Donald Eastlake and Paul Jones, and carries a BSD-ish license from the Internet Society. base64.c carries a BSD license from KTH. hmac_sha1.c, canlock.c, hmactest.c and canlocktest.c were written by Greg Andruk, and carry an MIT style license. How to compile it: If you are lucky, it will be enough to unpack the archive, change to it top directory and run make. You can also: make test to insure the library works as Fluffy intended make clean to get rid of stray build gunk make nuke to return the directory to its lovely pristine condition The libcanlock.a that will be produced is what you want to link into your newsreader or whatever. Random blabbage: This version compiled and ran correctly on x86, PowerPC, Itanium, PA-RISC and Alpha, so hopefully it's now reasonably portable. The canlocktest source code should give you a pretty good idea of how the functions work. See the doc directory for relevant RFCs and stuff. Meow. canlock2b/src/0040755000175000017500000000000010011460524013406 5ustar laurentlaurentcanlock2b/src/base64.c0100644000175000017500000000712607715522336014662 0ustar laurentlaurent/* * Copyright (c) 1995-2001 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * 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. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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. */ #ifdef HAVE_CONFIG_H #include RCSID("$Id: base64.c,v 1.5 2001/05/28 17:33:41 joda Exp $") #endif #include #include #include "base64.h" static char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static int pos(char c) { char *p; for (p = base64_chars; *p; p++) if (*p == c) return p - base64_chars; return -1; } size_t base64_encode(const void *data, int size, char **str) { char *s, *p; int i; int c; const unsigned char *q; p = s = (char *) malloc(size * 4 / 3 + 4); if (p == NULL) return -1; q = (const unsigned char *) data; i = 0; for (i = 0; i < size;) { c = q[i++]; c *= 256; if (i < size) c += q[i]; i++; c *= 256; if (i < size) c += q[i]; i++; p[0] = base64_chars[(c & 0x00fc0000) >> 18]; p[1] = base64_chars[(c & 0x0003f000) >> 12]; p[2] = base64_chars[(c & 0x00000fc0) >> 6]; p[3] = base64_chars[(c & 0x0000003f) >> 0]; if (i > size) p[3] = '='; if (i > size + 1) p[2] = '='; p += 4; } *p = 0; *str = s; return strlen(s); } #define DECODE_ERROR 0xffffffff static unsigned int token_decode(const char *token) { int i; unsigned int val = 0; int marker = 0; if (strlen(token) < 4) return DECODE_ERROR; for (i = 0; i < 4; i++) { val *= 64; if (token[i] == '=') marker++; else if (marker > 0) return DECODE_ERROR; else val += pos(token[i]); } if (marker > 2) return DECODE_ERROR; return (marker << 24) | val; } size_t base64_decode(const char *str, void *data) { const char *p; unsigned char *q; q = data; for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { unsigned int val = token_decode(p); unsigned int marker = (val >> 24) & 0xff; if (val == DECODE_ERROR) return -1; *q++ = (val >> 16) & 0xff; if (marker < 2) *q++ = (val >> 8) & 0xff; if (marker < 1) *q++ = val & 0xff; } return q - (unsigned char *) data; } canlock2b/src/canlock.c0100644000175000017500000001276407737747007015224 0ustar laurentlaurent/* * COPYRIGHT AND PERMISSION NOTICE * * Copyright (c) 2003 G.J. Andruk * * All rights reserved. * * 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, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * 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 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. */ #include #include #include #include #include #include "base64.h" #include "sha1.h" #include "hmac_sha1.h" #include "canlock.h" #define BUFFSIZE 40 /* * Return a stripped cancel lock, that is, with the xx: prefix * removed, else NULL on failure. * type is set to the lock type, else zero on failure. */ char * lock_strip_alpha(const char *key, char *type) { char *c, *typetext, *mykey = (char *)key; size_t ttpos = 0, ttlen = 256; typetext = (char *) malloc(ttlen); if (!typetext) return NULL; *typetext = 0; while (*mykey && *mykey != ':') { if (ttpos >= ttlen) { ttlen += 256; typetext = (char *) realloc( (void *)typetext, ttlen); if (!typetext) return NULL; } typetext[ttpos++] = *mykey++; } if (! *mykey) type = NULL; else { mykey++; for (c = mykey; *c; c++) { if (*c == ':') *c = '\0'; } strcpy(type, typetext); for (c = type; *c; ++c) *c = tolower(*c); } return (mykey); } char * lock_strip(const char *key, char *type) { return lock_strip_alpha(key, type); } /* * Generate an SHA1 cancel key. * Returns a malloc()'d buffer that the caller will need to free(). */ char * sha_key(const unsigned char *secret, size_t seclen, const unsigned char *message, size_t msglen) { char *cankey[1]; unsigned char *hmacbuff; size_t keysize; hmacbuff = hmac_sha1(secret, seclen, message, msglen); if (!hmacbuff) return NULL; keysize = base64_encode(hmacbuff, SHA1HashSize, cankey); free ((void *) hmacbuff); if (!keysize) return NULL; *cankey = (char *) realloc((void *) *cankey, keysize + 6); if (!*cankey) return NULL; memmove((void *) (*cankey + 5), (void *) *cankey, keysize + 1); strncpy(*cankey, "sha1:", 5); return (*cankey); } /* * Generate an SHA1 cancel lock. * Returns a malloc()'d buffer that the caller will need to free(). */ char * sha_lock(const unsigned char *secret, size_t seclen, const unsigned char *message, size_t msglen) { char *canlock[1], junk[SHA1HashSize]; unsigned char *cankey, hmacbuff[SHA1HashSize]; size_t locksize; SHA1Context hash_ctx; cankey = (unsigned char *) lock_strip_alpha( sha_key(secret, seclen, message, msglen), junk); if (!cankey) return NULL; if (SHA1Reset(&hash_ctx)) return NULL; if (SHA1Input(&hash_ctx, cankey, strlen((char *) cankey))) return NULL; if (SHA1Result(&hash_ctx, hmacbuff)) return NULL; locksize = base64_encode(hmacbuff, SHA1HashSize, canlock); if (!locksize) return NULL; *canlock = (char *) realloc((void *) *canlock, locksize + 6); if (!*canlock) return NULL; memmove((void *) (*canlock + 5), (void *) *canlock, locksize + 1); strncpy(*canlock, "sha1:", 5); return (*canlock); } /* * Verify an SHA cancel key against a cancel lock. * Returns 0 on success, nonzero on failure. */ int sha_verify(const char *key, const char *lock) { unsigned char binkey[SHA1HashSize + 4], hmacbuff[SHA1HashSize]; char *templock[1]; size_t keysize, locksize; SHA1Context hash_ctx; /* Convert the key back into binary */ keysize = base64_decode(key, (void *) &binkey); if (!keysize) return -1; if (SHA1Reset(&hash_ctx)) return -1; if (SHA1Input(&hash_ctx, (unsigned char *)key, strlen(key))) return -1; if (SHA1Result(&hash_ctx, hmacbuff)) return -1; locksize = base64_encode(hmacbuff, SHA1HashSize, templock); if (!locksize) return -1; return strcmp(*templock, lock); } canlock2b/src/hmac_sha1.c0100644000175000017500000000704107737744461015427 0ustar laurentlaurent/* * COPYRIGHT AND PERMISSION NOTICE * * Copyright (c) 2003 G.J. Andruk * * All rights reserved. * * 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, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * 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 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. */ #include #include #include #include "sha1.h" #include "hmac_sha1.h" #define ipad 0x36 #define opad 0x5c /* * Encode a string using HMAC - see RFC-2104 for details. * Returns the MAC, or NULL on error. * Caller needs to free() non-NULL return values.. */ unsigned char * hmac_sha1( const unsigned char *K, /* key */ int Klen, /* and it size */ const unsigned char *T, /* text to encode */ int Tlen /* and its size */ ) { SHA1Context hash_ctx; unsigned char keyin[SHA1HashSize], *step2, step4[SHA1HashSize], step5[SHA1Block + SHA1HashSize], *hmac_out, *c; int i, j; if (SHA1Reset(&hash_ctx)) return NULL; /* If the key is bigger than SHA1Block we need to hash it. */ if (Klen > SHA1Block) { if (SHA1Input(&hash_ctx, K, Klen)) return NULL; if (SHA1Result(&hash_ctx, keyin)) return NULL; Klen = SHA1HashSize; } else memcpy(keyin, K, Klen); step2 = (unsigned char *) malloc(Tlen + SHA1Block); c = keyin; for (i = 0; i < Klen; i++) { step2[i] = *c ^ ipad; step5[i] = *c ^ opad; c++; } for (j = i; j < SHA1Block; j++) { step2[j] = 0x36; step5[j] = opad; } memcpy(&step2[SHA1Block], T, Tlen); if (SHA1Reset(&hash_ctx)) return NULL; if (SHA1Input(&hash_ctx, step2, SHA1Block + Tlen)) return NULL; if (SHA1Result(&hash_ctx, step4)) return NULL; memcpy(&step5[SHA1Block], step4, SHA1HashSize); hmac_out = (unsigned char *) malloc(SHA1HashSize); if (!hmac_out) return NULL; if (SHA1Reset(&hash_ctx)) return NULL; if (SHA1Input(&hash_ctx, step5, SHA1Block + SHA1HashSize)) return NULL; if (SHA1Result(&hash_ctx, hmac_out)) return NULL; return hmac_out; } canlock2b/src/sha1.c0100644000175000017500000003015110011460524014403 0ustar laurentlaurent/* sha.c - Implementation of the Secure Hash Algorithm * * Copyright (C) 1995, A.M. Kuchling * * Distribute and use freely; there are no restrictions on further * dissemination and usage except those imposed by the laws of your * country of residence. * * Adapted to pike and some cleanup by Niels Mller. */ /* $Id: sha1.c,v 1.5 2002/05/26 17:46:16 nmav Exp $ */ /* SHA: NIST's Secure Hash Algorithm */ /* Based on SHA code originally posted to sci.crypt by Peter Gutmann in message <30ajo5$oe8@ccu2.auckland.ac.nz>. Modified to test for endianness on creation of SHA objects by AMK. Also, the original specification of SHA was found to have a weakness by NSA/NIST. This code implements the fixed version of SHA. */ /* Here's the first paragraph of Peter Gutmann's posting: The following is my SHA (FIPS 180) code updated to allow use of the "fixed" SHA, thanks to Jim Gillogly and an anonymous contributor for the information on what's changed in the new version. The fix is a simple change which involves adding a single rotate in the initial expansion function. It is unknown whether this is an optimal solution to the problem which was discovered in the SHA or whether it's simply a bandaid which fixes the problem with a minimum of effort (for example the reengineering of a great many Capstone chips). */ #include "libdefs.h" #ifdef ENABLE_SHA1 #include "mhash_sha1.h" void sha_copy(struct sha_ctx *dest, struct sha_ctx *src) { int i; dest->count_l=src->count_l; dest->count_h=src->count_h; for(i=0; idigest[i]=src->digest[i]; for(i=0; i < src->index; i++) dest->block[i] = src->block[i]; dest->index = src->index; } /* The SHA f()-functions. The f1 and f3 functions can be optimized to save one boolean operation each - thanks to Rich Schroeppel, rcs@cs.arizona.edu for discovering this */ /*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ /*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ /* The SHA Mysterious Constants */ #define K1 0x5A827999L /* Rounds 0-19 */ #define K2 0x6ED9EBA1L /* Rounds 20-39 */ #define K3 0x8F1BBCDCL /* Rounds 40-59 */ #define K4 0xCA62C1D6L /* Rounds 60-79 */ /* SHA initial values */ #define h0init 0x67452301L #define h1init 0xEFCDAB89L #define h2init 0x98BADCFEL #define h3init 0x10325476L #define h4init 0xC3D2E1F0L /* 32-bit rotate left - kludged with shifts */ #define ROTL(n,X) ( ( (X) << (n) ) | ( (X) >> ( 32 - (n) ) ) ) /* The initial expanding function. The hash function is defined over an 80-word expanded input array W, where the first 16 are copies of the input data, and the remaining 64 are defined by W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] This implementation generates these values on the fly in a circular buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this optimization. The updated SHA changes the expanding function by adding a rotate of 1 bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor for this information */ #define expand(W,i) ( W[ i & 15 ] = \ ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) /* The prototype SHA sub-round. The fundamental sub-round is: a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; b' = a; c' = ROTL( 30, b ); d' = c; e' = d; but this is implemented by unrolling the loop 5 times and renaming the variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. This code is then replicated 20 times for each of the 4 functions, using the next 20 values from the W[] array each time */ #define subRound(a, b, c, d, e, f, k, data) \ ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) /* Initialize the SHA values */ void sha_init(struct sha_ctx *ctx) { /* Set the h-vars to their initial values */ ctx->digest[ 0 ] = h0init; ctx->digest[ 1 ] = h1init; ctx->digest[ 2 ] = h2init; ctx->digest[ 3 ] = h3init; ctx->digest[ 4 ] = h4init; /* Initialize bit count */ ctx->count_l = ctx->count_h = 0; /* Initialize buffer */ ctx->index = 0; } /* Perform the SHA transformation. Note that this code, like MD5, seems to break some optimizing compilers due to the complexity of the expressions and the size of the basic block. It may be necessary to split it into sections, e.g. based on the four subrounds Note that this function destroys the data area */ static void sha_transform(struct sha_ctx *ctx, word32 *data ) { register word32 A, B, C, D, E; /* Local vars */ /* Set up first buffer and local data buffer */ A = ctx->digest[0]; B = ctx->digest[1]; C = ctx->digest[2]; D = ctx->digest[3]; E = ctx->digest[4]; /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ subRound( A, B, C, D, E, f1, K1, data[ 0] ); subRound( E, A, B, C, D, f1, K1, data[ 1] ); subRound( D, E, A, B, C, f1, K1, data[ 2] ); subRound( C, D, E, A, B, f1, K1, data[ 3] ); subRound( B, C, D, E, A, f1, K1, data[ 4] ); subRound( A, B, C, D, E, f1, K1, data[ 5] ); subRound( E, A, B, C, D, f1, K1, data[ 6] ); subRound( D, E, A, B, C, f1, K1, data[ 7] ); subRound( C, D, E, A, B, f1, K1, data[ 8] ); subRound( B, C, D, E, A, f1, K1, data[ 9] ); subRound( A, B, C, D, E, f1, K1, data[10] ); subRound( E, A, B, C, D, f1, K1, data[11] ); subRound( D, E, A, B, C, f1, K1, data[12] ); subRound( C, D, E, A, B, f1, K1, data[13] ); subRound( B, C, D, E, A, f1, K1, data[14] ); subRound( A, B, C, D, E, f1, K1, data[15] ); subRound( E, A, B, C, D, f1, K1, expand( data, 16 ) ); subRound( D, E, A, B, C, f1, K1, expand( data, 17 ) ); subRound( C, D, E, A, B, f1, K1, expand( data, 18 ) ); subRound( B, C, D, E, A, f1, K1, expand( data, 19 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 20 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 21 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 22 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 23 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 24 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 25 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 26 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 27 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 28 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 29 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 30 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 31 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 32 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 33 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 34 ) ); subRound( A, B, C, D, E, f2, K2, expand( data, 35 ) ); subRound( E, A, B, C, D, f2, K2, expand( data, 36 ) ); subRound( D, E, A, B, C, f2, K2, expand( data, 37 ) ); subRound( C, D, E, A, B, f2, K2, expand( data, 38 ) ); subRound( B, C, D, E, A, f2, K2, expand( data, 39 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 40 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 41 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 42 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 43 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 44 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 45 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 46 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 47 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 48 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 49 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 50 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 51 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 52 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 53 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 54 ) ); subRound( A, B, C, D, E, f3, K3, expand( data, 55 ) ); subRound( E, A, B, C, D, f3, K3, expand( data, 56 ) ); subRound( D, E, A, B, C, f3, K3, expand( data, 57 ) ); subRound( C, D, E, A, B, f3, K3, expand( data, 58 ) ); subRound( B, C, D, E, A, f3, K3, expand( data, 59 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 60 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 61 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 62 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 63 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 64 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 65 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 66 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 67 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 68 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 69 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 70 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 71 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 72 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 73 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 74 ) ); subRound( A, B, C, D, E, f4, K4, expand( data, 75 ) ); subRound( E, A, B, C, D, f4, K4, expand( data, 76 ) ); subRound( D, E, A, B, C, f4, K4, expand( data, 77 ) ); subRound( C, D, E, A, B, f4, K4, expand( data, 78 ) ); subRound( B, C, D, E, A, f4, K4, expand( data, 79 ) ); /* Build message digest */ ctx->digest[0] += A; ctx->digest[1] += B; ctx->digest[2] += C; ctx->digest[3] += D; ctx->digest[4] += E; } static void sha_block(struct sha_ctx *ctx, word8 *block) { word32 data[SHA_DATALEN]; int i; /* Update block count */ if (!++ctx->count_l) ++ctx->count_h; /* Endian independent conversion */ for (i = 0; iindex) { /* Try to fill partial block */ unsigned left = SHA_DATASIZE - ctx->index; if (len < left) { memcpy(ctx->block + ctx->index, buffer, len); ctx->index += len; return; /* Finished */ } else { memcpy(ctx->block + ctx->index, buffer, left); sha_block(ctx, ctx->block); buffer += left; len -= left; } } while (len >= SHA_DATASIZE) { sha_block(ctx, buffer); buffer += SHA_DATASIZE; len -= SHA_DATASIZE; } if ((ctx->index = len)) /* This assignment is intended */ /* Buffer leftovers */ memcpy(ctx->block, buffer, len); } /* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern 1 0* (64-bit count of bits processed, MSB-first) */ void sha_final(struct sha_ctx *ctx) { word32 data[SHA_DATALEN]; int i; int words; i = ctx->index; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ ctx->block[i++] = 0x80; /* Fill rest of word */ for( ; i & 3; i++) ctx->block[i] = 0; /* i is now a multiple of the word size 4 */ words = i >> 2; for (i = 0; i < words; i++) data[i] = STRING2INT(ctx->block + 4*i); if (words > (SHA_DATALEN-2)) { /* No room for length in this block. Process it and * pad with another one */ for (i = words ; i < SHA_DATALEN; i++) data[i] = 0; sha_transform(ctx, data); for (i = 0; i < (SHA_DATALEN-2); i++) data[i] = 0; } else for (i = words ; i < SHA_DATALEN - 2; i++) data[i] = 0; /* Theres 512 = 2^9 bits in one block */ data[SHA_DATALEN-2] = (ctx->count_h << 9) | (ctx->count_l >> 23); data[SHA_DATALEN-1] = (ctx->count_l << 9) | (ctx->index << 3); sha_transform(ctx, data); } void sha_digest(struct sha_ctx *ctx, word8 *s) { int i; if (s!=NULL) for (i = 0; i < SHA_DIGESTLEN; i++) { *s++ = ctx->digest[i] >> 24; *s++ = 0xff & (ctx->digest[i] >> 16); *s++ = 0xff & (ctx->digest[i] >> 8); *s++ = 0xff & ctx->digest[i]; } } #endif /* ENABLE_SHA1 */ canlock2b/t/0040755000175000017500000000000010011460462013063 5ustar laurentlaurentcanlock2b/t/.DS_Store0100755000175000017500000001400407717563100014561 0ustar laurentlaurentBud1%  @ @ @ @ E%DSDB` @ @ @canlock2b/t/canlocktest.c0100644000175000017500000000551107737745345015573 0ustar laurentlaurent/* * canlocktest.c - just checking. * * This program doesn't really do anything but lightly exercise all the * library functions, so you can make sure it all compiled correctly. * Everything's kept simple so that you can also see how they would be * called in a real application. */ #include #include #include #include #include "canlock.h" #define BUFFSIZE 512 void checker(char *key, char *lock); void checker(char *key, char *lock) { char *rawkey, *rawlock; char keytype[BUFFSIZE], locktype[BUFFSIZE]; printf("L %s K %s ", lock, key); rawkey = lock_strip_alpha(key, keytype); rawlock = lock_strip_alpha(lock, locktype); if (!strcmp(keytype, locktype)) { if (!strcmp(keytype, "sha1")) { if (!sha_verify(rawkey, rawlock)) printf("sha1 OK\n"); else printf("sha1 no\n"); } else printf("unknown\n"); } else printf("Mismatch %s %s\n", keytype, locktype); } int main(void) { char cankey[256], canlock[256], *lkey, *llock; unsigned char secret[] = "fluffy", message[] = ""; printf("Secret %s\n", secret); printf("Message %s\n", message); llock = sha_lock(secret, strlen((char *) secret), message, strlen((char *) message)); lkey = sha_key(secret, strlen((char *) secret), message, strlen((char *)message)); printf("%s%s %s\n", "SHA Expect Lock/Key:\n", "L sha1:ScU1gyAi9bd/aFEOyzg4m99lwXs=", "K sha1:C1Me/4n0l/V778Ih3J2UnhAoHrA="); checker(lkey, llock); free((void *) llock); free((void *) lkey); printf("---\n"); /*********/ printf("Testing against usefor cancel lock draft 01 samples...\n"); sprintf(canlock, "%s", "sha1:bNXHc6ohSmeHaRHHW56BIWZJt+4="); sprintf(cankey, "%s", "sha1:aaaBBBcccDDDeeeFFF"); checker(cankey, canlock); printf("---above should have been OK---\n"); /*********/ sprintf(canlock, "%s", "SHA1:H7/zsCUemvbvSDyARDaMs6AQu5s="); sprintf(cankey, "%s", "sha1:chW8hNeDx3iNUsGBU6/ezDk88P4="); checker(cankey, canlock); sprintf(canlock, "%s", "SHA1:H7/zsCUemvbvSDyARDaMs6AQu5s="); sprintf(cankey, "%s", "sha1:4srkWaRIzvK51ArAP:Hc"); checker(cankey, canlock); printf("---above should have been OK, no---\n"); /*********/ sprintf(canlock, "%s", "sha1:JyEBL4w9/abCBuzCxMIE/E73GM4="); sprintf(cankey, "%s", "sha1:K4rkWRjRcXmIzvK51ArAP:Jy"); checker(cankey, canlock); sprintf(canlock, "%s", "sha1:2Bmg+zWaY1noRiCdy8k3IapwSDU="); sprintf(cankey, "%s", "sha1:K4rkWRjRcXmIzvK51ArAP:Jy"); checker(cankey, canlock); printf("---above should have been OK, no---\n"); return 0; } canlock2b/t/canlocktest.shouldbe0100444000175000017500000000137607715526301017142 0ustar laurentlaurentSecret fluffy Message SHA Expect Lock/Key: L sha1:ScU1gyAi9bd/aFEOyzg4m99lwXs= K sha1:C1Me/4n0l/V778Ih3J2UnhAoHrA= L sha1:ScU1gyAi9bd/aFEOyzg4m99lwXs= K sha1:C1Me/4n0l/V778Ih3J2UnhAoHrA= sha1 OK --- Testing against usefor cancel lock draft 01 samples... L sha1:bNXHc6ohSmeHaRHHW56BIWZJt+4= K sha1:aaaBBBcccDDDeeeFFF sha1 OK ---above should have been OK--- L SHA1:H7/zsCUemvbvSDyARDaMs6AQu5s= K sha1:chW8hNeDx3iNUsGBU6/ezDk88P4= sha1 OK L SHA1:H7/zsCUemvbvSDyARDaMs6AQu5s= K sha1:4srkWaRIzvK51ArAP:Hc sha1 no ---above should have been OK, no--- L sha1:JyEBL4w9/abCBuzCxMIE/E73GM4= K sha1:K4rkWRjRcXmIzvK51ArAP:Jy sha1 OK L sha1:2Bmg+zWaY1noRiCdy8k3IapwSDU= K sha1:K4rkWRjRcXmIzvK51ArAP:Jy sha1 no ---above should have been OK, no--- canlock2b/t/hmactest.c0100644000175000017500000000606507737744313015070 0ustar laurentlaurent/* * hmac test program */ #include #include #include "sha1.h" #include "hmac_sha1.h" int main(void) { unsigned char *hmachash, key1[] = "Jefe", message1[] = "what do ya want for nothing?", key2[20], message2[] = "Hi There", key3[80], message3[] = "Test Using Larger Than Block-Size Key - Hash Key First", key4[80], message4[] = "Test Using Larger Than Block-Size Key and Larger " "Than One Block-Size Data", key5[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00 }, message5[50]; int i; for (i = 0; i < 20; i++) key2[i] = 0x0b; for (i = 0; i < 80; i++) key3[i] = 0xaa; for (i = 0; i < 80; i++) key4[i] = 0xaa; for (i = 0; i < 50; i++) message5[i] = 0xcd; printf("Key: %s\n", key1); printf("Msg: %s\n", message1); hmachash = hmac_sha1(key1, strlen((char *) key1), message1, strlen((char *)message1)); printf("Expected SHA Digest: %s\n", "0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); printf(" Actual SHA Digest: 0x"); for (i = 0; i < SHA1HashSize; i++) printf("%02x", hmachash[i]); putchar('\n'); /********/ printf("\nKey: 0x0b, len 20 for SHA, 16 for MD5\n"); printf("Msg: %s\n", message2); hmachash = hmac_sha1(key2, 20, message2, strlen((char *) message2)); printf("Expected SHA Digest: %s\n", "0xb617318655057264e28bc0b6fb378c8ef146be00"); printf(" Actual SHA Digest: 0x"); for (i = 0; i < SHA1HashSize; i++) printf("%02x", hmachash[i]); putchar('\n'); /********/ printf("\nKey: 0xaa repeated 80 times\n"); printf("Msg: %s\n", message3); hmachash = hmac_sha1(key3, 80, message3, strlen((char *) message3)); printf("Expected SHA Digest: %s\n", "0xaa4ae5e15272d00e95705637ce8a3b55ed402112"); printf(" Actual SHA Digest: 0x"); for (i = 0; i < SHA1HashSize; i++) printf("%02x", hmachash[i]); putchar('\n'); /********/ printf("\nKey: 0xaa repeated 80 times\n"); printf("Msg: %s\n", message4); hmachash = hmac_sha1(key4, 80, message4, strlen((char *) message4)); printf("Expected SHA Digest: %s\n", "0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91"); printf(" Actual SHA Digest: 0x"); for (i = 0; i < SHA1HashSize; i++) printf("%02x", hmachash[i]); putchar('\n'); /********/ printf("\nKey: 0x"); for (i = 0; i < 25; i++) printf("%02x", key5[i]); printf("\nMsg: 0xcd repeated 50 times\n"); hmachash = hmac_sha1(key5, 25, message5, 50); printf("Expected SHA Digest: %s\n", "0x4c9007f4026250c6bc8414f9bf50c86c2d7235da"); printf(" Actual SHA Digest: 0x"); for (i = 0; i < SHA1HashSize; i++) printf("%02x", hmachash[i]); putchar('\n'); return 0; } canlock2b/t/hmactest.shouldbe0100444000175000017500000000177507715531065016446 0ustar laurentlaurentKey: Jefe Msg: what do ya want for nothing? Expected SHA Digest: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 Actual SHA Digest: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 Key: 0x0b, len 20 for SHA, 16 for MD5 Msg: Hi There Expected SHA Digest: 0xb617318655057264e28bc0b6fb378c8ef146be00 Actual SHA Digest: 0xb617318655057264e28bc0b6fb378c8ef146be00 Key: 0xaa repeated 80 times Msg: Test Using Larger Than Block-Size Key - Hash Key First Expected SHA Digest: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 Actual SHA Digest: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 Key: 0xaa repeated 80 times Msg: Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Expected SHA Digest: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 Actual SHA Digest: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 Msg: 0xcd repeated 50 times Expected SHA Digest: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da Actual SHA Digest: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da