14 unsigned char hash[HASHSIZE];
17 static struct _hash_obj
18 make_challenge(const char *uid, const char *pass, const char *nonce)
20 struct _hash_obj ho = {0};
23 int datasize = strlen(uid) + strlen(pass) + strlen(nonce) +
25 unsigned char *data = alloca(datasize);
26 int hashsize = sizeof(ho.hash);
28 serial_init(&srl, data, datasize);
29 if (serial_put(&srl, uid, strlen(uid)) != strlen(uid)) {
30 ho.err = "challenge: serialization of uid failed";
31 } else if (serial_put(&srl, pass, strlen(pass)) != strlen(pass)) {
32 ho.err = "challenge: serialization of pass failed";
33 } else if (serial_put(&srl, nonce, strlen(nonce)) != strlen(nonce)) {
34 ho.err = "challenge: serialization of nonce failed";
35 } else if (serial_put(&srl, NULL, 0) != 0) {
36 ho.err = "challenge: serialization of terminator failed";
39 if ((rc = hash(data, serial_size(&srl), &ho.hash, &hashsize))) {
40 ho.err = crypto_errstr(rc);
41 } else if (hashsize != sizeof(ho.hash)) {
42 ho.err = "challenge: hash size is wrong";
45 memset(data, 0, datasize);
49 static struct _hash_obj
50 make_key(const unsigned char *challenge, const int challengesize,
51 const unsigned char *secret, const int secsize)
53 struct _hash_obj ho = {0};
55 int keysize = sizeof(ho.hash);
57 if ((rc = hmac(secret, secsize, challenge, challengesize,
58 &ho.hash, &keysize))) {
59 ho.err = crypto_errstr(rc);
60 } else if (keysize != sizeof(ho.hash)) {
61 ho.err = "make_key: hash size is wrong";
66 static struct _hash_obj
67 fetch_key(const unsigned char *challenge, const int challengesize)
69 struct _hash_obj ho = {0};
71 int keysize = sizeof(ho.hash);
73 if ((rc = pcsc_cr(challenge, challengesize, ho.hash, &keysize))) {
74 ho.err = pcsc_errstr(rc);
79 static struct _auth_obj
80 make_authobj(const unsigned char *key, const int keysize,
81 const unsigned char *secret, const int secsize,
82 const unsigned char *payload, const int paysize)
84 struct _auth_obj ao = {0};
88 unsigned char datahash[HASHSIZE];
89 int datahashsize = HASHSIZE;
92 if (keysize < CBLKSIZE) {
93 ao.err = "make authobj: key too short";
96 datasize = ((secsize + paysize + HASHSIZE + 4 * sizeof(short) - 1) /
97 CBLKSIZE + 1) * CBLKSIZE;
98 data = alloca(datasize);
99 serial_init(&srl, data, datasize);
100 if (serial_put(&srl, secret, secsize) != secsize) {
101 ao.err = "authobj: serialization of secret failed";
102 } else if (serial_put(&srl, payload, paysize) != paysize) {
103 ao.err = "authobj: serialization of payload failed";
104 } else if ((rc = hash(data, serial_size(&srl),
105 datahash, &datahashsize))) {
106 ao.err = crypto_errstr(rc);
107 } else if (serial_put(&srl, datahash, datahashsize) != datahashsize) {
108 ao.err = "authobj: serialization of hash failed";
109 } else if (serial_put(&srl, NULL, 0) != 0) {
110 ao.err = "authobj: serialization of terminator failed";
115 int osize = ((serial_size(&srl) -1) / CBLKSIZE + 1) * CBLKSIZE;
117 if ((ao.buffer = malloc(osize + paysize)) == NULL) {
118 ao.err = "make authobj: malloc failed";
119 } else if ((lrc = encrypt(key, CBLKSIZE, data,
120 ao.buffer, osize))) {
121 ao.err = crypto_errstr(lrc);
125 if (payload && paysize) {
126 /* payload passthrough */
127 ao.payload = ao.data + osize;
128 memcpy(ao.payload, payload, paysize);
129 ao.paylsize = paysize;
134 memset(data, 0, datasize);
138 static struct _auth_obj
139 parse_authobj(const unsigned char *key, const int keysize,
140 const unsigned char *buffer, const int bufsize)
143 struct _auth_obj ao = {0};
145 if (keysize < CBLKSIZE) {
146 ao.err = "parse authobj: key too short";
147 } else if ((ao.buffer = malloc(bufsize)) == NULL) {
148 ao.err = "parse authobj: malloc failed";
149 } else if ((rc = decrypt(key, CBLKSIZE, buffer, ao.buffer, bufsize))) {
150 ao.err = crypto_errstr(rc);
153 unsigned char myhash[HASHSIZE];
154 int myhsize = HASHSIZE;
155 unsigned char *theirhash;
159 serial_init(&srl, ao.buffer, bufsize);
160 if (serial_get(&srl, (void**)&ao.data, &ao.datasize)) {
161 ao.err = "mismatch: impossible secret";
162 } else if (serial_get(&srl, (void**)&ao.payload, &ao.paylsize)) {
163 ao.err = "mismatch: impossible payload";
164 } else if ((rc = hash(ao.buffer, serial_size(&srl),
165 myhash, &myhsize))) {
166 ao.err = crypto_errstr(rc);
167 } else if (serial_get(&srl, (void**)&theirhash, &theirhsize)) {
168 ao.err = "mismatch: impossible hash";
169 } else if (theirhsize != HASHSIZE) {
170 ao.err = "mismatch: hash is of wrong size";
171 } else if ((myhsize != theirhsize) ||
172 memcmp(myhash, theirhash, myhsize)) {
173 ao.err = "mismatch: different hash";
179 struct _auth_obj new_authobj(const char *userid, const char *password,
181 const unsigned char *secret, const int secsize,
182 const unsigned char *payload, const int paysize)
184 struct _auth_obj new_ao = {0};
185 struct _hash_obj ho_chal, ho_key;
187 ho_chal = make_challenge(userid, password, nonce);
189 new_ao.err = ho_chal.err;
192 ho_key = make_key(ho_chal.hash, sizeof(ho_chal.hash), secret, secsize);
193 memset(&ho_chal, 0, sizeof(ho_chal));
195 new_ao.err = ho_key.err;
198 new_ao = make_authobj(ho_key.hash, sizeof(ho_key.hash),
199 secret, secsize, payload, paysize);
200 memset(&ho_key, 0, sizeof(ho_key));
204 struct _auth_obj verify_authobj(const char *userid, const char *password,
205 const char *oldnonce, const char *newnonce,
206 const unsigned char *authobj, const int authsize)
208 struct _auth_obj old_ao;
209 struct _auth_obj new_ao = {0};
210 struct _hash_obj ho_chal, ho_key;
212 ho_chal = make_challenge(userid, password, oldnonce);
214 new_ao.err = ho_chal.err;
217 ho_key = fetch_key(ho_chal.hash, sizeof(ho_chal.hash));
218 memset(&ho_chal, 0, sizeof(ho_chal));
220 new_ao.err = ho_key.err;
223 old_ao = parse_authobj(ho_key.hash, sizeof(ho_key.hash),
225 memset(&ho_key, 0, sizeof(ho_key));
227 new_ao.err = old_ao.err;
228 if (old_ao.buffer) free(old_ao.buffer);
232 ho_chal = make_challenge(userid, password, newnonce);
234 new_ao.err = ho_chal.err;
237 ho_key = make_key(ho_chal.hash, sizeof(ho_chal.hash),
238 old_ao.data, old_ao.datasize);
239 memset(&ho_chal, 0, sizeof(ho_chal));
241 new_ao.err = ho_key.err;
244 new_ao = make_authobj(ho_key.hash, sizeof(ho_key.hash),
245 old_ao.data, old_ao.datasize,
246 old_ao.payload, old_ao.paylsize);
247 memset(&ho_key, 0, sizeof(ho_key));
249 if (old_ao.data) memset(old_ao.data, 0, old_ao.datasize);
250 if (old_ao.payload) memset(old_ao.payload, 0, old_ao.paylsize);
251 if (old_ao.buffer) free(old_ao.buffer);
255 struct _auth_obj reload_authobj(const char *userid, const char *password,
256 const char *oldnonce, const char *newnonce,
257 const unsigned char *authobj, const int authsize,
258 const unsigned char *payload, const int paysize)
260 struct _auth_obj old_ao;
261 struct _auth_obj new_ao = {0};
262 struct _hash_obj ho_chal, ho_key;
264 ho_chal = make_challenge(userid, password, oldnonce);
266 new_ao.err = ho_chal.err;
269 ho_key = fetch_key(ho_chal.hash, sizeof(ho_chal.hash));
270 memset(&ho_chal, 0, sizeof(ho_chal));
272 new_ao.err = ho_key.err;
275 memset(&ho_key, 0, sizeof(ho_key));