all the forgotten files
authorbg <daniel.otte@rub.de>
Fri, 18 Oct 2013 01:24:08 +0000 (03:24 +0200)
committerbg <daniel.otte@rub.de>
Fri, 18 Oct 2013 01:24:08 +0000 (03:24 +0200)
firmware/hmac-sha1.c [new file with mode: 0644]
firmware/hmac-sha1.h [new file with mode: 0644]
firmware/hotp.c [new file with mode: 0644]
firmware/hotp.h [new file with mode: 0644]
firmware/percnt2.c [new file with mode: 0644]
firmware/percnt2.h [new file with mode: 0644]
firmware/sha1-asm.S [new file with mode: 0644]
firmware/sha1.h [new file with mode: 0644]

diff --git a/firmware/hmac-sha1.c b/firmware/hmac-sha1.c
new file mode 100644 (file)
index 0000000..d6d750d
--- /dev/null
@@ -0,0 +1,130 @@
+/* hmac-sha1.c */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * 
+ * implementation of HMAC as described in RFC2104
+ * Author:      Daniel Otte
+ * email:       daniel.otte@rub.de
+ * License:     GPLv3 or later
+ **/
+
+/* 
+ * hmac = hash ( k^opad , hash( k^ipad  , msg))
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "sha1.h"
+#include "hmac-sha1.h"
+
+#define IPAD 0x36
+#define OPAD 0x5C
+
+
+#ifndef HMAC_SHORTONLY
+
+void hmac_sha1_init(hmac_sha1_ctx_t *s, const void *key, uint16_t keylength_b){
+       uint8_t buffer[SHA1_BLOCK_BYTES];
+       uint8_t i;
+       
+       memset(buffer, 0, SHA1_BLOCK_BYTES);
+       if (keylength_b > SHA1_BLOCK_BITS){
+               sha1((void*)buffer, key, keylength_b);
+       } else {
+               memcpy(buffer, key, (keylength_b+7)/8);
+       }
+       
+       for (i=0; i<SHA1_BLOCK_BYTES; ++i){
+               buffer[i] ^= IPAD;
+       }
+       sha1_init(&(s->a));
+       sha1_nextBlock(&(s->a), buffer);
+       
+       for (i=0; i<SHA1_BLOCK_BYTES; ++i){
+               buffer[i] ^= IPAD^OPAD;
+       }
+       sha1_init(&(s->b));
+       sha1_nextBlock(&(s->b), buffer);
+       
+       
+#if defined SECURE_WIPE_BUFFER
+       memset(buffer, 0, SHA1_BLOCK_BYTES);
+#endif
+}
+
+void hmac_sha1_nextBlock(hmac_sha1_ctx_t *s, const void *block){
+       sha1_nextBlock(&(s->a), block);
+}
+void hmac_sha1_lastBlock(hmac_sha1_ctx_t *s, const void *block, uint16_t length_b){
+       while(length_b>=SHA1_BLOCK_BITS){
+               sha1_nextBlock(&s->a, block);
+               block = (uint8_t*)block + SHA1_BLOCK_BYTES;
+               length_b -= SHA1_BLOCK_BITS;
+       }
+       sha1_lastBlock(&s->a, block, length_b);
+}
+
+void hmac_sha1_final(void *dest, hmac_sha1_ctx_t *s){
+       sha1_ctx2hash(dest, &s->a);
+       sha1_lastBlock(&s->b, dest, SHA1_HASH_BITS);
+       sha1_ctx2hash(dest, &(s->b));
+}
+
+#endif
+
+/*
+ * keylength in bits!
+ * message length in bits!
+ */
+void hmac_sha1(void *dest, const void *key, uint16_t keylength_b, const void *msg, uint32_t msglength_b){ /* a one-shot*/
+       sha1_ctx_t s;
+       uint8_t i;
+       uint8_t buffer[SHA1_BLOCK_BYTES];
+       
+       memset(buffer, 0, SHA1_BLOCK_BYTES);
+       
+       /* if key is larger than a block we have to hash it*/
+       if (keylength_b > SHA1_BLOCK_BITS){
+               sha1((void*)buffer, key, keylength_b);
+       } else {
+               memcpy(buffer, key, (keylength_b+7)/8);
+       }
+       
+       for (i=0; i<SHA1_BLOCK_BYTES; ++i){
+               buffer[i] ^= IPAD;
+       }
+       sha1_init(&s);
+       sha1_nextBlock(&s, buffer);
+       while (msglength_b >= SHA1_BLOCK_BITS){
+               sha1_nextBlock(&s, msg);
+               msg = (uint8_t*)msg + SHA1_BLOCK_BYTES;
+               msglength_b -=  SHA1_BLOCK_BITS;
+       }
+       sha1_lastBlock(&s, msg, msglength_b);
+       /* since buffer still contains key xor ipad we can do ... */
+       for (i=0; i<SHA1_BLOCK_BYTES; ++i){
+               buffer[i] ^= IPAD ^ OPAD;
+       }
+       sha1_ctx2hash(dest, &s); /* save inner hash temporary to dest */
+       sha1_init(&s);
+       sha1_nextBlock(&s, buffer);
+       sha1_lastBlock(&s, dest, SHA1_HASH_BITS);
+       sha1_ctx2hash(dest, &s);
+}
+
diff --git a/firmware/hmac-sha1.h b/firmware/hmac-sha1.h
new file mode 100644 (file)
index 0000000..fccd5ed
--- /dev/null
@@ -0,0 +1,41 @@
+/* hmac-sha1.h */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef HMACSHA1_H_
+#define HMACSHA1_H_
+
+#include "sha1.h"
+
+#define HMAC_SHA1_BITS        SHA1_HASH_BITS
+#define HMAC_SHA1_BYTES       SHA1_HASH_BYTES
+#define HMAC_SHA1_BLOCK_BITS  SHA1_BLOCK_BITS
+#define HMAC_SHA1_BLOCK_BYTES SHA1_BLOCK_BYTES
+
+typedef struct{
+        sha1_ctx_t a, b;
+} hmac_sha1_ctx_t;
+
+
+void hmac_sha1_init(hmac_sha1_ctx_t *s, const void *key, uint16_t keylength_b);
+void hmac_sha1_nextBlock(hmac_sha1_ctx_t *s, const void *block);
+void hmac_sha1_lastBlock(hmac_sha1_ctx_t *s, const void *block, uint16_t length_b);
+void hmac_sha1_final(void *dest, hmac_sha1_ctx_t *s);
+
+void hmac_sha1(void *dest, const void *key, uint16_t keylength_b, const void *msg, uint32_t msglength_b);
+
+#endif /*HMACSHA1_H_*/
diff --git a/firmware/hotp.c b/firmware/hotp.c
new file mode 100644 (file)
index 0000000..f0e7c3c
--- /dev/null
@@ -0,0 +1,75 @@
+/* htop.c */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2006-2013 Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <hmac-sha1.h>
+
+static
+uint32_t dtrunc(uint8_t* buffer) {
+    uint8_t idx;
+    union {
+        uint8_t w8[4];
+        uint32_t w32;
+    } r;
+
+    idx = buffer[19] & 0x0f;
+    r.w8[3] = buffer[idx++] & 0x7f;
+    r.w8[2] = buffer[idx++];
+    r.w8[1] = buffer[idx++];
+    r.w8[0] = buffer[idx];
+    return r.w32;
+}
+
+static
+void to_digits(char *buffer, uint32_t value, uint8_t digits) {
+    ldiv_t t;
+    if (value == 0) {
+        *buffer++ = '0';
+    }
+    while (value && digits--) {
+        t = ldiv(value, 10);
+        value = t.quot;
+        *buffer++ = t.rem + '0';
+    }
+    *buffer = '\0';
+}
+
+void hotp(char *buffer, void* secret, uint16_t secret_length_b, uint32_t counter, uint8_t digits) {
+    union {
+        uint8_t mac[20];
+        uint8_t ctr_buffer[8];
+    } d;
+    uint32_t s;
+    d.ctr_buffer[7] = 0;
+    d.ctr_buffer[6] = 0;
+    d.ctr_buffer[5] = 0;
+    d.ctr_buffer[4] = 0;
+    d.ctr_buffer[3] = counter & 0xff;
+    counter >>= 8;
+    d.ctr_buffer[2] = counter & 0xff;
+    counter >>= 8;
+    d.ctr_buffer[1] = counter & 0xff;
+    counter >>= 8;
+    d.ctr_buffer[0] = counter & 0xff;
+    hmac_sha1(d.mac, secret, secret_length_b, d.ctr_buffer, 64);
+    s = dtrunc(d.mac);
+    to_digits(buffer, s, digits);
+}
diff --git a/firmware/hotp.h b/firmware/hotp.h
new file mode 100644 (file)
index 0000000..8265e0c
--- /dev/null
@@ -0,0 +1,27 @@
+/* hotp.h */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2013 Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOTP_H_
+#define HOTP_H_
+
+#include <stdint.h>
+
+void hotp(char *buffer, void* secret, uint16_t secret_length_b, uint32_t counter, uint8_t digits);
+
+#endif /* HOTP_H_ */
diff --git a/firmware/percnt2.c b/firmware/percnt2.c
new file mode 100644 (file)
index 0000000..72769af
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * 
+ * author: Daniel Otte
+ * email:  daniel.otte@rub.de
+ * license: GPLv3
+ * 
+ */
+
+#include <stdlib.h> /* labs() */
+#include <stdint.h>
+#include <avr/eeprom.h>
+#include <avr/pgmspace.h>
+
+#ifndef PERCNT_NO
+ #define PERCNT_NO 1
+#endif
+
+#ifndef PERCNT_BPC /* bytes per counter */
+ #define PERCNT_BPC 16
+#endif
+
+#define PERCNT_MBS ((PERCNT_BPC + 7) / 8) /* mask block size */
+
+#ifndef PERCNT_CS
+ #define PERCNT_CS 4 /* counter size (max 4)*/
+#endif
+
+#define PERCNT_RESETONERROR
+
+#ifndef PERCNT_POLICY_INC
+ #ifndef PERCNT_POLICY_STAY
+ #define PERCNT_POLICY_INC
+// #error You have to specify a counter policy either PERCNT_POLICY_STAY or PERCNT_POLICY_INC
+ #endif
+#endif
+
+#ifdef PERCNT_POLICY_INC
+ #ifdef PERCNT_POLICY_STAY
+ #error You have to specify a counter policy either PERCNT_POLICY_STAY or PERCNT_POLICY_INC (not both)
+ #endif
+#endif
+
+uint8_t percnt_count[PERCNT_NO][3][PERCNT_BPC] EEMEM;
+
+uint8_t percnt_mb[PERCNT_NO][3][PERCNT_MBS] EEMEM;
+
+typedef enum __attribute__((packed)) {counterA = 0, counterB = 1, counterC = 2} percnt_active_t;
+
+percnt_active_t percnt_active[PERCNT_NO];
+
+#ifdef PERCNT_CACHE
+uint32_t percnt_cache[PERCNT_NO];
+#endif
+
+/**
+ * this function resets the counter given in the parameter back to zero
+ *  this is quite unsafe
+ */
+void percnt_reset(uint8_t counter) {
+       uint8_t i;
+       for (i = 0; i < PERCNT_BPC; ++i) {
+               eeprom_write_byte(&(percnt_count[counter][counterA][i]), 0);
+       }
+       eeprom_write_byte(&(percnt_count[counter][counterB][0]), 1);
+       for (i = 1; i < PERCNT_BPC; ++i) {
+               eeprom_write_byte(&(percnt_count[counter][counterB][i]), 0);
+       }
+       eeprom_write_byte(&(percnt_count[counter][counterC][0]), 2);
+       for (i = 1; i < PERCNT_BPC; ++i) {
+               eeprom_write_byte(&(percnt_count[counter][counterC][i]), 0);
+       }
+       for (i = 0; i < PERCNT_MBS; ++i) {
+               eeprom_write_byte(&(percnt_mb[counter][counterA][i]), 0);
+       }
+       for (i = 0; i < PERCNT_MBS; ++i) {
+               eeprom_write_byte(&(percnt_mb[counter][counterB][i]), 0);
+       }
+       for (i = 0; i < PERCNT_MBS; ++i) {
+               eeprom_write_byte(&(percnt_mb[counter][counterC][i]), 0);
+       }
+       percnt_active[counter] = counterC;
+}
+
+
+static const uint8_t bitcnt_lut_P[16] PROGMEM =
+    { 0, 1, 1, 2,  /* 0..3 */
+      1, 2, 2, 3,  /* 4..7 */
+      1, 2, 2, 3,  /* 8..B */
+      2, 3, 3, 4} ; /* C..F */
+
+
+static
+uint8_t bitcnt(const void* a, uint8_t length){
+       uint8_t ret = 0;
+       while (length--) {
+               ret += pgm_read_byte(&bitcnt_lut_P[(*((uint8_t*)a)) >> 4]);
+               ret += pgm_read_byte(&bitcnt_lut_P[(*((uint8_t*)a)) & 0x0f]);
+       }
+       return ret;
+}
+
+/**
+ * returns 0 if everything went right, 1 or even 2 in the case of failure
+ */
+static
+uint8_t percnt_writecntx(uint32_t v, uint8_t counter, percnt_active_t subc){
+       uint8_t maskb[PERCNT_MBS];
+       uint8_t free;
+       uint8_t i, j = 0, t;
+       eeprom_read_block(maskb, &(percnt_mb[counter][subc][0]), PERCNT_MBS);
+       free = PERCNT_BPC - bitcnt(maskb, PERCNT_MBS);
+       
+       for (i = 0; i < PERCNT_CS; ++i) {
+               if (free < PERCNT_CS) {
+                       /* we don't have enough bytes left, so we can't count anymore :-( */
+                       return 1;
+               }
+               /* get next usable byte */
+               while ((maskb[j / 8] >> (j % 8)) & 1)
+                       ++j;
+               t = eeprom_read_byte(&(percnt_count[counter][subc][j]));
+               if(t != ((uint8_t*)&v)[i]){
+                       /* we have to do a write */
+                       eeprom_write_byte(&(percnt_count[counter][subc][j]), ((uint8_t*)&v)[i]);
+                       /* and check back */
+                       t = eeprom_read_byte(&(percnt_count[counter][subc][j]));
+                       if(t != ((uint8_t*)&v)[i]){
+                               /* thats not good, readback failed */
+                               /* mark byte as bad */
+                               maskb[j / 8] |= 1 << (j % 8);
+                               eeprom_write_byte(&(percnt_mb[counter][subc][j / 8]), maskb[j / 8]);
+                               /* check back the maskblock write*/
+                               t = eeprom_read_byte(&(percnt_mb[counter][subc][j / 8]));
+                               if(t != maskb[j / 8]){
+                                       /* uargghh! that should not happen, our bad byte table has a bad byte*/
+                                       return 2;
+                               }
+                               --i; /* this makes this byte gets another try */
+                       }       
+               }
+               ++j;
+       }
+       return 0;
+}
+
+/******************************************************************************/
+
+static
+uint32_t percnt_readcntx(uint8_t counter, percnt_active_t subc){
+       uint32_t ret = 0;
+       uint8_t maskb[PERCNT_MBS];
+       uint8_t i, j = 0;
+       eeprom_read_block(maskb, &(percnt_mb[counter][subc][0]), PERCNT_MBS);
+       for (i = 0; i < PERCNT_CS; ++i) {
+               while (((maskb[j / 8]) >> (j % 8)) & 1)
+                       ++j;
+               ((uint8_t*)&ret)[i] = eeprom_read_byte(&(percnt_count[counter][subc][j]));
+               ++j;
+       }
+       return ret;
+}
+
+/******************************************************************************/
+
+uint32_t percnt_get(uint8_t counter) {
+       return percnt_readcntx(counter, percnt_active[counter]) - 2;
+}
+
+/******************************************************************************/
+
+uint8_t percnt_inc(uint8_t counter) {
+       uint32_t t;
+       t = percnt_get(counter);
+       percnt_active[counter] += 1;
+       if (percnt_active[counter] == 3)
+               percnt_active[counter] = 0;
+       return percnt_writecntx(t + 1 + 2, counter, percnt_active[counter]); /* remember, _get subtracts two */
+}
+
+/******************************************************************************/
+
+uint8_t percnt_init(uint8_t counter){
+       uint32_t a,b,c;
+       uint32_t dab, dac, dbc;
+       a = percnt_readcntx(counter, counterA);
+       b = percnt_readcntx(counter, counterB);
+       c = percnt_readcntx(counter, counterC);
+       dab = labs(a - b);
+       dac = labs(a - c);
+       dbc = labs(b - c);
+       if (dab == 1 && dbc == 1 && dac == 2) {
+               percnt_active[counter] = counterC;
+               return 0;
+       }
+       if(dab == 1 && dbc == 2 && dac == 1) {
+               percnt_active[counter] = counterB;
+               return 0;
+       }
+       if(dab == 2 && dbc == 1 && dac == 1){
+               percnt_active[counter] = counterA;
+               return 0;
+       }
+       
+       /* here it gets intresting */
+       if(dab == 1 || dac == 1 || dbc == 1){
+               /* we might got interrupted while incrementing */
+               /* action depends on policy either finish the increment or not */
+               #ifdef PERCNT_POLICY_STAY
+               if(dab == 1){
+                       percnt_active[counter]=(a < b) ? counterB : counterA;
+                       c = (a < b) ? (a - 1) : (b - 1);
+                       return percnt_writecntx(c, counter, counterC);
+               }
+               if(dac == 1){
+                       percnt_active[counter]=(a<c)?counterC:counterA;
+                       b = (a < c) ? (a - 1) : (c - 1);
+                       return percnt_writecntx(b, counter, counterB);
+               }
+               if(dbc == 1){
+                       percnt_active[counter]=(b<c)?counterC:counterB;
+                       a = (b < c) ? (b - 1) : (c - 1);
+                       return percnt_writecntx(a, counter, counterA);
+               }
+               #endif
+               #ifdef PERCNT_POLICY_INC
+               if(dab == 1){
+                       percnt_active[counter] = counterC;
+                       c = (a < b) ? (a - 1) : (b - 1);
+                       return percnt_writecntx(c + 1, counter, counterC);
+               }
+               if(dac == 1){
+                       percnt_active[counter] = counterB;
+                       b = (a < c) ? (a - 1) : (c - 1);
+                       return percnt_writecntx(b + 1, counter, counterB);
+               }
+               if(dbc == 1){
+                       percnt_active[counter] = counterA;
+                       a = (b < c) ? (b - 1) : (c - 1);
+                       return percnt_writecntx(a + 1, counter, counterA);
+               }
+               #endif
+       } else {
+               /* something really strange happened */
+               /* may be we have to initialize or so, but we must make sure that no one evil drives us here */
+               #ifdef PERCNT_RESETONERROR
+               percnt_reset(counter);
+               return 0;
+               #endif
+               
+               return 23;
+       }
+       /* we won't get here, but to keep the compile quiet: */
+       return 42;
+}
+
+
+
+
+
diff --git a/firmware/percnt2.h b/firmware/percnt2.h
new file mode 100644 (file)
index 0000000..9a92354
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef PERCNT2_H_
+#define PERCNT2_H_
+
+#include <stdint.h>
+
+
+#define PERCNT_OK 0
+#define PERCNT_ERROR 1
+#define PERCNT_HAVYERROR 2
+#define PERCNT_INITERROR 23
+#define PERCNT_STRANGEERROR 42
+
+void percnt_reset(uint8_t counter);
+uint32_t percnt_get(uint8_t counter);
+uint8_t percnt_inc(uint8_t counter);
+uint8_t percnt_init(uint8_t counter);
+
+#endif /*PERCNT2_H_*/
diff --git a/firmware/sha1-asm.S b/firmware/sha1-asm.S
new file mode 100644 (file)
index 0000000..f479fcc
--- /dev/null
@@ -0,0 +1,883 @@
+/* sha1-asm.S */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ * Author:     Daniel Otte
+ *
+ * License: GPLv3 or later
+*/
+; SHA1 implementation in assembler for AVR
+SHA1_BLOCK_BITS = 512
+SHA1_HASH_BITS = 160
+
+.macro precall
+       /* push r18 - r27, r30 - r31*/
+       push r0
+       push r1
+       push r18
+       push r19
+       push r20
+       push r21
+       push r22
+       push r23
+       push r24
+       push r25
+       push r26
+       push r27
+       push r30
+       push r31
+       clr r1
+.endm
+
+.macro postcall
+       pop r31
+       pop r30
+       pop r27
+       pop r26
+       pop r25
+       pop r24
+       pop r23
+       pop r22
+       pop r21
+       pop r20
+       pop r19
+       pop r18
+       pop r1
+       pop r0
+.endm
+
+
+.macro hexdump length
+       push r27
+       push r26
+       ldi r25, '\r'
+       mov r24, r25
+       call uart_putc
+       ldi r25, '\n'
+       mov r24, r25
+       call uart_putc
+       pop r26
+       pop r27
+       movw r24, r26
+.if \length > 16
+       ldi r22, lo8(16)
+       ldi r23, hi8(16)
+       push r27
+       push r26
+       call uart_hexdump
+       pop r26
+       pop r27
+       adiw r26, 16
+       hexdump \length-16
+.else
+       ldi r22, lo8(\length)
+       ldi r23, hi8(\length)
+       call uart_hexdump
+.endif
+.endm
+
+.macro delay
+/*
+       push r0
+       push r1
+       clr r0
+1:     clr r1
+2:     dec r1
+       brne 2b
+       dec r0
+       brne 1b
+       pop r1
+       pop r0  // */
+.endm
+
+/* X points to Block */
+.macro dbg_hexdump length
+/*
+       precall
+       hexdump \length
+       postcall
+       // */
+.endm
+
+
+
+.section .text
+
+SPL = 0x3D
+SPH = 0x3E
+SREG = 0x3F
+
+
+;
+;sha1_ctx_t is:
+;
+; [h0][h1][h2][h3][h4][length]
+; hn is 32 bit large, length is 64 bit large
+
+;###########################################################
+
+.global sha1_ctx2hash
+; === sha1_ctx2hash ===
+; this function converts a state into a normal hash (bytestring)
+;  param1: the 16-bit destination pointer
+;      given in r25,r24 (r25 is most significant)
+;  param2: the 16-bit pointer to sha1_ctx structure
+;      given in r23,r22
+sha1_ctx2hash:
+       movw r26, r22
+       movw r30, r24
+       ldi r21, 5
+       sbiw r26, 4
+1:
+       ldi r20, 4
+       adiw r26, 8
+2:
+               ld r0, -X
+               st Z+, r0
+       dec r20
+       brne 2b
+
+       dec r21
+       brne 1b
+
+       ret
+
+;###########################################################
+
+.global sha1
+; === sha1 ===
+; this function calculates SHA-1 hashes from messages in RAM
+;  param1: the 16-bit hash destination pointer
+;      given in r25,r24 (r25 is most significant)
+;  param2: the 16-bit pointer to message
+;      given in r23,r22
+;  param3: 32-bit length value (length of message in bits)
+;   given in r21,r20,r19,r18
+sha1:
+sha1_prolog:
+       push r8
+       push r9
+       push r10
+       push r11
+       push r12
+       push r13
+       push r16
+       push r17
+       in r30, SPL
+       in r31, SPH
+       sbiw r30, 5*4+8
+       in r0, SREG
+       cli
+       out SPL, r30
+       out SREG, r0
+       out SPH, r31
+
+       push r25
+       push r24
+       adiw r30, 1
+       movw r16, r30
+
+       movw r8, r18            /* backup of length*/
+       movw r10, r20
+
+       movw r12, r22   /* backup pf msg-ptr */
+
+       movw r24, r16
+       rcall sha1_init
+       /* if length >= 512 */
+1:
+       tst r11
+       brne 2f
+       tst r10
+       breq 4f
+2:
+       movw r24, r16
+       movw r22, r12
+       rcall sha1_nextBlock
+       ldi r19, 64
+       add r12, r19
+       adc r13, r1
+       /* length -= 512 */
+       ldi r19, 0x02
+       sub r9, r19
+       sbc r10, r1
+       sbc r11, r1
+       rjmp 1b
+
+4:
+       movw r24, r16
+       movw r22, r12
+       movw r20, r8
+       rcall sha1_lastBlock
+
+       pop r24
+       pop r25
+       movw r22, r16
+       rcall sha1_ctx2hash
+
+sha1_epilog:
+       in r30, SPL
+       in r31, SPH
+       adiw r30, 5*4+8
+       in r0, SREG
+       cli
+       out SPL, r30
+       out SREG, r0
+       out SPH, r31
+       pop r17
+       pop r16
+       pop r13
+       pop r12
+       pop r11
+       pop r10
+       pop r9
+       pop r8
+       ret
+
+;###########################################################
+
+
+; block MUST NOT be larger than 64 bytes
+
+.global sha1_lastBlock
+; === sha1_lastBlock ===
+; this function does padding & Co. for calculating SHA-1 hashes
+;  param1: the 16-bit pointer to sha1_ctx structure
+;      given in r25,r24 (r25 is most significant)
+;  param2: an 16-bit pointer to 64 byte block to hash
+;      given in r23,r22
+;  param3: an 16-bit integer specifing length of block in bits
+;      given in r21,r20
+sha1_lastBlock_localSpace = (SHA1_BLOCK_BITS/8+1)
+
+
+sha1_lastBlock:
+       cpi r21, 0x02
+       brlo sha1_lastBlock_prolog
+       push r25
+       push r24
+       push r23
+       push r22
+       push r21
+       push r20
+       rcall sha1_nextBlock
+       pop r20
+       pop r21
+       pop r22
+       pop r23
+       pop r24
+       pop r25
+       subi r21, 2
+       ldi r19, 64
+       add r22, r19
+       adc r23, r1
+       rjmp sha1_lastBlock
+sha1_lastBlock_prolog:
+       /* allocate space on stack */
+       in r30, SPL
+       in r31, SPH
+       in r0, SREG
+       subi r30, lo8(64)
+       sbci r31, hi8(64) /* ??? */
+       cli
+       out SPL, r30
+       out SREG, r0
+       out SPH, r31
+
+       adiw r30, 1 /* SP points to next free byte on stack */
+       mov r18, r20 /* r20 = LSB(length) */
+       lsr r18
+       lsr r18
+       lsr r18
+       bst r21, 0      /* may be we should explain this ... */
+       bld r18, 5  /* now: r18 == length/8 (aka. length in bytes) */
+
+
+       movw r26, r22 /* X points to begin of msg */
+       tst r18
+       breq sha1_lastBlock_post_copy
+       mov r1, r18
+sha1_lastBlock_copy_loop:
+       ld r0, X+
+       st Z+, r0
+       dec r1
+       brne sha1_lastBlock_copy_loop
+sha1_lastBlock_post_copy:
+sha1_lastBlock_insert_stuffing_bit:
+       ldi r19, 0x80
+       mov r0,r19
+       ldi r19, 0x07
+       and r19, r20 /* if we are in bitmode */
+       breq 2f /* no bitmode */
+1:
+       lsr r0
+       dec r19
+       brne 1b
+       ld r19, X
+/* maybe we should do some ANDing here, just for safety */
+       or r0, r19
+2:
+       st Z+, r0
+       inc r18
+
+/* checking stuff here */
+       cpi r18, 64-8+1
+       brsh 0f
+       rjmp sha1_lastBlock_insert_zeros
+0:
+       /* oh shit, we landed here */
+       /* first we have to fill it up with zeros */
+       ldi r19, 64
+       sub r19, r18
+       breq 2f
+1:
+       st Z+, r1
+       dec r19
+       brne 1b
+2:
+       sbiw r30, 63
+       sbiw r30,  1
+       movw r22, r30
+
+       push r31
+       push r30
+       push r25
+       push r24
+       push r21
+       push r20
+       rcall sha1_nextBlock
+       pop r20
+       pop r21
+       pop r24
+       pop r25
+       pop r30
+       pop r31
+
+       /* now we should subtract 512 from length */
+       movw r26, r24
+       adiw r26, 4*5+1 /* we can skip the lowest byte */
+       ld r19, X
+       subi r19, hi8(512)
+       st X+, r19
+       ldi r18, 6
+1:
+       ld r19, X
+       sbci r19, 0
+       st X+, r19
+       dec r18
+       brne 1b
+
+;      clr r18 /* not neccessary ;-) */
+       /* reset Z pointer to begin of block */
+
+sha1_lastBlock_insert_zeros:
+       ldi r19, 64-8
+       sub r19, r18
+       breq sha1_lastBlock_insert_length
+       clr r1
+1:
+       st Z+, r1       /* r1 is still zero */
+       dec r19
+       brne 1b
+
+;      rjmp sha1_lastBlock_epilog
+sha1_lastBlock_insert_length:
+       movw r26, r24   /* X points to state */
+       adiw r26, 5*4   /* X points to (state.length) */
+       adiw r30, 8             /* Z points one after the last byte of block */
+       ld r0, X+
+       add r0, r20
+       st -Z, r0
+       ld r0, X+
+       adc r0, r21
+       st -Z, r0
+       ldi r19, 6
+1:
+       ld r0, X+
+       adc r0, r1
+       st -Z, r0
+       dec r19
+       brne 1b
+
+       sbiw r30, 64-8
+       movw r22, r30
+       rcall sha1_nextBlock
+
+sha1_lastBlock_epilog:
+       in r30, SPL
+       in r31, SPH
+       in r0, SREG
+       adiw r30, 63 ; lo8(64)
+       adiw r30,  1  ; hi8(64)
+       cli
+       out SPL, r30
+       out SREG, r0
+       out SPH, r31
+       clr r1
+       ret
+
+/**/
+;###########################################################
+
+.global sha1_nextBlock
+; === sha1_nextBlock ===
+; this is the core function for calculating SHA-1 hashes
+;  param1: the 16-bit pointer to sha1_ctx structure
+;      given in r25,r24 (r25 is most significant)
+;  param2: an 16-bit pointer to 64 byte block to hash
+;      given in r23,r22
+sha1_nextBlock_localSpace = (16+5+1)*4 ; 16 32-bit values for w array and 5 32-bit values for a array (total 84 byte)
+
+xtmp = 0
+xNULL = 1
+W1 = 10
+W2 = 11
+T1     = 12
+T2     = 13
+T3     = 14
+T4     = 15
+LoopC = 16
+S        = 17
+tmp1 = 18
+tmp2 = 19
+tmp3 = 20
+tmp4 = 21
+F1 = 22
+F2 = 23
+F3 = 24
+F4 = 25
+
+/* byteorder: high number <--> high significance */
+sha1_nextBlock:
+ ; initial, let's make some space ready for local vars
+                        /* replace push & pop by mem ops? */
+       push r10
+       push r11
+       push r12
+       push r13
+       push r14
+       push r15
+       push r16
+       push r17
+       push r28
+       push r29
+       in r20, SPL
+       in r21, SPH
+       movw r18, r20                   ;backup SP
+;      movw r26, r20                   ; X points to free space on stack /* maybe removeable? */
+       movw r30, r22                   ; Z points to message
+       subi r20, lo8(sha1_nextBlock_localSpace) ;sbiw can do only up to 63
+       sbci r21, hi8(sha1_nextBlock_localSpace)
+       movw r26, r20                   ; X points to free space on stack
+       in r0, SREG
+       cli ; we want to be uninterrupted while updating SP
+       out SPL, r20
+       out SREG, r0
+       out SPH, r21
+
+       push r18
+       push r19 /* push old SP on new stack */
+       push r24
+       push r25 /* param1 will be needed later */
+
+       /* load a[] with state */
+       movw 28, r24 /* load pointer to state in Y */
+       adiw r26, 1 ; X++
+
+       ldi LoopC, 5*4
+1:     ld tmp1, Y+
+       st X+, tmp1
+       dec LoopC
+       brne 1b
+
+       movw W1, r26 /* save pointer to w[0] */
+       /* load w[] with endian fixed message */
+               /* we might also use the changeendian32() function at bottom */
+       movw r30, r22 /* mv param2 (ponter to msg) to Z */
+       ldi LoopC, 16
+1:
+       ldd tmp1, Z+3
+       st X+, tmp1
+       ldd tmp1, Z+2
+       st X+, tmp1
+       ldd tmp1, Z+1
+       st X+, tmp1
+       ld tmp1, Z
+       st X+, tmp1
+       adiw r30, 4
+       dec LoopC
+       brne 1b
+
+       ;clr LoopC /* LoopC is named t in FIPS 180-2 */
+       clr xtmp
+sha1_nextBlock_mainloop:
+       mov S, LoopC
+       lsl S
+       lsl S
+       andi S, 0x3C /* S is a bytepointer so *4 */
+       /* load w[s] */
+       movw r26, W1
+       add r26, S /* X points at w[s] */
+       adc r27, xNULL
+       ld T1, X+
+       ld T2, X+
+       ld T3, X+
+       ld T4, X+
+
+/*
+       push r26
+       push r27
+       push T4
+       push T3
+       push T2
+       push T1
+       in r26, SPL
+       in r27, SPH
+       adiw r26, 1
+       dbg_hexdump 4
+       pop T1
+       pop T2
+       pop T3
+       pop T4
+       pop r27
+       pop r26
+*/
+
+       cpi LoopC, 16
+       brlt sha1_nextBlock_mainloop_core
+       /* update w[s] */
+       ldi tmp1, 2*4
+       rcall 1f
+       ldi tmp1, 8*4
+       rcall 1f
+       ldi tmp1, 13*4
+       rcall 1f
+       rjmp 2f
+1:             /* this might be "outsourced" to save the jump above */
+       add tmp1, S
+       andi tmp1, 0x3f
+       movw r26, W1
+       add r26, tmp1
+       adc r27, xNULL
+       ld tmp2, X+
+       eor T1, tmp2
+       ld tmp2, X+
+       eor T2, tmp2
+       ld tmp2, X+
+       eor T3, tmp2
+       ld tmp2, X+
+       eor T4, tmp2
+       ret
+2:     /* now we just hav to do a ROTL(T) and save T back */
+       mov tmp2, T4
+       rol tmp2
+       rol T1
+       rol T2
+       rol T3
+       rol T4
+       movw r26, W1
+       add r26, S
+       adc r27, xNULL
+       st X+, T1
+       st X+, T2
+       st X+, T3
+       st X+, T4
+
+sha1_nextBlock_mainloop_core:  /* ther core function; T=ROTL5(a) ....*/
+                                                               /* T already contains w[s] */
+       movw r26, W1
+       sbiw r26, 4*1           /* X points at a[4] aka e */
+       ld tmp1, X+
+       add T1, tmp1
+       ld tmp1, X+
+       adc T2, tmp1
+       ld tmp1, X+
+       adc T3, tmp1
+       ld tmp1, X+
+       adc T4, tmp1            /* T = w[s]+e */
+       sbiw r26, 4*5           /* X points at a[0] aka a */
+       ld F1, X+
+       ld F2, X+
+       ld F3, X+
+       ld F4, X+
+       mov tmp1, F4            /* X points at a[1] aka b */
+       ldi tmp2, 5
+1:
+       rol tmp1
+       rol F1
+       rol F2
+       rol F3
+       rol F4
+       dec tmp2
+       brne 1b
+
+       add T1, F1
+       adc T2, F2
+       adc T3, F3
+       adc T4, F4 /* T = ROTL(a,5) + e + w[s] */
+
+       /* now we have to do this fucking conditional stuff */
+       ldi r30, lo8(sha1_nextBlock_xTable)
+       ldi r31, hi8(sha1_nextBlock_xTable)
+       add r30, xtmp
+       adc r31, xNULL
+       lpm tmp1, Z
+       cp tmp1, LoopC
+       brne 1f
+       inc xtmp
+1:     ldi r30, lo8(sha1_nextBlock_KTable)
+       ldi r31, hi8(sha1_nextBlock_KTable)
+       lsl xtmp
+       lsl xtmp
+       add r30, xtmp
+       adc r31, xNULL
+       lsr xtmp
+       lsr xtmp
+
+       lpm tmp1, Z+
+       add T1, tmp1
+       lpm tmp1, Z+
+       adc T2, tmp1
+       lpm tmp1, Z+
+       adc T3, tmp1
+       lpm tmp1, Z+
+       adc T4, tmp1
+                       /* T = ROTL(a,5) + e + kt + w[s] */
+
+       /* Z-4 is just pointing to kt ... */
+       movw r28, r26 /* copy X in Y */
+       adiw r30, 3*4 /* now Z points to the rigth locatin in our jump-vector-table */
+       lsr r31
+       ror r30
+
+       icall
+       mov F1, tmp1
+       icall
+       mov F2, tmp1
+       icall
+       mov F3, tmp1
+       icall
+
+       add T1, F1
+       adc T2, F2
+       adc T3, F3
+       adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */
+                                /* X points still at a[1] aka b, Y points at a[2] aka c */
+       /* update a[] */
+sha1_nextBlock_update_a:
+       /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/
+       //adiw r28, 3*4  /* Y should point at a[4] aka e */
+       movw r28, W1
+       sbiw r28, 4
+
+       ldi tmp2, 4*4
+1:
+       ld tmp1, -Y
+       std Y+4, tmp1
+       dec tmp2
+       brne 1b
+       /* Y points at a[0] aka a*/
+
+       movw r28, W1
+       sbiw r28, 5*4
+       /* store T in a[0] aka a */
+       st Y+, T1
+       st Y+, T2
+       st Y+, T3
+       st Y+, T4
+       /* Y points at a[1] aka b*/
+
+       /* rotate c */
+       ldd T1, Y+1*4
+       ldd T2, Y+1*4+1
+       ldd T3, Y+1*4+2
+       ldd T4, Y+1*4+3
+       mov tmp1, T1
+       ldi tmp2, 2
+1:     ror tmp1
+       ror T4
+       ror T3
+       ror T2
+       ror T1
+       dec tmp2
+       brne 1b
+       std Y+1*4+0, T1
+       std Y+1*4+1, T2
+       std Y+1*4+2, T3
+       std Y+1*4+3, T4
+/*
+       push r27
+       push r26
+       movw r26, W1
+       sbiw r26, 4*5
+       dbg_hexdump 4*5
+       pop r26
+       pop r27
+*/
+       inc LoopC
+       cpi LoopC, 80
+       brge 1f
+       rjmp sha1_nextBlock_mainloop
+/**************************************/
+1:
+   /* littel patch */
+       sbiw r28, 4
+
+/* add a[] to state and inc length */
+       pop r27
+       pop r26         /* now X points to state (and Y still at a[0]) */
+       ldi tmp4, 5
+1:     clc
+       ldi tmp3, 4
+2:     ld tmp1, X
+       ld tmp2, Y+
+       adc tmp1, tmp2
+       st X+, tmp1
+       dec tmp3
+       brne 2b
+       dec tmp4
+       brne 1b
+
+       /* now length += 512 */
+       adiw r26, 1 /* we skip the least significant byte */
+       ld tmp1, X
+       ldi tmp2, hi8(512) /* 2 */
+       add tmp1, tmp2
+       st X+, tmp1
+       ldi tmp2, 6
+1:
+       ld tmp1, X
+       adc tmp1, xNULL
+       st X+, tmp1
+       dec tmp2
+       brne 1b
+
+; EPILOG
+sha1_nextBlock_epilog:
+/* now we should clean up the stack */
+       pop r21
+       pop r20
+       in r0, SREG
+       cli ; we want to be uninterrupted while updating SP
+       out SPL, r20
+       out SREG, r0
+       out SPH, r21
+
+       clr r1
+       pop r29
+       pop r28
+       pop r17
+       pop r16
+       pop r15
+       pop r14
+       pop r13
+       pop r12
+       pop r11
+       pop r10
+       ret
+
+sha1_nextBlock_xTable:
+.byte 20,40,60,0
+sha1_nextBlock_KTable:
+.int   0x5a827999
+.int   0x6ed9eba1
+.int   0x8f1bbcdc
+.int   0xca62c1d6
+sha1_nextBlock_JumpTable:
+rjmp sha1_nextBlock_Ch
+       nop
+rjmp sha1_nextBlock_Parity
+       nop
+rjmp sha1_nextBlock_Maj
+       nop
+rjmp sha1_nextBlock_Parity
+
+        /* X and Y still point at a[1] aka b ; return value in tmp1 */
+sha1_nextBlock_Ch:
+       ld tmp1, Y+
+       mov tmp2, tmp1
+       com tmp2
+       ldd tmp3, Y+3   /* load from c */
+       and tmp1, tmp3
+       ldd tmp3, Y+7   /* load from d */
+       and tmp2, tmp3
+       eor tmp1, tmp2
+       ret
+
+sha1_nextBlock_Maj:
+       ld tmp1, Y+
+       mov tmp2, tmp1
+       ldd tmp3, Y+3   /* load from c */
+       and tmp1, tmp3
+       ldd tmp4, Y+7   /* load from d */
+       and tmp2, tmp4
+       eor tmp1, tmp2
+       and tmp3, tmp4
+       eor tmp1, tmp3
+       ret
+
+sha1_nextBlock_Parity:
+       ld tmp1, Y+
+       ldd tmp2, Y+3   /* load from c */
+       eor tmp1, tmp2
+       ldd tmp2, Y+7   /* load from d */
+       eor tmp1, tmp2
+       ret
+/*
+ch_str:                        .asciz "\r\nCh"
+maj_str:               .asciz "\r\nMaj"
+parity_str:    .asciz "\r\nParity"
+*/
+;###########################################################
+
+.global sha1_init
+;void sha1_init(sha1_ctx_t *state){
+;      DEBUG_S("\r\nSHA1_INIT");
+;      state->h[0] = 0x67452301;
+;      state->h[1] = 0xefcdab89;
+;      state->h[2] = 0x98badcfe;
+;      state->h[3] = 0x10325476;
+;      state->h[4] = 0xc3d2e1f0;
+;      state->length = 0;
+;}
+; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram
+; modifys: Z(r30,r31), Func1, r22
+sha1_init:
+       movw r26, r24 ; (24,25) --> (26,27) load X with param1
+       ldi r30, lo8((sha1_init_vector))
+       ldi r31, hi8((sha1_init_vector))
+       ldi r22, 5*4 /* bytes to copy */
+sha1_init_vloop:
+       lpm r23, Z+
+       st X+, r23
+       dec r22
+       brne sha1_init_vloop
+       ldi r22, 8
+sha1_init_lloop:
+       st X+, r1
+       dec r22
+       brne sha1_init_lloop
+       ret
+
+sha1_init_vector:
+.int 0x67452301;
+.int 0xefcdab89;
+.int 0x98badcfe;
+.int 0x10325476;
+.int 0xc3d2e1f0;
+
diff --git a/firmware/sha1.h b/firmware/sha1.h
new file mode 100644 (file)
index 0000000..0da9ee7
--- /dev/null
@@ -0,0 +1,119 @@
+/* sha1.h */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file       sha1.h
+ * \author     Daniel Otte
+ * \email   daniel.otte@rub.de
+ * \date       2006-10-08
+ * \license GPLv3 or later
+ * \brief   SHA-1 declaration.
+ * \ingroup SHA-1
+ * 
+ */
+#ifndef SHA1_H_
+#define SHA1_H_
+
+#include <stdint.h>
+/** \def SHA1_HASH_BITS
+ * definees the size of a SHA-1 hash in bits 
+ */
+
+/** \def SHA1_HASH_BYTES
+ * definees the size of a SHA-1 hash in bytes 
+ */
+
+/** \def SHA1_BLOCK_BITS
+ * definees the size of a SHA-1 input block in bits 
+ */
+
+/** \def SHA1_BLOCK_BYTES
+ * definees the size of a SHA-1 input block in bytes 
+ */
+#define SHA1_HASH_BITS  160
+#define SHA1_HASH_BYTES (SHA1_HASH_BITS/8)
+#define SHA1_BLOCK_BITS 512
+#define SHA1_BLOCK_BYTES (SHA1_BLOCK_BITS/8)
+
+/** \typedef sha1_ctx_t
+ * \brief SHA-1 context type
+ * 
+ * A vatiable of this type may hold the state of a SHA-1 hashing process
+ */
+typedef struct {
+       uint32_t h[5];
+       uint64_t length;
+} sha1_ctx_t;
+
+/** \typedef sha1_hash_t
+ * \brief hash value type
+ * A variable of this type may hold a SHA-1 hash value 
+ */
+/*
+typedef uint8_t sha1_hash_t[SHA1_HASH_BITS/8];
+*/
+
+/** \fn sha1_init(sha1_ctx_t *state)
+ * \brief initializes a SHA-1 context
+ * This function sets a ::sha1_ctx_t variable to the initialization vector
+ * for SHA-1 hashing.
+ * \param state pointer to the SHA-1 context variable
+ */
+void sha1_init(sha1_ctx_t *state);
+
+/** \fn sha1_nextBlock(sha1_ctx_t *state, const void *block)
+ *  \brief process one input block
+ * This function processes one input block and updates the hash context 
+ * accordingly
+ * \param state pointer to the state variable to update
+ * \param block pointer to the message block to process
+ */
+void sha1_nextBlock (sha1_ctx_t *state, const void *block);
+
+/** \fn sha1_lastBlock(sha1_ctx_t *state, const void *block, uint16_t length_b)
+ * \brief processes the given block and finalizes the context
+ * This function processes the last block in a SHA-1 hashing process.
+ * The block should have a maximum length of a single input block.
+ * \param state pointer to the state variable to update and finalize
+ * \param block pointer to themessage block to process
+ * \param length_b length of the message block in bits  
+ */
+void sha1_lastBlock (sha1_ctx_t *state, const void *block, uint16_t length_b);
+
+/** \fn sha1_ctx2hash(sha1_hash_t *dest, sha1_ctx_t *state)
+ * \brief convert a state variable into an actual hash value
+ * Writes the hash value corresponding to the state to the memory pointed by dest.
+ * \param dest pointer to the hash value destination
+ * \param state pointer to the hash context
+ */ 
+void sha1_ctx2hash (void *dest, sha1_ctx_t *state);
+
+/** \fn sha1(sha1_hash_t *dest, const void *msg, uint32_t length_b)
+ * \brief hashing a message which in located entirely in RAM
+ * This function automatically hashes a message which is entirely in RAM with
+ * the SHA-1 hashing algorithm.
+ * \param dest pointer to the hash value destination
+ * \param msg  pointer to the message which should be hashed
+ * \param length_b length of the message in bits
+ */ 
+void sha1(void *dest, const void *msg, uint32_t length_b);
+
+
+
+#endif /*SHA1_H_*/