diff --git a/ATMegaCard/ISO7816-card.c b/ATMegaCard/ISO7816-card.c
new file mode 100644
index 0000000000000000000000000000000000000000..d82cf617a6eae3f444916639fa902a3c10a378cf
--- /dev/null
+++ b/ATMegaCard/ISO7816-card.c
@@ -0,0 +1,345 @@
+#include "ISO7816-card.h"
+#include "common.h"
+#include <util/delay.h>
+#include <string.h>
+
+//ATMega Card
+//ATR: 3B8F014156522049534F3738313620302E31B9
+//Query: 00C101FE3E00000267016400C101FE3E00000267016400C101FE3E000002670164
+
+//Java Card
+//ATR: 3BFA1800FF8131FE454A434F5032315632333165
+//Query: FF1118F6FF1118F6F8FF38F8E098E0003BFA1800FF8131FE454A434F5032315632333165
+static apdu_handler_t handler;
+
+//                  TS    T0     TA1   TB1   TC1   TD1(T=1)
+ISO7816_ATR atr = {0x3B, 0x9F, {{0x11, 0x00, 0x00, 0x01},
+//                               TA2   TB2   TC2   TD2 (unused)
+                                {0x00, 0x00, 0x00, 0x00},
+//                               TA3   TB3   TC3   TD3 (unused)
+                                {0x00, 0x00, 0x00, 0x00},
+//                               TA4   TB4   TC4   TD4 (unused)
+                                {0x00, 0x00, 0x00, 0x00},
+//                               TA5   TB5   TC5   TD5 (unused)
+                                {0x00, 0x00, 0x00, 0x00}},
+                   //Historical Bytes
+                   {0x41,0x56,0x52,0x20,0x49,0x53,0x4f,0x37,0x38,0x31,0x36,0x20,0x30,0x2e,0x31},
+                   0}; //Checksum
+
+// unsigned char atr[] = {0x3B, 0xFA, 0x18, 0x00, 0xFF , 0x81 , 0x31 , 0xFE , 0x45 , 0x4A , 0x43 , 0x4F , 0x50 , 0x32 , 0x31 , 0x56 , 0x32 , 0x33 , 0x31, 0x65};
+
+uint16_t ISO7816_receive_buffer(uint8_t* buffer, uint8_t length);
+uint8_t  ISO7816_transmit_buffer(uint8_t* buffer, uint8_t length);
+uint8_t  ISO7816_transmit_t1_header(ISO7816_T1_Header* t1_header);
+
+void ISO7816_init(void){
+	UART_init();
+}
+/*
+void ISO7816_sendATR(void){
+	UART_transmit_init();
+	for (uint8_t i = 0; i < sizeof(atr); i++){
+		UART_transmit_char(atr[i]);
+	}
+	UART_recv_init();
+}*/
+
+void ISO7816_sendATR(void){
+	uint8_t checksum = 0;
+	UART_transmit_init();
+	UART_transmit_char(atr.initial_char);
+	checksum ^= atr.t0; UART_transmit_char(atr.t0);
+	
+	uint8_t num_hist_bytes = NUM_HIST_BYTES(atr);
+	uint8_t next_interface_bytes = INTERFACE_BYTE_SET(atr, 0);
+	uint8_t i = 0;
+	while (next_interface_bytes){
+		if (next_interface_bytes & TA) {checksum ^= atr.interface_bytes[i].ta; UART_transmit_char(atr.interface_bytes[i].ta);}
+		if (next_interface_bytes & TB) {checksum ^= atr.interface_bytes[i].tb; UART_transmit_char(atr.interface_bytes[i].tb);}
+		if (next_interface_bytes & TC) {checksum ^= atr.interface_bytes[i].tc; UART_transmit_char(atr.interface_bytes[i].tc);}
+		if (next_interface_bytes & TD) {checksum ^= atr.interface_bytes[i].td; UART_transmit_char(atr.interface_bytes[i].td);}
+		i++;
+		next_interface_bytes = INTERFACE_BYTE_SET(atr, i);
+	}
+	for (i = 0; i < num_hist_bytes; i++){
+		checksum ^= atr.historical_bytes[i];
+		UART_transmit_char(atr.historical_bytes[i]);
+	}
+	UART_transmit_char(checksum);
+	UART_recv_init();
+// 	UART_read_char();
+}
+
+uint8_t ISO7816_data_available(void){
+	return UART_data_available();
+}
+
+#define RECV_ERROR(new_status) {status = (status == ISO7816_STATUS_OK) ? new_status : status;}
+
+uint16_t process_pts(void){
+	uint8_t checksum = 0xFF; //PTSS = 0xFF, so we start with that
+	uint16_t ret;
+	uint8_t c;
+	uint8_t pts0;
+	uint8_t pts1;
+	uint8_t pts2;
+	uint8_t pts3;
+	
+	ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+	if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+	pts0 = ret & 0xFF;
+	checksum ^= pts0;
+	
+	if (pts0 & 0x10){ //PTS1 avail
+		ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+		pts1 = ret & 0xFF;
+		checksum ^= pts1;
+	}
+	if (pts0 & 0x20){ //PTS2 avail
+		ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+		pts2 = ret & 0xFF;
+		checksum ^= pts2;
+	}
+	if (pts0 & 0x40){ //PTS3 avail
+		ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+		pts3 = ret & 0xFF;
+		checksum ^= pts3;
+	}
+	
+	ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+	if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+	c = ret & 0xFF;
+	checksum ^= c;
+	
+	if (c != checksum) return ISO7816_STATUS_ERR_DATA_INVALID;
+	_delay_us(300);
+	
+	UART_transmit_init();
+	UART_transmit_char(0xFF); //PTSS
+	UART_transmit_char(pts0);
+	if (pts0 & 0x10) UART_transmit_char(pts1);
+	if (pts0 & 0x20) UART_transmit_char(pts2);
+	if (pts0 & 0x40) UART_transmit_char(pts3);
+	UART_transmit_char(checksum);
+	
+	UART_recv_init();
+	
+	return ISO7816_STATUS_OK;
+}
+
+uint8_t ISO7816_read_t1_header(ISO7816_T1_Header* h, uint8_t* checksum){
+	uint16_t ret;
+	uint8_t c = 0;
+// 	static uint8_t first = 0;
+	
+// 	if (first){
+// 		while (c == 0x00){
+// 			//NAD (Node Address, not used)
+// 			ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+// 			if (ret == UART_ERR_TIMEOUT) return 0;
+// 			c = ret & 0xFF;
+// 			*checksum ^= c;
+// 			if (c == 0xFF) {process_pts(); return 0;}
+// 		}
+// 		h->node_address = 0;
+// 		
+// 		first = 0;
+// 	} else {
+		//NAD (Node Address, not used)
+		ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return 0;
+		c = ret & 0xFF;
+		*checksum ^= c;
+		if (c == 0xFF) {process_pts(); return 0;}
+		h->node_address = c;
+		
+		// 	Protocol control byte
+		c = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return 0;
+		c = ret & 0xFF;
+		*checksum ^= c;
+		
+// 		first = 1;
+// 	}
+	
+	h->protocol_control = c;
+// 	if (!(seq_number && (c & 0x40))) RECV_ERROR(ISO7816_STATUS_ERR_UNKNOWN); //TODO: Better response? Or no response? This is below the APDU level
+	
+	//Message Length
+	ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+	if (ret == UART_ERR_TIMEOUT) return 0;
+	c = ret & 0xFF;
+	*checksum ^= c;
+	h->message_length = c;
+	
+	return 1;
+}
+
+uint16_t ISO7816_read_t1_trailer(uint8_t checksum){
+	uint16_t ret;
+	uint8_t c;
+	
+	ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+	if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+	c = ret & 0xFF;
+	
+// 	if (c != checksum) return ISO7816_STATUS_ERR_DATA_INVALID;
+	
+	return 1;
+}
+
+void ISO7816_process_apdu(ISO7816_T1_Header* t1_header, uint8_t* message_buffer){
+	uint16_t status = ISO7816_STATUS_OK;
+	
+	ISO7816_APDU_Header *apdu_header = (ISO7816_APDU_Header*)&message_buffer[0];
+	uint8_t* payload = &message_buffer[APDU_PAYLOAD_OFFSET];
+	uint8_t payload_length = 0;
+		
+	uint8_t answer_buffer[255];
+	uint8_t answer_length = 0;
+	uint8_t max_answer_length = 0;
+	
+	
+	//Now about interpreting length values...
+	if (t1_header->message_length < sizeof(ISO7816_APDU_Header)){
+		status = ISO7816_STATUS_ERR_WRONG_LENGTH;
+	} else if (t1_header->message_length == sizeof(ISO7816_APDU_Header)){
+		//no APDU payload, no answer payload.
+		payload_length = 0;
+		max_answer_length = 0;
+	} else if (t1_header->message_length == sizeof(ISO7816_APDU_Header) + 1){
+		//no APDU payload, but answer payload allowed.
+		payload_length = 0;
+		max_answer_length = APDU_PAYLOAD_LENGTH(message_buffer);
+	} else { //we have APDU payload
+		payload_length = APDU_PAYLOAD_LENGTH(message_buffer);
+		if (t1_header->message_length - sizeof(ISO7816_APDU_Header) - 1 == payload_length){
+			//APDU Header + APDU Payload, no answer payload
+			max_answer_length = 0;
+		} else if (t1_header->message_length - sizeof(ISO7816_APDU_Header) - 1 == (payload_length + 1)) {
+			//APDU Header + APDU Payload + answer payload
+			max_answer_length = message_buffer[t1_header->message_length - 1];
+		} else {
+			status = ISO7816_STATUS_ERR_WRONG_LENGTH;
+		}
+	}
+	
+	
+	if (status == ISO7816_STATUS_OK){
+		answer_length = max_answer_length;
+		status = handler(apdu_header, payload, payload_length, answer_buffer, &answer_length);
+		if (answer_length > max_answer_length){
+			status = ISO7816_STATUS_ERR_WRONG_LENGTH;
+		}
+	}
+	if (status != ISO7816_STATUS_OK) answer_length = 0;
+	
+	t1_header->node_address = 0;
+	t1_header->message_length = answer_length+2;
+	
+	memcpy(message_buffer, answer_buffer, answer_length);
+	message_buffer[answer_length]   = status >> 8;
+	message_buffer[answer_length+1] = status & 0xFF;
+}
+
+uint8_t ISO7816_process(void){
+	uint16_t ret;
+	
+	ISO7816_T1_Header t1_header;
+	
+	uint8_t ok;
+	uint8_t checksum = 0;
+	
+	uint8_t buffer[255];
+	
+	ok = ISO7816_read_t1_header(&t1_header, &checksum);                 //T1 Protocol header
+	if (!ok) return 0;
+	
+	ret = ISO7816_receive_buffer(buffer, t1_header.message_length); //Message Body (e.g. APDU)
+	if (ret == UART_ERR_TIMEOUT) return 0;
+	checksum ^= ret & 0xFF;
+	
+	ok = ok && ISO7816_read_t1_trailer(checksum); //T1 Protocol trailer (checksum)
+	
+	//------------ Process message ------------
+	if (ok){
+		if (t1_header.protocol_control == ISO7816_PCB_IFS_REQUEST){
+			t1_header.protocol_control = ISO7816_PCB_IFS_RESPONSE;
+			t1_header.node_address = 0;
+			
+		} else if (ISO7816_PCM_IS_I_BLOCK(t1_header.protocol_control)){
+			ISO7816_process_apdu(&t1_header, buffer);
+		} else {
+			ok = 0;
+		}
+	}
+	
+// 	PORTB |= (1 << 7);
+	
+	if (!ok) return 0;
+	
+	//------------ Send Answer ------------
+	_delay_us(200);
+	PORTB &= ~(1 << 7);
+	
+	UART_transmit_init();
+	_delay_us(200);
+	
+	checksum = 0;
+	checksum ^= ISO7816_transmit_t1_header(&t1_header);                    //Header
+	checksum ^= ISO7816_transmit_buffer(buffer, t1_header.message_length); //Payload
+	UART_transmit_char(checksum);                                          //Checksum
+	
+	UART_recv_init();  //switch back to receive mode.
+	
+	return ok;
+}
+
+uint8_t ISO7816_transmit_t1_header(ISO7816_T1_Header* t1_header){
+	//Node Address TODO: WTF is that? do i need to care?
+	uint8_t checksum = t1_header->node_address;
+	UART_transmit_char(t1_header->node_address);
+	
+	//Protocol control byte
+	checksum ^= t1_header->protocol_control; //seq_number ? 0x40 : 0x00;;
+	UART_transmit_char(t1_header->protocol_control);
+	
+	//Answer length (answer payload + 2 byte Status)
+// 	t1_header.message_length = answer_length + 2;
+	checksum ^= t1_header->message_length;
+	UART_transmit_char(t1_header->message_length);
+	
+	return checksum;
+}
+
+uint8_t ISO7816_transmit_buffer(uint8_t* buffer, uint8_t length){
+	uint8_t checksum = 0;
+	
+	for (uint8_t i = 0; i < length; i++){
+		UART_transmit_char(buffer[i]);
+		checksum ^= buffer[i];
+	}
+	return checksum;
+}
+
+uint16_t ISO7816_receive_buffer(uint8_t* buffer, uint8_t length){
+	uint8_t c;
+	uint8_t checksum = 0;
+	uint16_t ret;
+	
+	for (uint8_t i = 0; i < length; i++){
+		ret = UART_receive_char_timeout(ISO7816_APDU_READ_TIMEOUT);
+		if (ret == UART_ERR_TIMEOUT) return ISO7816_ERR_TIMEOUT;
+		c = ret & 0xFF;
+		checksum ^= c;
+		if (buffer) buffer[i] = c;
+	}
+	return checksum;
+}
+
+void ISO7816_set_apdu_handler(apdu_handler_t h){
+	handler = h;
+}
\ No newline at end of file
diff --git a/ATMegaCard/ISO7816-card.h b/ATMegaCard/ISO7816-card.h
new file mode 100644
index 0000000000000000000000000000000000000000..9728a1370a57b9c2ca9b9be61d0b31398a5285b8
--- /dev/null
+++ b/ATMegaCard/ISO7816-card.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "software_serial.h"
+#include "../common/ISO7816-common.h"
+
+#define ISO7816_APDU_READ_TIMEOUT 3000 //300ms
+#define ISO7816_ERR_TIMEOUT 0xFFFF
+
+#define ISO7816_STATUS_OK                                0x9000
+#define ISO7816_STATUS_ERR_INCORRECT_P1P2                0x6A86
+#define ISO7816_STATUS_ERR_WRONG_P1P2                    0x6B00
+#define ISO7816_STATUS_ERR_CORRECT_LENGTH_00             0x6C00
+#define ISO7816_STATUS_ERR_INS_NOT_SUPPORTED             0x6D00
+#define ISO7816_STATUS_ERR_CLA_NOT_SUPPORTED             0x6E00
+#define ISO7816_STATUS_ERR_BYTES_REMAINING_00            0x6100
+#define ISO7816_STATUS_ERR_WRONG_LENGTH                  0x6700
+#define ISO7816_STATUS_ERR_SECURITY_STATUS_NOT_SATISFIED 0x6982
+#define ISO7816_STATUS_ERR_FILE_INVALID                  0x6983
+#define ISO7816_STATUS_ERR_DATA_INVALID                  0x6984
+#define ISO7816_STATUS_ERR_CONDITIONS_NOT_SATISFIED      0x6985
+#define ISO7816_STATUS_ERR_COMMAND_NOT_ALLOWED           0x6986
+#define ISO7816_STATUS_ERR_WRONG_DATA                    0x6A80
+#define ISO7816_STATUS_ERR_FUNC_NOT_SUPPORTED            0x6A81
+#define ISO7816_STATUS_ERR_FILE_NOT_FOUND                0x6A82
+#define ISO7816_STATUS_ERR_RECORD_NOT_FOUND              0x6A83
+#define ISO7816_STATUS_ERR_APPLET_SELECT_FAILED          0x6999
+#define ISO7816_STATUS_ERR_UNKNOWN                       0x6F00
+
+struct ISO7816_T1_Header{
+	uint8_t node_address;
+	uint8_t protocol_control;
+	uint8_t message_length;
+} typedef ISO7816_T1_Header;
+
+#define ISO7816_PCM_IS_I_BLOCK(pcb) (((pcb) & 0x80) == 0)
+#define ISO7816_PCB_IFS_REQUEST 0xC1
+#define ISO7816_PCB_IFS_RESPONSE 0xE1
+
+#define MIN(a,b) (((a) < (b)) : (a) : (b))
+
+//uint16_t ISO7816_handle_adpu(ISO7816_APDU_Header* header, uint8_t* payload, uint8_t payload_length, uint8_t* answer_buffer, uint8_t* answer_length);
+
+typedef uint16_t(*apdu_handler_t)(ISO7816_APDU_Header*, uint8_t*, uint8_t, uint8_t*, uint8_t*);
+
+void ISO7816_init(void);
+void ISO7816_sendATR(void);
+uint8_t ISO7816_data_available(void);
+uint8_t ISO7816_process(void);
+void ISO7816_set_apdu_handler(apdu_handler_t handler);
+
+
diff --git a/ATMegaCard/Makefile b/ATMegaCard/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cb0f90049378c8d8999afceb40a7ca7e8439b566
--- /dev/null
+++ b/ATMegaCard/Makefile
@@ -0,0 +1,398 @@
+# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+# Additional material for this makefile was submitted by:
+#  Tim Henigan
+#  Peter Fleury
+#  Reiner Patommel
+#  Sander Pool
+#  Frederik Rouleau
+#  Markus Pfaff
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
+#
+# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
+#                4.07 or greater).
+#
+# make program = Download the hex file to the device, using avrdude.  Please
+#                customize the avrdude settings below first!
+#
+# make filename.s = Just compile filename.c into the assembler code only
+#
+# To rebuild project do "make clean" then "make all".
+#
+
+# MCU name
+
+MCU = atmega163
+
+
+
+#Fuse settings for ATmega163
+ifeq ($(MCU), atmega163)
+	FUSE_BITS = -u -U lfuse:w:0x81:m -U hfuse:w:0x01:m 
+	HEX_FILE_NAME = MEGA163
+endif
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Target file name (without extension).
+TARGET = out/atmegacard_$(HEX_FILE_NAME)
+
+# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# If there is more than one source file, append them above, or modify and
+# uncomment the following:
+
+SRC = main.c software_serial.c ISO7816-card.c keystore.c rng.c ../common/sha1/sha1.c applications/portal/portal.c
+
+# List Assembler source files here.
+# Make them always end in a capital .S.  Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC = 
+
+
+# List any extra directories to look for include files here.
+#     Each directory must be seperated by a space.
+EXTRAINCDIRS = 
+
+
+# Optional compiler flags.
+#  -g:        generate debugging information (for GDB, or for COFF conversion)
+#  -O*:       optimization level
+#  -f...:     tuning, see gcc manual and avr-libc documentation
+#  -Wall...:  warning level
+#  -Wa,...:   tell GCC to pass this to the assembler.
+#    -ahlms:  create assembler listing
+CFLAGS = -g -O$(OPT) \
+-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
+-Wall -Wstrict-prototypes \
+-Wa,-adhlns=$(<:.c=.lst) \
+$(patsubst %,-I%,$(EXTRAINCDIRS))
+
+
+# Set a "language standard" compiler flag.
+#   Unremark just one line below to set the language standard to use.
+#   gnu99 = C99 + GNU extensions. See GCC manual for more information.
+#CFLAGS += -std=c89
+#CFLAGS += -std=gnu89
+#CFLAGS += -std=c99
+CFLAGS += -std=gnu99
+
+
+
+# Optional assembler flags.
+#  -Wa,...:   tell GCC to pass this to the assembler.
+#  -ahlms:    create listing
+#  -gstabs:   have the assembler create line number information; note that
+#             for use in COFF files, additional information about filenames
+#             and function names needs to be present in the assembler source
+#             files -- see avr-libc docs [FIXME: not yet described there]
+ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 
+
+
+
+# Optional linker flags.
+#  -Wl,...:   tell GCC to pass this to linker.
+#  -Map:      create map file
+#  --cref:    add cross reference to  map file
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+
+
+
+# Additional libraries
+
+# Minimalistic printf version
+#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires -lm below)
+#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
+
+# -lm = math library
+LDFLAGS += -lm
+
+
+
+
+# Programming support using avrdude. Settings and variables.
+
+# Programming hardware: alf avr910 avrisp bascom bsd 
+# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
+#
+# Type: avrdude -c ?
+# to get a full listing.
+#
+
+#AVRDUDE_PROGRAMMER = AVR910
+AVRDUDE_PROGRAMMER = usbtiny
+# AVRDUDE_PROGRAMMER = USBasp
+
+AVRDUDE_PORT = usb        # programmer connected to USB port
+#AVRDUDE_PORT = com1	   # programmer connected to serial device
+#AVRDUDE_PORT = lpt1	       # programmer connected to parallel port
+
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex $(FUSE_BITS)
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -b 115200 -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS = -B 1 -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE += -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_FLAGS += -V
+
+# Increase verbosity level.  Please use this when submitting bug
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
+# to submit bug reports.
+#AVRDUDE_FLAGS += -v -v
+
+
+
+
+# ---------------------------------------------------------------------------
+
+# Define programs and commands.
+SHELL = sh
+
+CC = avr-gcc
+
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+
+
+# Programming support using avrdude.
+AVRDUDE = avrdude
+
+
+REMOVE = rm -f
+COPY = cp
+
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = --------  end  --------
+MSG_SIZE_BEFORE = Size before: 
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+
+
+
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) 
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+
+# Default target.
+all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
+	$(TARGET).lss $(TARGET).sym sizeafter finished end
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+	@echo
+	@echo $(MSG_BEGIN)
+
+finished:
+	@echo $(MSG_ERRORS_NONE)
+
+end:
+	@echo $(MSG_END)
+	@echo
+
+
+# Display size of file.
+sizebefore:
+	@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+	@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+
+# Display compiler version information.
+gccversion : 
+	@$(CC) --version
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in
+# AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+	--change-section-address .data-0x800000 \
+	--change-section-address .bss-0x800000 \
+	--change-section-address .noinit-0x800000 \
+	--change-section-address .eeprom-0x810000 
+
+
+coff: $(TARGET).elf
+	@echo
+	@echo $(MSG_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	@echo
+	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+
+# Program the device.  
+program: $(TARGET).hex $(TARGET).eep
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+	@echo
+	@echo $(MSG_FLASH) $@
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+	@echo
+	@echo $(MSG_EEPROM) $@
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+	--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+	@echo
+	@echo $(MSG_EXTENDED_LISTING) $@
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+	@echo
+	@echo $(MSG_SYMBOL_TABLE) $@
+	avr-nm -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+	@echo
+	@echo $(MSG_LINKING) $@
+	$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+%.o : %.c
+	@echo
+	@echo $(MSG_COMPILING) $<
+	$(CC) -c $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+%.o : %.S
+	@echo
+	@echo $(MSG_ASSEMBLING) $<
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+clean_list :
+	@echo
+	@echo $(MSG_CLEANING)
+#	$(REMOVE) $(TARGET).hex
+	$(REMOVE) $(TARGET).eep
+	$(REMOVE) $(TARGET).obj
+	$(REMOVE) $(TARGET).cof
+	$(REMOVE) $(TARGET).elf
+	$(REMOVE) $(TARGET).map
+	$(REMOVE) $(TARGET).obj
+	$(REMOVE) $(TARGET).a90
+	$(REMOVE) $(TARGET).sym
+	$(REMOVE) $(TARGET).lnk
+	$(REMOVE) $(TARGET).lss
+	$(REMOVE) $(OBJ)
+	$(REMOVE) $(LST)
+	$(REMOVE) $(SRC:.c=.s)
+	$(REMOVE) $(SRC:.c=.d)
+
+
+# Automatically generate C source code dependencies. 
+# (Code originally taken from the GNU make user manual and modified 
+# (See README.txt Credits).)
+#
+# Note that this will work with sh (bash) and sed that is shipped with WinAVR
+# (see the SHELL variable defined above).
+# This may not work with other shells or other seds.
+#
+%.d: %.c
+	set -e; $(CC) -MM $(ALL_CFLAGS) $< \
+	| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
+	[ -s $@ ] || rm -f $@
+
+
+# Remove the '-' if you want to see the dependency files generated.
+-include $(SRC:.c=.d)
+
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
+	clean clean_list program
+
diff --git a/ATMegaCard/applications/applications.h b/ATMegaCard/applications/applications.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0bd87c979c21439a79d345ca86b3912abb07ad6
--- /dev/null
+++ b/ATMegaCard/applications/applications.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "../ISO7816-card.h"
+
+typedef uint8_t application_id_t[5];
+
+struct application_t{
+	application_id_t aid;
+	void (*init)(void);
+	apdu_handler_t (*select)(void);
+	void (*deselect)(void);
+} typedef application_t;
+
+
+/* ****** Place application defined here ****** */
+
+#include "portal/portal.h"
+#define NUM_APPLICATIONS 1
+#define APPLICATIONS {APP_PORTAL}
+
+void portal_init(void);
+apdu_handler_t portal_select(void);
+void portal_deselect(void);
+
diff --git a/ATMegaCard/applications/portal/portal.c b/ATMegaCard/applications/portal/portal.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e1ed6af6c1e02729fa22d6f3ec40a96033d257a
--- /dev/null
+++ b/ATMegaCard/applications/portal/portal.c
@@ -0,0 +1,126 @@
+#include <string.h>
+#include "portal.h"
+#include "../../ISO7816-card.h"
+#include "keystore.h"
+#include "../../rng.h"
+
+#define PORTAL_INS_QUERY_VERSION 0x00
+#define PORTAL_INS_INIT_KEY      0x01
+#define PORTAL_INS_AUTH          0x02
+#define PORTAL_INS_UPDATE_KEY    0x03
+
+uint16_t portal_handle_adpu(ISO7816_APDU_Header* header,
+							 uint8_t* payload,
+							 uint8_t payload_length,
+							 uint8_t* answer_buffer,
+							 uint8_t* answer_length);
+
+sha1_ctx_t sha1_state;
+uint8_t challenge[sizeof(SALT)];
+uint8_t current_auth_key = 1;
+
+void portal_init(void){
+	rnd_get_bytes(challenge, sizeof(SALT));
+}
+
+apdu_handler_t portal_select(void){
+	return portal_handle_adpu;
+}
+
+uint16_t portal_handle_adpu(ISO7816_APDU_Header* header,
+							 uint8_t* payload,
+							 uint8_t payload_length,
+							 uint8_t* answer_buffer,
+							 uint8_t* answer_length){
+	
+	switch (header->instruction){
+		case PORTAL_INS_QUERY_VERSION:
+			if (*answer_length < 1) return ISO7816_STATUS_ERR_WRONG_LENGTH;
+			
+			*answer_length = 1;
+			answer_buffer[0] = 2;
+			return ISO7816_STATUS_OK;
+			break;
+			
+			
+		case PORTAL_INS_INIT_KEY:
+			if (payload_length != sizeof(KEY)) return ISO7816_STATUS_ERR_WRONG_LENGTH + payload_length+1;
+			
+			*answer_length = 0;
+			if (keystore_is_empty()){
+				keystore_init_key(payload);
+				return ISO7816_STATUS_OK;
+			} else {
+				return ISO7816_STATUS_ERR_CONDITIONS_NOT_SATISFIED;
+			}
+			break;
+			
+			
+		case PORTAL_INS_AUTH:
+			if (*answer_length < sizeof(HASH) + sizeof(SALT)) return ISO7816_STATUS_ERR_WRONG_LENGTH;
+			if (payload_length != sizeof(SALT)) return ISO7816_STATUS_ERR_WRONG_LENGTH;
+			
+			current_auth_key = !current_auth_key;
+			*answer_length = sizeof(HASH) + sizeof(SALT);
+			sha1_init(&sha1_state);
+			sha1_nextBlock(&sha1_state, keystore_get_key(current_auth_key));
+			sha1_lastBlock(&sha1_state, payload, sizeof(SALT)*8);
+			sha1_ctx2hash(answer_buffer, &sha1_state);
+			memcpy(answer_buffer + sizeof(HASH), challenge, sizeof(SALT));
+			
+			return ISO7816_STATUS_OK;
+			break;
+			
+			
+		case PORTAL_INS_UPDATE_KEY:
+			if (payload_length != sizeof(KEY)+ sizeof(HASH)) return ISO7816_STATUS_ERR_WRONG_LENGTH;
+			*answer_length = 0;
+			
+			uint8_t* new_key_delta = payload;
+			uint8_t* challange_response = payload + sizeof(KEY);
+			
+			sha1_init(&sha1_state);
+			sha1_nextBlock(&sha1_state, keystore_get_key(current_auth_key));
+			sha1_lastBlock(&sha1_state, challenge, sizeof(SALT)*8);
+			if (! sha1_ctx_hash_compare(challange_response, &sha1_state)){
+				return ISO7816_STATUS_ERR_SECURITY_STATUS_NOT_SATISFIED;
+// 				*answer_length = 20;
+// 				memcpy(answer_buffer, (const void*)challange_response, 20);
+// 				return ISO7816_STATUS_OK;
+			}
+			
+			
+			keystore_update_key(new_key_delta, current_auth_key);
+			
+			return ISO7816_STATUS_OK;
+			break;
+			
+			
+		case 0xFE:
+			if (*answer_length < sizeof(KEY)) return ISO7816_STATUS_ERR_WRONG_LENGTH;
+			
+			memset(answer_buffer, 0xBB, sizeof(KEY));
+			memcpy(answer_buffer, keystore_get_key(0), sizeof(KEY));
+			if (*answer_length < 2*sizeof(KEY)){
+				*answer_length = sizeof(KEY);
+			} else {
+				memcpy(answer_buffer + sizeof(KEY), keystore_get_key(1), sizeof(KEY));
+				*answer_length = 2*sizeof(KEY);
+			}
+			return ISO7816_STATUS_OK;
+			break;
+			
+			
+		case 0xFF:
+			*answer_length = 0;
+			keystore_clear();
+			
+			return ISO7816_STATUS_OK;
+			break;
+	}
+	return ISO7816_STATUS_ERR_INS_NOT_SUPPORTED;
+}
+
+void portal_deselect(void){
+	
+}
diff --git a/ATMegaCard/applications/portal/portal.h b/ATMegaCard/applications/portal/portal.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a8f57416491f23e97e6429da02699cc6ff498f4
--- /dev/null
+++ b/ATMegaCard/applications/portal/portal.h
@@ -0,0 +1,7 @@
+#include "../applications.h"
+
+void portal_init(void);
+apdu_handler_t portal_select(void);
+void portal_deselect(void);
+
+#define APP_PORTAL {"\x23\x23\x00\x42\x42", portal_init, portal_select, portal_deselect}
\ No newline at end of file
diff --git a/ATMegaCard/common.h b/ATMegaCard/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c7f2176f8ddc22aaf14b6dcc314ec79d6607f7a
--- /dev/null
+++ b/ATMegaCard/common.h
@@ -0,0 +1 @@
+#define F_CPU 3579500
\ No newline at end of file
diff --git a/ATMegaCard/keystore.c b/ATMegaCard/keystore.c
new file mode 100644
index 0000000000000000000000000000000000000000..b23e9e3529fb5e80bdb8fa9afc4dca46bd3b1df7
--- /dev/null
+++ b/ATMegaCard/keystore.c
@@ -0,0 +1,77 @@
+/**
+ * This Keystore manages two keyslots, a "primary" and a "secondary" slot
+ * The key locations (0 and 1) are at EEPROM location EEP_KEY_OFFSET and EEP_KEY_OFFSET+sizeof(KEY)
+ * The value at EEP_PRIMARY_KEY_SLOT declares which keyslot (0 or 1) ist the "primary" slot.
+ * The remaining one is the "secondary"
+ * 
+ * If the "primary" key is requested, the value at EEP_PRIMARY_KEY_SLOT is looked up and the key is read from the indicated location
+ * If the "secondary" key is requested the key is read from the alternate location.
+ * 
+ * When the "primary" key is updated (parameter "update_secondary" = false) the "secondary" keyslot is overwritten
+ * with the new key and then declared as "primary" by flipping the value stored at EEP_PRIMARY_KEY_SLOT.
+ * This procedure ensures that there is always one valid key in the store.
+ * 
+ * When the "secondary" key is updated (parameter "update_secondary" = false) the "primary" keyslot is overwritten
+ * with the new key. The value at EEP_PRIMARY_KEY_SLOT stays unchanged, declaring the new key as "primary".
+ * The old secondary key stays at place.
+ * This procedure ensures that there is always one valid key in the store.
+ */
+
+#include "keystore.h"
+
+
+#define EEP_PRIMARY_KEY_SLOT 127
+#define EEP_KEY_OFFSET 128
+
+static uint8_t get_keyslot_index(uint8_t secondary);
+static void write_new_primary_key(uint8_t* key, uint8_t slotindex);
+void xor(uint8_t* src1dst, uint8_t* src2, uint8_t length);
+
+uint8_t keybuffer[sizeof(KEY)];
+
+uint8_t keystore_is_empty(void){
+	return (eeprom_read_byte((const uint8_t*)EEP_PRIMARY_KEY_SLOT) == 0xFF);
+}
+uint8_t* keystore_get_key(int8_t secondary){
+	uint8_t slotindex = get_keyslot_index(secondary);
+	
+	eeprom_read_block(keybuffer, (const void*)EEP_KEY_OFFSET + (slotindex*sizeof(KEY)), sizeof(KEY));
+	return keybuffer;
+}
+
+void keystore_init_key(uint8_t* key){
+	uint8_t slotindex = get_keyslot_index(0);
+	write_new_primary_key(key, slotindex);
+}
+
+void keystore_update_key(uint8_t* new_key_delta, uint8_t update_secondary){
+	uint8_t read_slotindex = get_keyslot_index(update_secondary); //read from the valid slot
+	
+	eeprom_read_block(keybuffer, (const void*)EEP_KEY_OFFSET + (read_slotindex*sizeof(KEY)), sizeof(KEY));
+	xor(keybuffer, new_key_delta, sizeof(KEY));
+	
+	uint8_t write_slotindex = get_keyslot_index(!update_secondary); //write to the invalid slot
+	write_new_primary_key(keybuffer, write_slotindex);
+}
+
+void keystore_clear(void){
+	for (uint8_t i = 0; i < sizeof(KEY)*2; i++){
+		eeprom_write_byte((uint8_t*)(EEP_KEY_OFFSET+i), 0xFF);
+	}
+	eeprom_write_byte((uint8_t*)EEP_PRIMARY_KEY_SLOT, 0xFF);
+}
+
+static uint8_t get_keyslot_index(uint8_t secondary){
+	uint8_t primary_slot = eeprom_read_byte((const uint8_t*)EEP_PRIMARY_KEY_SLOT);
+	if (primary_slot > 1) primary_slot = 0;
+	return secondary ? !primary_slot : primary_slot;
+}
+static void write_new_primary_key(uint8_t* key, uint8_t slotindex){
+	eeprom_write_block(key, (void*)EEP_KEY_OFFSET + (slotindex*sizeof(KEY)) , sizeof(KEY));
+	eeprom_write_byte((uint8_t*)EEP_PRIMARY_KEY_SLOT, slotindex);
+}
+void xor(uint8_t* src1dst, uint8_t* src2, uint8_t length){
+	for (uint8_t i = 0; i < length; i++){
+		src1dst[i] ^= src2[i];
+	}
+}
diff --git a/ATMegaCard/keystore.h b/ATMegaCard/keystore.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b52a7e617e9b8593938cfa79b36b5336016b697
--- /dev/null
+++ b/ATMegaCard/keystore.h
@@ -0,0 +1,31 @@
+#include <avr/eeprom.h>
+#include "../common/card_common.h"
+
+/**
+ * Returns non-zero result if the keystore is empty.
+ * Returns zero if at least one key has been stored.
+ */
+uint8_t keystore_is_empty(void);
+
+/**
+ * Initializes the "primary" key of the keystore
+ */
+void keystore_init_key(uint8_t* key);
+
+/**
+ * Loads a key to the keybuffer and returns the pointer to it. The pointer is valid until the next call to a keystore_ method.
+ * @param secondary  0 - load the primary key, 1 - load the secondary key
+ */
+uint8_t* keystore_get_key(int8_t secondary);
+
+/**
+ * Update a key with the given key_delta. 
+ * @param new_key_delta bitwise XOR between the old key and the given key_delta is performed and the result is stored.
+ * @param update_secondary 0 - update the primary key (and mark it as primary) 1 - update the secondary key (and mark it as primary)
+ */
+void keystore_update_key(uint8_t* new_key_delta, uint8_t update_secondary);
+
+/**
+ * Delete all keys from the keystore
+ */
+void keystore_clear(void);
\ No newline at end of file
diff --git a/ATMegaCard/main.c b/ATMegaCard/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..270701fc18c12999f93e699992481e7e1494f143
--- /dev/null
+++ b/ATMegaCard/main.c
@@ -0,0 +1,77 @@
+#include "common.h"
+#include <avr/io.h>
+#include <util/delay.h>
+#include <string.h>
+#include "rng.h"
+
+#include "ISO7816-card.h"
+#include "applications/applications.h"
+
+#define INS_APPLICATION_MANAGER 0xA4
+#define APPLICATION_MANAGER_P1_SELECT 0x04
+
+application_t applications[NUM_APPLICATIONS] = APPLICATIONS;
+
+uint16_t main_handle_adpu(ISO7816_APDU_Header* header,
+						  uint8_t* payload,
+						  uint8_t payload_length,
+						  uint8_t* answer_buffer,
+						  uint8_t* answer_length);
+
+uint8_t current_application = 0xFF;
+
+int main(void){
+	//DDRB = (1 << 5) | (1 << 7);
+// 	ISO7816_init();
+	ISO7816_set_apdu_handler(main_handle_adpu);
+	ISO7816_sendATR();
+	sei();
+	rnd_init();
+	
+	
+	for (uint8_t i = 0; i < NUM_APPLICATIONS; i++){
+		applications[i].init();
+	}
+	
+	while(1){
+		if (ISO7816_data_available()){
+			ISO7816_process();
+		}
+	}
+}
+
+uint16_t main_handle_adpu(ISO7816_APDU_Header* header,
+						  uint8_t* payload,
+						  uint8_t payload_length,
+						  uint8_t* answer_buffer,
+						  uint8_t* answer_length){
+	
+	*answer_length = 0;
+	
+	
+	if (header->instruction == INS_APPLICATION_MANAGER){
+		
+		if (header->param1 == APPLICATION_MANAGER_P1_SELECT){
+			for (uint8_t i = 0; i < NUM_APPLICATIONS; i++){
+				if (memcmp(applications[i].aid, payload, sizeof(application_id_t)) == 0){
+					if (current_application != 0xFF) applications[current_application].deselect();
+					ISO7816_set_apdu_handler(applications[i].select());
+					return APDU_RESULT_OK;
+				}
+			}
+			return ISO7816_STATUS_ERR_FILE_NOT_FOUND;
+		} else {
+			return ISO7816_STATUS_ERR_WRONG_P1P2;
+		}
+	} else if (header->instruction == 0x11){
+		for (uint8_t i = 0; i < 32; i++){
+			answer_buffer[i] = rnd_get_byte();
+		}
+		*answer_length = 32;
+		return APDU_RESULT_OK;
+		
+	} else {
+		return ISO7816_STATUS_ERR_INS_NOT_SUPPORTED;
+	}
+	
+}
\ No newline at end of file
diff --git a/ATMegaCard/rnd b/ATMegaCard/rnd
new file mode 100644
index 0000000000000000000000000000000000000000..d36f2af328a4c177221926377bd8c3d53dd2880d
Binary files /dev/null and b/ATMegaCard/rnd differ
diff --git a/ATMegaCard/rng.c b/ATMegaCard/rng.c
new file mode 100644
index 0000000000000000000000000000000000000000..de843640f2286f66443b996d69cb7c1f205ccfea
--- /dev/null
+++ b/ATMegaCard/rng.c
@@ -0,0 +1,45 @@
+#include <avr/io.h>
+#include <util/crc16.h>
+
+#define ADC_RNG_CHANNEL 0
+
+uint16_t seed;
+
+uint8_t rnd_adc_read(void);
+
+void rnd_init(void){
+	seed = 0xFFFF;
+	seed = _crc16_update(seed, rnd_adc_read());
+	seed = _crc16_update(seed, rnd_adc_read());
+}
+
+uint8_t rnd_adc_read(void){
+	uint8_t result = 0;
+	
+	ADMUX = ADC_RNG_CHANNEL | (1 << REFS0); // Select channel,  AVCC Reference voltage.
+	
+	ADCSR = (1<<ADEN) | (1 << ADPS1); // Enable ADC (Prescaler 4)
+	
+// 	for (uint8_t i = 0; i < 8; i++){
+	ADCSR |= (1<<ADSC);
+	while (ADCSR & (1<<ADSC)) {;}
+// 		
+// 		result = (ADCL & 1) << i;
+// 		ADCH;         
+// 	}
+	result = ADCL;
+	ADCH;
+	
+	return result;
+}
+
+uint8_t rnd_get_byte(void){
+	seed = _crc16_update(seed, rnd_adc_read());
+	return ((seed & 0xFF) ^ (seed >> 8));
+}
+
+void rnd_get_bytes(uint8_t* buffer, uint8_t length){
+	for (uint8_t i = 0; i < length; i++){
+		buffer[i] = rnd_get_byte();
+	}
+}
\ No newline at end of file
diff --git a/ATMegaCard/rng.h b/ATMegaCard/rng.h
new file mode 100644
index 0000000000000000000000000000000000000000..c309ffe529b6e9f65eab38640d80669cd06237bd
--- /dev/null
+++ b/ATMegaCard/rng.h
@@ -0,0 +1,3 @@
+void rnd_init(void);
+uint8_t rnd_get_byte(void);
+void rnd_get_bytes(uint8_t* buffer, uint8_t length);
\ No newline at end of file
diff --git a/ATMegaCard/software_serial.c b/ATMegaCard/software_serial.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd9fb3946118f7ad442fc8d63f10c6f7c4a5fc23
--- /dev/null
+++ b/ATMegaCard/software_serial.c
@@ -0,0 +1,221 @@
+#include "software_serial.h"
+
+#ifdef UART_USE_AS_STDOUT //Sets up the serial port as a stream for stdout. With this printf and stuff will write to the serial port.
+	#include <stdio.h>
+	
+	void UART_transmit_stdout(char c, FILE* stream){
+		UART_transmit_char((unsigned char)c);
+	}
+
+    static FILE UART_stdout = FDEV_SETUP_STREAM(UART_transmit_stdout, NULL, _FDEV_SETUP_WRITE);
+#endif
+
+
+/**
+ * Initializes the Software UART
+ */
+void UART_init(void){
+	#ifdef UART_USE_AS_STDOUT
+		stdout = &UART_stdout; //assign serial output stream as stdout.
+	#endif
+	
+	UART_recv_init();
+}
+
+/**
+ * Switches the UART to transmit mode
+ */
+void UART_transmit_init(void){
+	cli(); //interrupts disable (messes up send timings otherwise)
+	SWSERIAL_PORT |= (1 << SWSERIAL_LINE); //data line to high level (otherwise we might trigger a start bit)
+	SWSERIAL_PORT_DR |= (1 << SWSERIAL_LINE); //output
+}
+
+/**
+ * Sends a 0-terminated string
+ * Note: The caller must to switch to transmit mode before calling this
+ */
+void UART_transmit_buffer_sz(char* buffer){
+	while (buffer[0] != 0){
+		UART_transmit_char(buffer[0]);
+		buffer++;
+	}
+}
+
+/**
+ * Sends a byte coverted to hex digits
+ * Note: The caller must to switch to transmit mode before calling this
+ */
+void UART_transmit_byte_hex(unsigned char b){
+
+	unsigned char n;
+	n = '0' + (b >> 4 & 0xF);
+	UART_transmit_char((n > '9') ? n + 7 : n);
+	n = '0' + (b & 0xF);
+	UART_transmit_char((n > '9') ? n + 7 : n);
+}
+
+
+/**
+ * Writes a single character to the data line, bit-by-bit
+ * Note: The caller must to switch to transmit mode before calling this
+ */
+void UART_transmit_char(unsigned char x){
+
+	_delay_us(BIT_LENGTH); //guard time beween bytes
+	
+	WRITE(0); //start bit
+	
+	#if SWSERIAL_PARITY == EVEN
+		uint8_t parity = 0;
+	#endif
+	#if SWSERIAL_PARITY == ODD
+		uint8_t parity = 1;
+	#endif
+	for (unsigned char i = 0; i < 8; i++){
+		_delay_us(BIT_LENGTH - INST_LENGTH(8));
+		WRITE(x & 1);
+		#if SWSERIAL_PARITY != NONE
+			parity ^= x & 1;
+		#endif
+		x >>= 1;
+	}
+	
+	#if (SWSERIAL_PARITY != NONE)
+		_delay_us(BIT_LENGTH - INST_LENGTH(8));
+		WRITE(parity);		
+	#endif
+	
+	_delay_us(BIT_LENGTH - INST_LENGTH(8));
+	WRITE(1); //stop bit
+	
+	#if SWSERIAL_STOPBITS == 2
+	_delay_us(BIT_LENGTH - INST_LENGTH(8));
+	WRITE(1); //stop bit 2
+	#endif
+	
+	_delay_us(BIT_LENGTH); //guard time beween bytes
+	_delay_us(BIT_LENGTH); //guard time beween bytes
+}
+
+
+//------------------------- Receive code ----------------------------
+
+uint8_t recv_buffer1 = 0;          //Byte currently beeing received (only used by timer interrupt handler)
+uint8_t recv_bits = 0;             //Number of bits done in current receive (only used by timer interrupt handler)
+volatile uint8_t recv_buffer2 = 0; //Last Byte that finished receiving
+volatile uint8_t recv_avail = 0;   //Is a byte ready to be processed?
+volatile uint8_t recv_parity;
+volatile uint8_t recv_valid = 0;    //Did we receive 1 for the stop bits and valid parity
+
+/**
+ * Switch UART into receive mode
+ */
+void UART_recv_init(void){
+	SWSERIAL_PORT_DR &= ~(1 << SWSERIAL_LINE); //set Serial pin to input
+	SWSERIAL_PORT |= (1 << SWSERIAL_LINE); //pullup
+	
+	DDRB |= (1 << 5) | (1 << 7);
+	
+	TIFR = (1 << ICF1); //clear old interrupt flag.
+	TIMSK = 1 << TICIE1; //enable ICP interrupt, disable timer compare interrupt
+	TCCR1B =  (1 << CS10)   //Timer prescaler = 1
+// #ifdef CTC1
+			| (1 << CTC1)   //Clear timer on compare match (important for exact timing, don't do it in software)
+// #else
+// 			| (1 << WGM12)
+// #endif
+			| (1 << ICNC1) //Capture interrupt noise canceler enable (filters out very short spikes  < 4 clks)
+// #ifdef ICES1
+// 			| (1 << ICES1)
+// #endif
+			;
+	
+	OCR1A  = 372; //Default smartcard conversion factor 3571200Hz/372(clks/bit) = 9600bit/s
+	
+	sei(); //global interrupt enable
+}
+
+/**
+ * Is a byte available to be processed?
+ */
+inline uint8_t UART_data_available(void){
+	return recv_avail != 0;
+}
+/**
+ * Reads the last byte that was received.
+ * Resets the availability flag.
+ */
+uint8_t UART_read_char(void){
+	recv_avail = 0;
+	return recv_buffer2;
+}
+
+uint16_t UART_receive_char_timeout(uint16_t timeout){
+	while ((timeout > 0) && (recv_avail == 0)) {_delay_us(100); timeout--;}
+	if (recv_avail == 0) return UART_ERR_TIMEOUT;
+	
+	return UART_read_char();
+}
+
+/**
+ * Enables the timer (interrupt) that samples the data line to receive the bits.
+ * Disables the Capture (ICP) interrupt that triggered on the start bit.
+ */
+void UART_start_read(void){
+	recv_bits = 0;
+	
+	#if SWSERIAL_PARITY == EVEN
+		recv_parity = 0;
+	#endif
+	#if SWSERIAL_PARITY == ODD
+		recv_parity = 1;
+	#endif
+	
+	TCNT1 = 0xFFFF-70; //Timer value. We start above the match counter, instead of starting af 0, this makes the first tick take a little longer, moving the sampling further inside the bit, not at the very beginning.
+
+	TIFR = (1 << OCF1A); //clear old interrupt flag
+	TIMSK = (1 << OCIE1A); //Disable ICP interrupt, Enable timer Compare Interrupt.
+}
+
+/**
+ * Capture interrupt, trigered by a falling edge on the data line (start bit)
+ */
+ISR(TIMER1_CAPT_vect){
+	PORTB |= (1 << 5); //Debug
+	UART_start_read();
+	PORTB &= ~(1 << 5); //Debug
+}
+
+/**
+ * Timer interrupt, samples the data line and writes the bits to the recv buffer.
+ * If all bits are read it returns control to the Capture interrupt and disables itself.
+ */
+ISR(TIMER1_COMPA_vect){
+	PORTB |= (1 << 7); //Debug
+	
+	uint8_t bit = (SWSERIAL_PIN & (1 << SWSERIAL_LINE)) ? 1 : 0;
+	
+	if (recv_bits < 8){
+		recv_buffer1 >>= 1;
+		recv_buffer1 |= (bit ? 0x80 : 0);
+		if (bit) recv_parity = !recv_parity;
+	}
+	if (recv_bits == 8){
+		recv_valid = bit == recv_parity;
+	}
+	if (recv_bits == 9){
+		if (!bit) recv_valid = 0;
+	}
+	
+	recv_bits++;
+	if (recv_bits == 10){
+		if (recv_valid){
+			recv_buffer2 = recv_buffer1;
+			recv_avail = 1;
+		}
+		recv_bits = 0;
+		UART_recv_init();
+	}
+	PORTB &= ~(1 << 7); //Debug
+}
diff --git a/ATMegaCard/software_serial.h b/ATMegaCard/software_serial.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7a423a9ac21d818acbf0493e2beafce84ae69df
--- /dev/null
+++ b/ATMegaCard/software_serial.h
@@ -0,0 +1,58 @@
+#include "common.h"
+#include <avr/io.h>
+#include <util/delay_basic.h>
+#include <util/delay.h>
+#include <avr/interrupt.h>
+
+//Serial Data Line: PD6  (ICP)
+
+#define BAUD 9600
+#define SWSERIAL_PARITY EVEN
+#define SWSERIAL_STOPBITS 2
+#define SWSERIAL_PORT_NAME D
+#define SWSERIAL_LINE 6
+
+#define UART_ERR_TIMEOUT 0xFFFF
+
+#ifndef XPASTE
+	//Macro magic to glue #defined names together. See http://groups.google.com/group/comp.lang.c/msg/8c085fe5a8ad1296?hl=en
+	#define PASTE(a,b) a ## b
+	#define XPASTE(a,b) PASTE(a,b)
+#endif
+
+#define EVEN 1
+#define ODD  2
+#define NONE 0
+#ifndef SWSERIAL_PARITY
+	#define SWSERIAL_PARITY NONE
+#endif
+#ifndef SWSERIAL_STOPBITS
+	#define SWSERIAL_STOPBITS 1
+#endif
+
+#define BIT_LENGTH 1000000/BAUD //(µSec) Duration of a RS232 Bit
+
+#define SWSERIAL_PORT_DR XPASTE(DDR, SWSERIAL_PORT_NAME)
+#define SWSERIAL_PORT    XPASTE(PORT,SWSERIAL_PORT_NAME)
+#define SWSERIAL_PIN     XPASTE(PIN, SWSERIAL_PORT_NAME)
+
+#define WRITE(x) if ((x) != 0) {SWSERIAL_PORT |= (1 << SWSERIAL_LINE);} else {SWSERIAL_PORT &= (unsigned char)~(1 << SWSERIAL_LINE);}
+
+
+#define INST_LENGTH(count) ((1000000*count)/F_CPU)  //(µSec) Duration of count CPU Instructions
+
+void UART_transmit_char(unsigned char data);
+
+void UART_transmit_buffer_sz(char* buffer);
+void UART_transmit_byte_hex(unsigned char b);
+
+void UART_init(void);
+
+void UART_transmit_init(void);
+void UART_recv_init(void);
+
+void UART_transmit_char(unsigned char x);
+
+uint8_t UART_data_available(void);
+uint8_t UART_read_char(void);
+uint16_t UART_receive_char_timeout(uint16_t timeout);
\ No newline at end of file