]> git.cryptolib.org Git - labortage2013badge.git/blob - firmware/hotp.c
test commit
[labortage2013badge.git] / firmware / hotp.c
1 /* htop.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2013 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <hmac-sha1.h>
25
26 static
27 uint32_t dtrunc(uint8_t* buffer) {
28     uint8_t idx;
29     union {
30         uint8_t w8[4];
31         uint32_t w32;
32     } r;
33
34     idx = buffer[19] & 0x0f;
35     r.w8[3] = buffer[idx++] & 0x7f;
36     r.w8[2] = buffer[idx++];
37     r.w8[1] = buffer[idx++];
38     r.w8[0] = buffer[idx];
39     return r.w32;
40 }
41
42 static
43 void reverse_string(char *str) {
44     char *end;
45     end = str + strlen(str) - 1;
46     while (end > str) {
47         *str ^= *end;
48         *end ^= *str;
49         *str ^= *end;
50         ++str;
51         --end;
52     }
53 }
54
55 static
56 void to_digits(char *buffer, uint32_t value, uint8_t digits) {
57     ldiv_t t;
58     if (value == 0) {
59         *buffer++ = '0';
60     }
61     while (value && digits--) {
62         t = ldiv(value, 10);
63         value = t.quot;
64         *buffer++ = t.rem + '0';
65     }
66     *buffer = '\0';
67 }
68
69 void hotp(char *buffer, const void* secret, uint16_t secret_length_b, uint32_t counter, uint8_t digits) {
70     union {
71         uint8_t mac[20];
72         uint8_t ctr_buffer[8];
73     } d;
74     uint32_t s;
75     d.ctr_buffer[7] = counter & 0xff;
76     counter >>= 8;
77     d.ctr_buffer[6] = counter & 0xff;
78     counter >>= 8;
79     d.ctr_buffer[5] = counter & 0xff;
80     counter >>= 8;
81     d.ctr_buffer[4] = counter & 0xff;
82     d.ctr_buffer[3] = 0;
83     d.ctr_buffer[2] = 0;
84     d.ctr_buffer[1] = 0;
85     d.ctr_buffer[0] = 0;
86     if (digits > 9) {
87         digits = 9;
88     }
89     hmac_sha1(d.mac, secret, secret_length_b, d.ctr_buffer, 64);
90     s = dtrunc(d.mac);
91     to_digits(buffer, s, digits);
92     reverse_string(buffer);
93 }