introcude authfile module
[pam_pcsc_cr.git] / authobj.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <stdio.h>
5 #include <string.h>
6 #include <alloca.h>
7 #include "serial.h"
8 #include "crypto.h"
9 #include "authobj.h"
10
11 int make_challenge(const char *id, const char *pass, const char *nonce,
12                 unsigned char *challenge, int *challengesize)
13 {
14         serializer_t srl;
15
16         serial_init(&srl, challenge, *challengesize);
17         if (serial_put(&srl, id, strlen(id)) != strlen(id))
18                 return aoe_serial;
19         if (serial_put(&srl, pass, strlen(pass)) != strlen(pass))
20                 return aoe_serial;
21         if (serial_put(&srl, nonce, strlen(nonce)) != strlen(nonce))
22                 return aoe_serial;
23         if (serial_put(&srl, NULL, 0) != 0)
24                 return aoe_serial;
25         *challengesize = serial_size(&srl);
26         return 0;
27 }
28
29 int make_authobj(const char *id, const char *pass, const char *nonce,
30                 const unsigned char *secret, const int secsize,
31                 const unsigned char *payload, const int paysize,
32                 unsigned char *buffer, int *bufsize)
33 {
34         unsigned char *data;
35         int datasize;
36         unsigned char datahash[HASHSIZE];
37         int datahashsize = HASHSIZE;
38         unsigned char *challenge;
39         int challengesize;
40         unsigned char key[HASHSIZE];
41         int keysize = HASHSIZE;
42         serializer_t srl;
43
44         datasize = ((secsize + paysize + HASHSIZE * 4 * sizeof(short) - 1) /
45                         CBLKSIZE + 1) * CBLKSIZE;
46         data = alloca(datasize);
47         serial_init(&srl, data, datasize);
48         if (serial_put(&srl, secret, secsize) != secsize) return aoe_serial;
49         if (serial_put(&srl, payload, paysize) != paysize) return aoe_serial;
50         if (hash(data, serial_size(&srl), datahash, &datahashsize))
51                 return aoe_size;
52         if (serial_put(&srl, datahash, datahashsize) != datahashsize)
53                 return aoe_serial;
54         if (serial_put(&srl, NULL, 0) != 0) return aoe_serial;
55         datasize = ((serial_size(&srl) -1) / CBLKSIZE + 1) * CBLKSIZE;
56
57         challengesize = ((strlen(id) + strlen(pass) + strlen(nonce) +
58                         4 * sizeof(short) - 1) / CBLKSIZE + 1) * CBLKSIZE;
59         challenge = alloca(challengesize);
60         if (make_challenge(id, pass, nonce, challenge, &challengesize))
61                 return aoe_serial;
62
63         if (hmac(secret, secsize, challenge, challengesize,
64                 key, &keysize)) return aoe_crypt;
65
66         if (*bufsize < datasize) return aoe_size;
67         if (encrypt(key, CBLKSIZE, data, buffer, datasize)) return aoe_crypt;
68         *bufsize = datasize;
69
70         return 0;
71 }
72
73 int parse_authobj(const unsigned char *key, const int keysize,
74                 const unsigned char *buffer, const int bufsize,
75                 unsigned char *secret, int *secsize,
76                 unsigned char *payload, int *paysize)
77 {
78         int datasize = bufsize;
79         unsigned char *data = alloca(datasize);
80         serializer_t srl;
81         int tsize;
82         unsigned char myhash[HASHSIZE];
83         int myhashsize = HASHSIZE;
84         unsigned char theirhash[HASHSIZE];
85         int theirhashsize = HASHSIZE;
86
87         if (decrypt(key, CBLKSIZE, buffer, data, datasize))
88                 return aoe_crypt;
89         serial_init(&srl, data, datasize);
90         tsize = *secsize;
91         *secsize = serial_get(&srl, secret, tsize);
92         if (*secsize > tsize || *secsize <= 0) return aoe_serial;
93         tsize = *paysize;
94         *paysize = serial_get(&srl, payload, tsize);
95         if (*paysize > tsize || *paysize <= 0) return aoe_serial;
96         if (hash(data, serial_size(&srl), myhash, &myhashsize))
97                 return aoe_crypt;
98         theirhashsize = serial_get(&srl, theirhash, theirhashsize);
99         if (theirhashsize != HASHSIZE) return aoe_data;
100         if ((myhashsize != theirhashsize) ||
101             memcmp(myhash, theirhash, myhashsize))
102                 return aoe_data;
103         return 0;
104 }