#define INTERVAL_SECONDS 30
-int b32_decode(char *buf, size_t *len) {
+static inline char *b32_advance_inptr(char *inptr) {
+ while (isspace(*inptr) || *inptr == '\n')
+ inptr++;
+ return inptr;
+}
+
+static inline uint8_t b32_decode_char(uint8_t c) {
const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
- size_t i = 0, used = 0;
+ char *ptr = strchr(alphabet, toupper(c));
+ if (ptr == NULL || *ptr == '\0') {
+ fprintf(
+ stderr,
+ "Error: %s: invalid input: '%c' (%02X)\n",
+ __func__,
+ c,
+ c
+ );
+ return UINT8_MAX;
+ }
+ return ptr - alphabet;
+}
+
+static inline int b32_decode(char *buf, size_t *len) {
+ size_t used;
uint8_t x;
- char *ptr, *output = buf;
- for(;;) {
- while(isspace(buf[i]) || buf[i] == '\n')
- i++;
- if(buf[i] == '\0' || buf[i] == '=')
+ char *outptr = buf, *inptr = buf;
+ for (used = 0;; used = (used + 1) & 7) {
+ inptr = b32_advance_inptr(inptr);
+ if (*inptr == '\0' || *inptr == '=')
break;
- ptr = strchr(alphabet, toupper(buf[i]));
- if(ptr == NULL || *ptr == '\0') {
- fprintf(
- stderr,
- "Error: invalid input: '%c' (%02X)\n",
- buf[i],
- (uint8_t)buf[i]
- );
+ x = b32_decode_char(*inptr++);
+ if (x == UINT8_MAX)
return -1;
- }
- i++;
- x = ptr - alphabet;
- switch(used++ % 8) {
+ switch (used) {
case 0:
- *output = x << 3;
+ *outptr = x << 3;
break;
case 1:
- *output |= x >> 2;
- output++;
- *output = x << 6;
+ *outptr |= x >> 2;
+ outptr++;
+ *outptr = x << 6;
break;
case 2:
- *output |= x << 1;
+ *outptr |= x << 1;
break;
case 3:
- *output |= x >> 4;
- output++;
- *output = x << 4;
+ *outptr |= x >> 4;
+ outptr++;
+ *outptr = x << 4;
break;
case 4:
- *output |= x >> 1;
- output++;
- *output = x << 7;
+ *outptr |= x >> 1;
+ outptr++;
+ *outptr = x << 7;
break;
case 5:
- *output |= x << 2;
+ *outptr |= x << 2;
break;
case 6:
- *output |= x >> 3;
- output++;
- *output = x << 5;
+ *outptr |= x >> 3;
+ outptr++;
+ *outptr = x << 5;
break;
case 7:
- *output |= x;
- output++;
+ *outptr |= x;
+ outptr++;
break;
}
}
- if(len != NULL)
- *len = output - buf;
+ if (len != NULL)
+ *len = outptr - buf;
return 0;
}
-static inline uint8_t *pack_be64(
- uint8_t data[],
- uint64_t value
-) {
+static inline uint8_t *pack_be64(uint8_t data[], uint64_t value) {
size_t i;
- for(i = 0; i < sizeof value; i++)
- data[i] = (value >> ((sizeof value - 1 - i) * CHAR_BIT)) & 0xff;
+ for (i = 0; i < sizeof value; i++)
+ data[i] = value >> ((sizeof value - 1 - i) * CHAR_BIT);
return data;
}
-int calculate_totp(const char *line, const char *search) {
+static inline int calculate_totp(const char *line, const char *search) {
size_t len = 0;
unsigned int hmac_len = 0, label_len;
- uint8_t data[sizeof(uint64_t)], i;
- char *ptr, *find;
- if(line == NULL)
+ uint8_t data[sizeof (uint64_t)], i, *ptr8;
+ char *find, *ptr = line ? strrchr(line, ':') : NULL;
+ if (ptr == NULL)
return -1;
- if(strlen(line) < 2)
+ if (strlen(line) < 2)
return 0;
- ptr = strrchr(line, ':');
- if(ptr == NULL)
- return -1;
label_len = ptr - line;
if (search != NULL) {
find = strcasestr(line, search);
- if (find == NULL || find + strlen(search) - line > label_len)
+ if (find == NULL || find + strlen(search) > ptr)
return 0;
}
ptr++;
- if(b32_decode(ptr, &len) < 0) {
- fprintf(stderr, "Error: b32_decode.\n");
+ if (b32_decode(ptr, &len) < 0)
return -1;
- }
// fill data with the current time divided by INTERVAL_SECONDS
pack_be64(data, time(NULL) / INTERVAL_SECONDS);
- if(
- HMAC(
- EVP_sha1(),
- ptr,
- len,
- data,
- sizeof data,
- (uint8_t*)ptr,
- &hmac_len
- ) == NULL
+ ptr8 = (uint8_t*)ptr;
+ if (
+ HMAC(EVP_sha1(), ptr, len, data, sizeof data, ptr8, &hmac_len) == NULL
) {
fprintf(stderr, "\nError: hmac.\n");
return -1;
}
- i = ptr[hmac_len - 1] & 0xf;
+ i = ptr8[hmac_len - 1] & 0xf;
printf(
"%.*s: %06"PRIu32"\n",
label_len,
line,
(
- (((uint8_t)ptr[i] & 0x7f) << 24) | ((uint8_t)ptr[i + 1] << 16) |
- ((uint8_t)ptr[i + 2] << 8) | (uint8_t)ptr[i + 3]
+ ((ptr8[i] & 0x7f) << 24)
+ | (ptr8[i + 1] << 16)
+ | (ptr8[i + 2] << 8)
+ | ptr8[i + 3]
) % 1000000
);
return 0;
case -1:
goto error;
}
- while(fgets(buf, sizeof buf, ta.fh) != NULL)
- if(calculate_totp(buf, ta.search) < 0)
+ while (fgets(buf, sizeof buf, ta.fh) != NULL)
+ if (calculate_totp(buf, ta.search) < 0)
goto error;
- if(ferror(ta.fh)) {
+ if (ferror(ta.fh)) {
fprintf(stderr, "Error: read error.\n");
goto error;
}