Added SHA1 implementation.

master
Hannes Matuschek 11 years ago
parent 23d2e122bd
commit 5ded7135d0

@ -1,13 +1,13 @@
# Sources of libsdr # Sources of libsdr
set(LIBSDR_SOURCES set(LIBSDR_SOURCES
buffer.cc node.cc queue.cc traits.cc portaudio.cc utils.cc wavfile.cc exception.cc logger.cc buffer.cc node.cc queue.cc traits.cc portaudio.cc utils.cc wavfile.cc exception.cc logger.cc
psk31.cc options.cc fsk.cc ax25.cc aprs.cc baudot.cc pocsag.cc bch31_21.cc http.cc) psk31.cc options.cc fsk.cc ax25.cc aprs.cc baudot.cc pocsag.cc bch31_21.cc http.cc sha1.cc)
set(LIBSDR_HEADERS sdr.hh math.hh set(LIBSDR_HEADERS sdr.hh math.hh
buffer.hh node.hh queue.hh buffernode.hh filternode.hh traits.hh autocast.hh buffer.hh node.hh queue.hh buffernode.hh filternode.hh traits.hh autocast.hh
siggen.hh portaudio.hh utils.hh wavfile.hh demod.hh firfilter.hh siggen.hh portaudio.hh utils.hh wavfile.hh demod.hh firfilter.hh
fftplan.hh fftplan_native.hh exception.hh baseband.hh freqshift.hh subsample.hh fftplan.hh fftplan_native.hh exception.hh baseband.hh freqshift.hh subsample.hh
combine.hh logger.hh psk31.hh interpolate.hh operators.hh options.hh fsk.hh ax25.hh combine.hh logger.hh psk31.hh interpolate.hh operators.hh options.hh fsk.hh ax25.hh
aprs.hh baudot.hh pocsag.hh bch31_21.hh http.hh) aprs.hh baudot.hh pocsag.hh bch31_21.hh http.hh sha1.hh)
if(SDR_WITH_PORTAUDIO) if(SDR_WITH_PORTAUDIO)
set(LIBSDR_SOURCES ${LIBSDR_SOURCES} portaudio.cc) set(LIBSDR_SOURCES ${LIBSDR_SOURCES} portaudio.cc)

