aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/lib/libotputil/lrfc2289-otp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libotputil/lrfc2289-otp.c')
-rw-r--r--lib/libotputil/lrfc2289-otp.c294
1 files changed, 292 insertions, 2 deletions
diff --git a/lib/libotputil/lrfc2289-otp.c b/lib/libotputil/lrfc2289-otp.c
index 627ed12..fe96ce9 100644
--- a/lib/libotputil/lrfc2289-otp.c
+++ b/lib/libotputil/lrfc2289-otp.c
@@ -49,6 +49,7 @@
49#include <openssl/evp.h> 49#include <openssl/evp.h>
50#include <openssl/hmac.h> 50#include <openssl/hmac.h>
51 51
52#include "lmisc.h"
52#include "lrfc1760-skey-dict.h" 53#include "lrfc1760-skey-dict.h"
53 54
54 55
@@ -66,6 +67,33 @@ otputil_otp_decode_hex(
66 67
67 68
68static int 69static int
70otputil_otp_decode_value(
71 int val,
72 int * wordcount,
73 otputil_bv_t * dst,
74 size_t maxlen );
75
76
77static int
78otputil_otp_decode_verify(
79 int wordcount,
80 otputil_bv_t * dst );
81
82
83static int
84otputil_otp_decode_word(
85 const char * word,
86 int * methodp,
87 const EVP_MD * evp_md );
88
89
90static int
91otputil_otp_dict_value(
92 const char * word,
93 const EVP_MD * evp_md );
94
95
96static int
69otputil_otp_encode_word( 97otputil_otp_encode_word(
70 char * dst, 98 char * dst,
71 int value, 99 int value,
@@ -88,11 +116,21 @@ otputil_otp_encode_word(
88otputil_bv_t * 116otputil_bv_t *
89otputil_otp_decode( 117otputil_otp_decode(
90 const char * src, 118 const char * src,
91 otputil_bv_t * dst ) 119 otputil_bv_t * dst,
120 int altdict_hash )
92{ 121{
93 static otputil_bv_t bv; 122 static otputil_bv_t bv;
94 static uint8_t buff[OTPUTIL_MAX_DECODE_SIZE]; 123 static uint8_t buff[OTPUTIL_MAX_DECODE_SIZE];
124 char word[OTPUTIL_MAX_WORD_SIZE];
125 int wlen;
95 int rc; 126 int rc;
127 int method;
128 int pos;
129 int len;
130 int val;
131 int wordcount;
132 size_t bv_len;
133 const EVP_MD * evp_md;
96 134
97 assert(src != NULL); 135 assert(src != NULL);
98 136
@@ -110,9 +148,49 @@ otputil_otp_decode(
110 if (rc == -1) 148 if (rc == -1)
111 return(NULL); 149 return(NULL);
112 150
151 // determine message digest
152 evp_md = (!(altdict_hash)) ? NULL : otputil_evp_md(altdict_hash);
153 if ( ((altdict_hash)) && (!(evp_md)) )
154 return(NULL);
155
113 // checks for six-word format with S/KEY dictionary 156 // checks for six-word format with S/KEY dictionary
157 method = 0;
158 len = -1;
159 bv_len = dst->bv_len;
160 dst->bv_len = 0;
161 wordcount = 0;
162 for(pos = 0; ((src[pos])); pos++)
163 {
164 // skip white space
165 if ((isspace(src[pos])))
166 continue;
167
168 // check for invalid character
169 if (!(isalnum(src[pos])))
170 return(NULL);
171
172 // process word
173 for(wlen = 0; ( ((isalnum(src[pos+wlen])) && (wlen < (int)sizeof(word))) ); wlen++)
174 word[wlen] = src[pos+wlen];
175 if (wlen >= (int)sizeof(word))
176 return(NULL);
177 word[wlen] = '\0';
178 pos += wlen - 1;
179
180 // decode word
181 if ((val = otputil_otp_decode_word(word, &method, evp_md)) == -1)
182 return(NULL);
114 183
115 return(NULL); 184 // add value to buffer
185 if (otputil_otp_decode_value(val, &wordcount, dst, bv_len) == -1)
186 return(NULL);
187 };
188
189 // verify checksum of six-word encoding
190 if (otputil_otp_decode_verify(wordcount, dst) == -1)
191 return(NULL);
192
193 return(dst);
116} 194}
117 195
118 196
@@ -165,6 +243,194 @@ otputil_otp_decode_hex(
165 return(0); 243 return(0);
166} 244}
167 245
246
247int
248otputil_otp_decode_value(
249 int val,
250 int * wordcount,
251 otputil_bv_t * dst,
252 size_t maxlen )
253{
254 int8_t * bytes;
255
256 if ((val & ~0x07FF))
257 return(-1);
258 if ((dst->bv_len+2) > maxlen)
259 return(-1);
260
261 bytes = dst->bv_val;
262
263 switch(*wordcount % 8)
264 {
265 case 0: // word 0: ( 00000000 000----- -------- )
266 bytes[dst->bv_len++] = (val >> 3) & 0xff;
267 bytes[dst->bv_len++] = (val << 5) & 0xe0;
268 break;
269
270 case 1: // word 1: ( 00011111 111111-- -------- )
271 bytes[dst->bv_len-1] |= (val >> 6) & 0x1f;
272 bytes[dst->bv_len++] = (val << 2) & 0xfc;
273 break;
274
275 case 2: // word 2: ( 11111122 22222222 2------- )
276 if ((dst->bv_len+2) > maxlen)
277 return(-1);
278 bytes[dst->bv_len-1] |= (val >> 9) & 0x03;
279 bytes[dst->bv_len++] = (val >> 1) & 0xff;
280 bytes[dst->bv_len++] = (val << 7) & 0x80;
281 break;
282
283 case 3: // word 3: ( 23333333 3333---- -------- )
284 bytes[dst->bv_len-1] |= (val >> 4) & 0x7f;
285 bytes[dst->bv_len++] = (val << 4) & 0xf0;
286 break;
287
288 case 4: // word 4: ( 33334444 4444444- -------- )
289 bytes[dst->bv_len-1] |= (val >> 7) & 0x0f;
290 bytes[dst->bv_len++] = (val << 1) & 0xfe;
291 break;
292
293 case 5: // word 5: ( 44444445 55555555 55------ )
294 if ((dst->bv_len+2) > maxlen)
295 return(-1);
296 bytes[dst->bv_len-1] |= (val >> 10) & 0x01;
297 bytes[dst->bv_len++] = (val >> 2) & 0xff;
298 bytes[dst->bv_len++] = (val << 6) & 0xc0;
299 break;
300
301 case 6: // word 6: ( 55666666 66666--- -------- )
302 bytes[dst->bv_len-1] |= (val >> 5) & 0x3f;
303 bytes[dst->bv_len++] = (val << 3) & 0xf8;
304 break;
305
306 case 7: // word 7: ( 66666777 77777777 -------- )
307 bytes[dst->bv_len-1] |= (val >> 8) & 0xe0;
308 bytes[dst->bv_len++] = (val << 0) & 0x0f;
309 break;
310
311 default:
312 break;
313 };
314
315 (*wordcount)++;
316
317 return(0);
318}
319
320
321int
322otputil_otp_decode_verify(
323 int wordcount,
324 otputil_bv_t * dst )
325{
326 size_t pos;
327 int8_t * bytes;
328 int checksum;
329 int sum;
330
331 if (!(wordcount))
332 return(0);
333
334 bytes = dst->bv_val;
335
336 // finish checksum
337 // Mappings:
338 // 0 1 2 3 4 5 6 7 8 9 a
339 // 00000000 00011111 11111122 22222222 23333333 33334444 44444445 55555555 55666666 66666777 77777777
340 switch(wordcount % 8)
341 {
342 case 1: // word 0: bytes 1: ( 00000000 000----- -------- )
343 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
344 dst->bv_len--;
345 break;
346
347 case 2: // word 1: bytes 1: ( 00011111 111111-- -------- )
348 return(-1);
349
350 case 3: // word 2: bytes 2: ( 11111122 22222222 2------- )
351 checksum = (bytes[dst->bv_len-2] >> 6) & 0x03;
352 dst->bv_len -= 2;
353 break;
354
355 case 4: // word 3: bytes 3: ( 23333333 3333---- -------- )
356 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
357 dst->bv_len--;
358 break;
359
360 case 5: // word 4: bytes 4: ( 33334444 4444444- -------- )
361 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
362 dst->bv_len--;
363 break;
364
365 case 6: // word 5: bytes 5: ( 44444445 55555555 55------ )
366 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
367 dst->bv_len--;
368 break;
369
370 case 7: // word 6: bytes 6: ( 55666666 66666--- -------- )
371 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
372 dst->bv_len--;
373 break;
374
375 case 0: // word 7: bytes 7: ( 66666777 77777777 -------- )
376 checksum = (bytes[dst->bv_len-1] >> 6) & 0x03;
377 dst->bv_len--;
378 break;
379
380 default:
381 return(-1);
382 };
383
384 // start generating checksum
385 for(pos = 0, sum = 0; (pos < dst->bv_len); pos++)
386 {
387 sum += (bytes[pos] >> 6) & 0x03;
388 sum += (bytes[pos] >> 4) & 0x03;
389 sum += (bytes[pos] >> 2) & 0x03;
390 sum += (bytes[pos] >> 0) & 0x03;
391 sum &= 0x03;
392 };
393 if (sum != checksum)
394 return(-1);
395
396 return(0);
397}
398
399
400int
401otputil_otp_decode_word(
402 const char * word,
403 int * methodp,
404 const EVP_MD * evp_md )
405{
406 int val;
407
408 switch(*methodp)
409 {
410 case OTPUTIL_ENC_SIXWORD:
411 return(otputil_skey_dict_value(word));
412
413 case OTPUTIL_ENC_ALTDICT:
414 return(otputil_otp_dict_value(word, evp_md));
415
416 default:
417 if ((val = otputil_skey_dict_value(word)) != -1)
418 {
419 *methodp = OTPUTIL_ENC_SIXWORD;
420 return(val);
421 };
422 if ((val = otputil_otp_dict_value(word, evp_md)) != -1)
423 {
424 *methodp = OTPUTIL_ENC_ALTDICT;
425 return(val);
426 };
427 break;
428 };
429
430 return(-1);
431}
432
433
168size_t 434size_t
169otputil_otp_decode_len( 435otputil_otp_decode_len(
170 const char * str ) 436 const char * str )
@@ -182,6 +448,30 @@ otputil_otp_decode_len(
182} 448}
183 449
184 450
451int
452otputil_otp_dict_value(
453 const char * word,
454 const EVP_MD * evp_md )
455{
456 unsigned char md[EVP_MAX_MD_SIZE];
457 unsigned md_len;
458 int val;
459
460 if (!(evp_md))
461 return(-1);
462
463 md_len = sizeof(md);
464 if (!(EVP_Digest(word, strlen(word), md, &md_len, evp_md, NULL)))
465 return(-1);
466
467 val = 0;
468 val |= (md[md_len-1] & 0xff) << 0;
469 val |= (md[md_len-2] & 0x07) << 8;
470
471 return(val);
472}
473
474
185const char * 475const char *
186otputil_otp_encode( 476otputil_otp_encode(
187 const otputil_bv_t * bv, 477 const otputil_bv_t * bv,