1 /*
2 ** $Id: io.c 1003 2008-06-24 14:35:09Z aaron $
3 */
4 /************************************************************************
5 * *
6 * Copyright (C) 2002 *
7 * Internet2 *
8 * All Rights Reserved *
9 * *
10 ************************************************************************/
11 /*
12 ** File: io.c
13 **
14 ** Author: Jeff W. Boote
15 ** Anatoly Karp
16 **
17 ** Date: Wed Apr 24 10:42:12 2002
18 **
19 ** Description: This file contains the private functions to
20 ** to facilitate IO that the library needs to do.
21 */
22 #include <owampP.h>
23
24 #include <I2util/pbkdf2.h>
25 #include <I2util/hmac-sha1.h>
26
27 int
_OWPSendBlocksIntr(OWPControl cntrl,uint8_t * buf,int num_blocks,int * retn_on_intr)28 _OWPSendBlocksIntr(
29 OWPControl cntrl,
30 uint8_t *buf,
31 int num_blocks,
32 int *retn_on_intr
33 )
34 {
35 ssize_t n;
36
37 if (cntrl->mode & OWP_MODE_DOCIPHER)
38 _OWPEncryptBlocks(cntrl, buf, num_blocks, buf);
39
40 n = I2Writeni(cntrl->sockfd,buf,num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE,
41 retn_on_intr);
42 if(n < 0){
43 return -1;
44 }
45
46 return num_blocks;
47 }
48
49 int
_OWPReceiveBlocksIntr(OWPControl cntrl,uint8_t * buf,int num_blocks,int * retn_on_intr)50 _OWPReceiveBlocksIntr(
51 OWPControl cntrl,
52 uint8_t *buf,
53 int num_blocks,
54 int *retn_on_intr
55 )
56 {
57 ssize_t n;
58
59 n = I2Readni(cntrl->sockfd,buf,num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE,
60 retn_on_intr);
61 if(n < 0){
62 return -1;
63 }
64
65 /*
66 * Short reads mean socket was closed.
67 */
68 if(n != (num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE))
69 return 0;
70
71 if (cntrl->mode & OWP_MODE_DOCIPHER)
72 _OWPDecryptBlocks(cntrl, buf, num_blocks, buf);
73
74 return num_blocks;
75 }
76
77 int
_OWPSendBlocks(OWPControl cntrl,uint8_t * buf,int num_blocks)78 _OWPSendBlocks(
79 OWPControl cntrl,
80 uint8_t *buf,
81 int num_blocks
82 )
83 {
84 int intr=1;
85 int *retn_on_intr = &intr;
86
87 if(cntrl->retn_on_intr){
88 retn_on_intr = cntrl->retn_on_intr;
89 }
90
91 return _OWPSendBlocksIntr(cntrl,buf,num_blocks,retn_on_intr);
92 }
93
94 int
_OWPReceiveBlocks(OWPControl cntrl,uint8_t * buf,int num_blocks)95 _OWPReceiveBlocks(
96 OWPControl cntrl,
97 uint8_t *buf,
98 int num_blocks
99 )
100 {
101 int intr=1;
102 int *retn_on_intr = &intr;
103
104 if(cntrl->retn_on_intr){
105 retn_on_intr = cntrl->retn_on_intr;
106 }
107
108 return _OWPReceiveBlocksIntr(cntrl,buf,num_blocks,retn_on_intr);
109 }
110
111 /*
112 ** The following two functions encrypt/decrypt a given number
113 ** of (_OWP_RIJNDAEL_BLOCK_SIZE-byte) blocks. IV is currently updated within
114 ** the rijndael api (blockEncrypt/blockDecrypt).
115 */
116 int
_OWPEncryptBlocks(OWPControl cntrl,uint8_t * buf,int num_blocks,uint8_t * out)117 _OWPEncryptBlocks(
118 OWPControl cntrl,
119 uint8_t *buf,
120 int num_blocks,
121 uint8_t *out
122 )
123 {
124 int r;
125 r = blockEncrypt(cntrl->writeIV,&cntrl->encrypt_key,
126 (uint8_t *)buf, num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE*8,
127 (uint8_t *)out);
128 if (r != num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE*8)
129 return -1;
130 return 0;
131 }
132
133
134 int
_OWPDecryptBlocks(OWPControl cntrl,uint8_t * buf,int num_blocks,uint8_t * out)135 _OWPDecryptBlocks(
136 OWPControl cntrl,
137 uint8_t *buf,
138 int num_blocks,
139 uint8_t *out
140 )
141 {
142 int r;
143 r = blockDecrypt(cntrl->readIV,&cntrl->decrypt_key,
144 (uint8_t *)buf, num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE*8,
145 (uint8_t *)out);
146 if (r != num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE*8)
147 return -1;
148 return 0;
149 }
150
151 /*
152 ** This function sets up the key field of a OWPControl structure,
153 ** using the binary key located in <binKey>.
154 */
155
156 void
_OWPMakeKey(OWPControl cntrl,uint8_t binKey[_OWP_RIJNDAEL_BLOCK_SIZE])157 _OWPMakeKey(
158 OWPControl cntrl,
159 uint8_t binKey[_OWP_RIJNDAEL_BLOCK_SIZE]
160 )
161 {
162 cntrl->encrypt_key.Nr = rijndaelKeySetupEnc(cntrl->encrypt_key.rk,binKey,
163 _OWP_RIJNDAEL_BLOCK_SIZE*8);
164 cntrl->decrypt_key.Nr = rijndaelKeySetupDec(cntrl->decrypt_key.rk,binKey,
165 _OWP_RIJNDAEL_BLOCK_SIZE*8);
166 }
167
168
169 /*
170 * The next two functions perform a single encryption/decryption
171 * of the Token in the SetupResponse message from the Control protocol.
172 *
173 * (AES CBC, IV=0) key=pbkdf2(pf,salt,count)
174 */
175
176 int
OWPEncryptToken(const uint8_t * pf,size_t pf_len,const uint8_t salt[_OWP_SALT_SIZE],uint32_t count,const uint8_t token_in[_OWP_TOKEN_SIZE],uint8_t token_out[_OWP_TOKEN_SIZE])177 OWPEncryptToken(
178 const uint8_t *pf,
179 size_t pf_len,
180 const uint8_t salt[_OWP_SALT_SIZE],
181 uint32_t count,
182 const uint8_t token_in[_OWP_TOKEN_SIZE],
183 uint8_t token_out[_OWP_TOKEN_SIZE]
184 )
185 {
186 int r;
187 uint8_t IV[_OWP_RIJNDAEL_BLOCK_SIZE];
188 uint8_t dk[_OWP_RIJNDAEL_BLOCK_SIZE];
189 keyInstance key;
190
191 /*
192 * Derive key
193 */
194 if( (I2pbkdf2(I2HMACSha1,(uint32_t)I2SHA1_DIGEST_SIZE,
195 pf,pf_len,salt,_OWP_SALT_SIZE,count,sizeof(dk),dk))){
196 return -1;
197 }
198
199 memset(IV, 0, _OWP_RIJNDAEL_BLOCK_SIZE);
200
201 key.Nr = rijndaelKeySetupEnc(key.rk, dk, sizeof(dk)*8);
202 r = blockEncrypt(IV,&key,token_in,_OWP_TOKEN_SIZE*8,token_out);
203
204 if (r != (_OWP_TOKEN_SIZE*8))
205 return -1;
206
207 return 0;
208 }
209
210 int
OWPDecryptToken(const uint8_t * pf,size_t pf_len,const uint8_t salt[_OWP_SALT_SIZE],uint32_t count,const uint8_t token_in[_OWP_TOKEN_SIZE],uint8_t token_out[_OWP_TOKEN_SIZE])211 OWPDecryptToken(
212 const uint8_t *pf,
213 size_t pf_len,
214 const uint8_t salt[_OWP_SALT_SIZE],
215 uint32_t count,
216 const uint8_t token_in[_OWP_TOKEN_SIZE],
217 uint8_t token_out[_OWP_TOKEN_SIZE]
218 )
219 {
220 int r;
221 uint8_t IV[_OWP_RIJNDAEL_BLOCK_SIZE];
222 uint8_t dk[_OWP_RIJNDAEL_BLOCK_SIZE];
223 keyInstance key;
224
225 /*
226 * Derive key
227 */
228 if( (I2pbkdf2(I2HMACSha1,(uint32_t)I2SHA1_DIGEST_SIZE,
229 pf,pf_len,salt,_OWP_SALT_SIZE,count,sizeof(dk),dk))){
230 return -1;
231 }
232
233 memset(IV, 0, _OWP_RIJNDAEL_BLOCK_SIZE);
234
235 key.Nr = rijndaelKeySetupDec(key.rk, dk, 128);
236 r = blockDecrypt(IV,&key,token_in,_OWP_TOKEN_SIZE*8,token_out);
237
238 if (r != (_OWP_TOKEN_SIZE*8))
239 return -1;
240
241 return 0;
242 }
243
244 /*
245 * Function: _OWPSendHMACAdd
246 *
247 * Description:
248 * Adds data to the 'send' HMAC.
249 *
250 * In Args:
251 *
252 * Out Args:
253 *
254 * Scope:
255 * Returns:
256 * Side Effect:
257 */
258 void
_OWPSendHMACAdd(OWPControl cntrl,const char * txt,uint32_t num_blocks)259 _OWPSendHMACAdd(
260 OWPControl cntrl,
261 const char *txt,
262 uint32_t num_blocks
263 )
264 {
265 if( !(cntrl->mode & OWP_MODE_DOCIPHER)){
266 return;
267 }
268
269 I2HMACSha1Append(cntrl->send_hmac_ctx,(uint8_t *)txt,
270 num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE);
271
272 return;
273 }
274
275 /*
276 * Function: _OWPSendHMACDigestClear
277 *
278 * Description:
279 * Fetches the digest from the 'send' HMAC and
280 * clears the digest in preparation for the next
281 * "message".
282 *
283 * In Args:
284 *
285 * Out Args:
286 *
287 * Scope:
288 * Returns:
289 * Side Effect:
290 */
291 void
_OWPSendHMACDigestClear(OWPControl cntrl,char digest[_OWP_RIJNDAEL_BLOCK_SIZE])292 _OWPSendHMACDigestClear(
293 OWPControl cntrl,
294 char digest[_OWP_RIJNDAEL_BLOCK_SIZE]
295 )
296 {
297 uint8_t hmacd[I2HMAC_SHA1_DIGEST_SIZE];
298
299 memset(digest,0,_OWP_RIJNDAEL_BLOCK_SIZE);
300
301 if( !(cntrl->mode & OWP_MODE_DOCIPHER)){
302 return;
303 }
304
305 memset(hmacd,0,sizeof(hmacd));
306
307 I2HMACSha1Finish(cntrl->send_hmac_ctx,hmacd);
308 memcpy(digest,hmacd,MIN(_OWP_RIJNDAEL_BLOCK_SIZE,sizeof(hmacd)));
309
310 I2HMACSha1Init(cntrl->send_hmac_ctx,cntrl->hmac_key,
311 sizeof(cntrl->hmac_key));
312 return;
313 }
314
315 /*
316 * Function: _OWPRecvHMACAdd
317 *
318 * Description:
319 * Adds data to the 'send' HMAC.
320 *
321 * In Args:
322 *
323 * Out Args:
324 *
325 * Scope:
326 * Returns:
327 * Side Effect:
328 */
329 void
_OWPRecvHMACAdd(OWPControl cntrl,const char * txt,uint32_t num_blocks)330 _OWPRecvHMACAdd(
331 OWPControl cntrl,
332 const char *txt,
333 uint32_t num_blocks
334 )
335 {
336 if( !(cntrl->mode & OWP_MODE_DOCIPHER)){
337 return;
338 }
339
340 I2HMACSha1Append(cntrl->recv_hmac_ctx,(uint8_t *)txt,
341 num_blocks*_OWP_RIJNDAEL_BLOCK_SIZE);
342
343 return;
344 }
345
346 /*
347 * Function: _OWPRecvHMACCheckClear
348 *
349 * Description:
350 * Determines if the hmac sent from the remote
351 * party matches the locally computed one. Then
352 * clears the hmac and prepares it for the next
353 * message.
354 *
355 * In Args:
356 *
357 * Out Args:
358 *
359 * Scope:
360 * Returns:
361 * Side Effect:
362 */
363 OWPBoolean
_OWPRecvHMACCheckClear(OWPControl cntrl,char check[_OWP_RIJNDAEL_BLOCK_SIZE])364 _OWPRecvHMACCheckClear(
365 OWPControl cntrl,
366 char check[_OWP_RIJNDAEL_BLOCK_SIZE]
367 )
368 {
369 uint8_t hmacd[I2HMAC_SHA1_DIGEST_SIZE];
370 OWPBoolean rval;
371
372 if( !(cntrl->mode & OWP_MODE_DOCIPHER)){
373 return True;
374 }
375
376 memset(hmacd,0,sizeof(hmacd));
377
378 I2HMACSha1Finish(cntrl->recv_hmac_ctx,hmacd);
379 rval = (memcmp(check,hmacd,
380 MIN(_OWP_RIJNDAEL_BLOCK_SIZE,sizeof(hmacd))) == 0);
381
382 I2HMACSha1Init(cntrl->recv_hmac_ctx,cntrl->hmac_key,
383 sizeof(cntrl->hmac_key));
384
385 return rval;
386 }
387