@ -1,7 +1,7 @@
#ifndef __SDR_BCH31_21_HH__ #ifndef __SDR_BCH31_21_HH__
#define __SDR_BCH31_21_HH__ #define __SDR_BCH31_21_HH__
#include <cinttypes> #include <inttypes.h>
namespace sdr { namespace sdr {

@ -0,0 +1,189 @@
/* This code is public-domain - it is based on libcrypt
* placed in the public domain by Wei Dai and other contributors.
*/
// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test
#include "sha1.hh"
#include <stdint.h>
#include <string.h>
using namespace sdr;
#ifdef __BIG_ENDIAN__
# define SHA_BIG_ENDIAN
#elif defined __LITTLE_ENDIAN__
/* override */
#elif defined __BYTE_ORDER
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SHA_BIG_ENDIAN
# endif
#else // ! defined __LITTLE_ENDIAN__
# include <endian.h> // machine/endian.h
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SHA_BIG_ENDIAN
# endif
#endif
/* code */
#define SHA1_K0 0x5a827999
#define SHA1_K20 0x6ed9eba1
#define SHA1_K40 0x8f1bbcdc
#define SHA1_K60 0xca62c1d6
void
sdr::sha1_init(sha1 *s) {
s->state[0] = 0x67452301;
s->state[1] = 0xefcdab89;
s->state[2] = 0x98badcfe;
s->state[3] = 0x10325476;
s->state[4] = 0xc3d2e1f0;
s->byteCount = 0;
s->bufferOffset = 0;
}
uint32_t
sdr::sha1_rol32(uint32_t number, uint8_t bits) {
return ((number << bits) | (number >> (32-bits)));
}
void
sdr::sha1_hashBlock(sha1 *s) {
uint8_t i;
uint32_t a,b,c,d,e,t;
a=s->state[0];
b=s->state[1];
c=s->state[2];
d=s->state[3];
e=s->state[4];
for (i=0; i<80; i++) {
if (i>=16) {
t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15];
s->buffer[i&15] = sha1_rol32(t,1);
}
if (i<20) {
t = (d ^ (b & (c ^ d))) + SHA1_K0;
} else if (i<40) {
t = (b ^ c ^ d) + SHA1_K20;
} else if (i<60) {
t = ((b & c) | (d & (b | c))) + SHA1_K40;
} else {
t = (b ^ c ^ d) + SHA1_K60;
}
t+=sha1_rol32(a,5) + e + s->buffer[i&15];
e=d;
d=c;
c=sha1_rol32(b,30);
b=a;
a=t;
}
s->state[0] += a;
s->state[1] += b;
s->state[2] += c;
s->state[3] += d;
s->state[4] += e;
}
void
sdr::sha1_addUncounted(sha1 *s, uint8_t data) {
uint8_t * const b = (uint8_t*) s->buffer;
#ifdef SHA_BIG_ENDIAN
b[s->bufferOffset] = data;
#else
b[s->bufferOffset ^ 3] = data;
#endif
s->bufferOffset++;
if (s->bufferOffset == SDR_SHA1_BLOCK_LENGTH) {
sha1_hashBlock(s);
s->bufferOffset = 0;
}
}
void
sdr::sha1_writebyte(sha1 *s, uint8_t data) {
++s->byteCount;
sha1_addUncounted(s, data);
}
void
sdr::sha1_write(sha1 *s, const char *data, size_t len) {
for (;len--;) sha1_writebyte(s, (uint8_t) *data++);
}
void
sdr::sha1_pad(sha1 *s) {
// Implement SHA-1 padding (fips180-2 §5.1.1)
// Pad with 0x80 followed by 0x00 until the end of the block
sha1_addUncounted(s, 0x80);
while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
// Append length in the last 8 bytes
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
sha1_addUncounted(s, 0); // So zero pad the top bits
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, s->byteCount >> 13); // byte.
sha1_addUncounted(s, s->byteCount >> 5);
sha1_addUncounted(s, s->byteCount << 3);
}
uint8_t*
sdr::sha1_result(sha1 *s) {
// Pad to complete the last block
sha1_pad(s);
#ifndef SHA_BIG_ENDIAN
// Swap byte order back
int i;
for (i=0; i<5; i++) {
s->state[i]=
(((s->state[i])<<24)& 0xff000000)
| (((s->state[i])<<8) & 0x00ff0000)
| (((s->state[i])>>8) & 0x0000ff00)
| (((s->state[i])>>24)& 0x000000ff);
}
#endif
// Return pointer to hash (20 characters)
return (uint8_t*) s->state;
}
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
void
sdr::sha1_initHmac(sha1 *s, const uint8_t* key, int keyLength) {
uint8_t i;
memset(s->keyBuffer, 0,SDR_SHA1_BLOCK_LENGTHH);
if (keyLength >SDR_SHA1_BLOCK_LENGTHH) {
// Hash long keys
sha1_init(s);
for (;keyLength--;) sha1_writebyte(s, *key++);
memcpy(s->keyBuffer, sha1_result(s),SDR_SHA1_HASH_LENGTHH);
} else {
// Block length keys are used as is
memcpy(s->keyBuffer, key, keyLength);
}
// Start inner hash
sha1_init(s);
for (i=0; iSDR_SHA1_BLOCK_LENGTHH; i++) {
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
}
}
uint8_t*
sdr::sha1_resultHmac(sha1 *s) {
uint8_t i;
// Complete inner hash
memcpy(s->innerHash,sha1_result(s)SDR_SHA1_HASH_LENGTHH);
// Calculate outer hash
sha1_init(s);
for (i=0; iSDR_SHA1_BLOCK_LENGTHH; i++) sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
for (i=0; iSDR_SHA1_HASH_LENGTHH; i++) sha1_writebyte(s, s->innerHash[i]);
return sha1_result(s);
}

@ -0,0 +1,43 @@
#ifndef __SDR_SHA1_HH__
#define __SDR_SHA1_HH__
#include <stdint.h>
namespace sdr {
/* header */
#define SDR_SHA1_HASH_LENGTH 20
#define SDR_SHA1_BLOCK_LENGTH 64
typedef struct {
uint32_t buffer[SDR_SHA1_BLOCK_LENGTH/4];
uint32_t state[SDR_SHA1_HASH_LENGTH/4];
uint32_t byteCount;
uint8_t bufferOffset;
uint8_t keyBuffer[SDR_SHA1_BLOCK_LENGTH];
uint8_t innerHash[SDR_SHA1_HASH_LENGTH];
} sha1;
/**
*/
void sha1_init(sha1 *s);
/**
*/
void sha1_writebyte(sha1 *s, uint8_t data);
/**
*/
void sha1_write(sha1 *s, const char *data, size_t len);
/**
*/
uint8_t* sha1_result(sha1 *s);
/**
*/
void sha1_initHmac(sha1 *s, const uint8_t* key, int keyLength);
/**
*/
uint8_t* sha1_resultHmac(sha1 *s);
}
#endif // __SDR_SHA1_HH__
Loading…
Cancel
Save