whitespace editing / typo correction
[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 <inttypes.h>
23 #include <hmac-sha1.h>
24
25 static
26 uint32_t dtrunc(uint8_t* buffer) {
27     uint8_t idx;
28     union {
29         uint8_t w8[4];
30         uint32_t w32;
31     } r;
32
33     idx = buffer[19] & 0x0f;
34     r.w8[3] = buffer[idx++] & 0x7f;
35     r.w8[2] = buffer[idx++];
36     r.w8[1] = buffer[idx++];
37     r.w8[0] = buffer[idx];
38     return r.w32;
39 }
40
41 static
42 void to_digits(char *buffer, uint32_t value, uint8_t digits) {
43     ldiv_t t;
44     if (value == 0) {
45         *buffer++ = '0';
46     }
47     while (value && digits--) {
48         t = ldiv(value, 10);
49         value = t.quot;
50         *buffer++ = t.rem + '0';
51     }
52     *buffer = '\0';
53 }
54
55 void hotp(char *buffer, void* secret, uint16_t secret_length_b, uint32_t counter, uint8_t digits) {
56     union {
57         uint8_t mac[20];
58         uint8_t ctr_buffer[8];
59     } d;
60     uint32_t s;
61     d.ctr_buffer[7] = 0;
62     d.ctr_buffer[6] = 0;
63     d.ctr_buffer[5] = 0;
64     d.ctr_buffer[4] = 0;
65     d.ctr_buffer[3] = counter & 0xff;
66     counter >>= 8;
67     d.ctr_buffer[2] = counter & 0xff;
68     counter >>= 8;
69     d.ctr_buffer[1] = counter & 0xff;
70     counter >>= 8;
71     d.ctr_buffer[0] = counter & 0xff;
72     hmac_sha1(d.mac, secret, secret_length_b, d.ctr_buffer, 64);
73     s = dtrunc(d.mac);
74     to_digits(buffer, s, digits);
75 }