summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorFranklin Wei <frankhwei536@gmail.com>2016-07-09 19:36:30 -0400
committerFranklin Wei <frankhwei536@gmail.com>2016-07-09 19:36:30 -0400
commit3df07c7953c950ed268ddb61a728f5d7d39ebc58 (patch)
tree29c878496f3e170bd21852b05cd3b38b02264ee0 /apps/plugins
parent5fc1b86d596778cf65c844eac2d36f607c870598 (diff)
downloadrockbox-3df07c7953c950ed268ddb61a728f5d7d39ebc58.zip
rockbox-3df07c7953c950ed268ddb61a728f5d7d39ebc58.tar.gz
rockbox-3df07c7953c950ed268ddb61a728f5d7d39ebc58.tar.bz2
rockbox-3df07c7953c950ed268ddb61a728f5d7d39ebc58.tar.xz
rename otp to passmgr
Change-Id: I9f172c71eb2f120e7071d6fa812e5b19b7d73124
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/CATEGORIES2
-rw-r--r--apps/plugins/SOURCES2
-rw-r--r--apps/plugins/passmgr.c (renamed from apps/plugins/otp.c)174
3 files changed, 112 insertions, 66 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 21d325f..4fda6ef 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -68,8 +68,8 @@ mp3_encoder,apps
mpegplayer,viewers
nim,games
oscilloscope,demos
-otp,apps
pacbox,games
+passmgr,apps
pdbox,viewers
pegbox,games
periodic_table,apps
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index ed3bf64..9131c26 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -34,7 +34,7 @@ disktidy.c
flipit.c
shopper.c
resistor.c
-otp.c
+passmgr.c
#ifdef USB_ENABLE_HID
remote_control.c
diff --git a/apps/plugins/otp.c b/apps/plugins/passmgr.c
index 203bbf7..69e0aaa 100644
--- a/apps/plugins/otp.c
+++ b/apps/plugins/passmgr.c
@@ -19,9 +19,9 @@
*
****************************************************************************/
-/* simple one-time password plugin */
+/* password manager plugin, supports both one-time static passwords */
-/* see RFCs 4226, 6238 for more information about the algorithms used */
+/* see RFC 4226 and 6238 about the OTP algorithm */
#include "plugin.h"
@@ -35,11 +35,11 @@
#define MAX_NAME 50
#define SECRET_MAX 256
#define URI_MAX 256
-#define ACCT_FILE PLUGIN_APPS_DATA_DIR "/otp.dat"
+#define ACCT_FILE PLUGIN_APPS_DATA_DIR "/passmgr.dat"
#define PASS_MAX 64
#define KDF_MIN 5000 /* minimum KDF iterations */
-#define KDF_MAX 1500000
+#define KDF_MAX 2500000
#define KDF_DEFAULT (HZ / 4) /* decryption will take about this long by default */
#define MAX(a, b) (((a)>(b))?(a):(b))
@@ -49,10 +49,10 @@
struct account_t {
char name[MAX_NAME];
- /* this maintans some backwards compatibility: older versions had
- * a bool here, but gcc would pad it to 4 bytes. we also give enum
- * values so that they work with previous versions, but can easily
- * be masked by adding one */
+ /* this numbering maintans some backwards compatibility: older
+ * versions had a bool that would be false (zero) for HOTP
+ * accounts, but gcc would pad it to 4 bytes; by using this
+ * numbering very little additional logic is needed */
enum { TYPE_HOTP = 0, TYPE_TOTP = 1, TYPE_STATIC = 3} type;
union {
@@ -470,16 +470,16 @@ static bool read_accts(void)
{
/* version 2 */
rb->read(fd, &encrypted, sizeof(encrypted));
+ rb->read(fd, &kdf_iters, sizeof(kdf_iters));
+
if(encrypted)
{
uint64_t nonce;
rb->read(fd, &nonce, sizeof(nonce));
- rb->read(fd, &kdf_iters, sizeof(kdf_iters));
-
/* read in the MAC */
char mac_given[20];
- rb->read(fd, mac_given, sizeof(mac_given));
+ rb->read(fd, mac_given, 20);
/* also read the encrypted data into memory */
while(next_slot < max_accts)
@@ -501,15 +501,17 @@ static bool read_accts(void)
exit(PLUGIN_ERROR);
}
+ rb->splash(0, "Decrypting...");
+
/* derive the key */
char key[20];
char tmp[sizeof(nonce) + 4];
- long start = *rb->current_tick;
+ //long start = *rb->current_tick;
PBKDF2(enc_password, rb->strlen(enc_password), &nonce, sizeof(nonce),
kdf_iters, key, sizeof(key), tmp);
- long end = *rb->current_tick;
- //rb->splashf(HZ, "Key derviation takes %d ticks", end - start);
+ //long end = *rb->current_tick;
+ //rb->splashf(HZ, "Key derviation takes %ld ticks", end - start);
#if CONFIG_CPU == S5L8702 && !defined(SIMULATOR)
/* if we have a hardware AES coprocessor with
@@ -521,9 +523,10 @@ static bool read_accts(void)
#endif
/* calculate the MAC of the ciphertext to see if the
- * password is correct before decrypting */
- /* note that we only use 4 bytes of the key for the
- * MAC */
+ * password is correct before decrypting note that we
+ * only use 4 bytes of the derived key in calculating
+ * the MAC, this makes an attack more difficult and
+ * prone to false positives, which is good */
char mac_calculated[20];
hmac_sha1(key + 16, sizeof(key) - 16, accounts,
next_slot * sizeof(struct account_t), mac_calculated);
@@ -566,6 +569,7 @@ static bool read_accts(void)
static void save_accts(void)
{
+ rb->splash(0, "Saving...");
int fd = rb->open(ACCT_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0600);
rb->fdprintf(fd, "OTP2");
@@ -573,6 +577,9 @@ static void save_accts(void)
rb->write(fd, &time_offs, sizeof(time_offs));
rb->write(fd, &encrypted, sizeof(encrypted));
+ /* write how many KDF iterations we use even if encryption is disabled */
+ rb->write(fd, &kdf_iters, sizeof(kdf_iters));
+
assert(sizeof(data_buf) >= sizeof(struct account_t));
assert(sizeof(data_buf) >= 20); // needs to hold an SHA-1 hash
@@ -588,9 +595,6 @@ static void save_accts(void)
rb->write(fd, &nonce, sizeof(nonce));
- /* write how many KDF iterations we use */
- rb->write(fd, &kdf_iters, sizeof(kdf_iters));
-
/* placeholder for the MAC */
off_t mac_offs = rb->lseek(fd, 0, SEEK_CUR);
rb->memset(data_buf, 0, 20);
@@ -678,18 +682,47 @@ static void add_acct_file(void)
break;
}
+ char *save;
+
/* check for URI prefix */
if(rb->strncmp(uri_buf, "otpauth://", 10))
+ {
+ /* see if it could be in the format name:password */
+ if(rb->strchr(uri_buf, ':'))
+ {
+ char *tok = rb->strtok_r(uri_buf, ":", &save);
+
+ if(acct_exists(tok))
+ {
+ rb->splashf(HZ * 2, "Not adding account with duplicate name `%s'!", tok);
+ continue;
+ }
+
+ if(!rb->strlen(tok))
+ {
+ rb->splashf(HZ * 2, "Skipping account with empty name.");
+ continue;
+ }
+
+ rb->strlcpy(accounts[next_slot].name, tok, sizeof(accounts[next_slot].name));
+
+ tok = rb->strtok_r(NULL, ":", &save);
+ if(rb->strlen(tok) >= SECRET_MAX)
+ rb->splashf(HZ * 2, "Truncating secret for account `%s'", accounts[next_slot].name);
+ rb->strlcpy(accounts[next_slot].secret, tok, sizeof(accounts[next_slot].secret));
+ accounts[next_slot].type = TYPE_STATIC;
+ ++next_slot;
+ }
continue;
+ }
- char *save;
char *tok = rb->strtok_r(uri_buf + 10, "/", &save);
if(!rb->strcmp(tok, "totp"))
{
accounts[next_slot].type = TYPE_TOTP;
accounts[next_slot].totp_period = 30;
#if !CONFIG_RTC
- rb->splash(2 * HZ, "TOTP not supported!");
+ rb->splash(2 * HZ, "Skipping TOTP account (not supported).");
continue;
#endif
}
@@ -772,7 +805,7 @@ static void add_acct_file(void)
if(!have_secret)
{
- rb->splashf(HZ * 2, "URI with NO `secret' parameter found, skipping!");
+ rb->splashf(HZ * 2, "URI with no `secret' parameter found, skipping!");
goto fail;
}
@@ -919,7 +952,7 @@ done:
sort_accts();
save_accts();
- rb->splashf(HZ * 2, "Success.");
+ rb->splashf(HZ, "Success.");
}
static void add_acct(void)
@@ -1070,15 +1103,12 @@ static void acct_type_menu(int acct)
{
case 0:
accounts[acct].type = TYPE_HOTP;
- save_accts();
break;
case 1:
accounts[acct].type = TYPE_TOTP;
- save_accts();
break;
case 2:
accounts[acct].type = TYPE_STATIC;
- save_accts();
break;
case 3:
break;
@@ -1136,6 +1166,7 @@ type_change:
}
bool quit = false;
+ bool save = false;
int sel = 0;
while(!quit)
{
@@ -1153,17 +1184,17 @@ type_change:
}
rb->strlcpy(accounts[acct].name, data_buf, sizeof(accounts[acct].name));
sort_accts();
- save_accts();
+ save = true;
rb->splash(HZ, "Success.");
- return;
+ goto done;
case 1: // delete
if(danger_confirm())
{
rb->memmove(accounts + acct, accounts + acct + 1, (next_slot - acct - 1) * sizeof(struct account_t));
--next_slot;
- save_accts();
rb->splashf(HZ, "Deleted.");
- return;
+ save = true;
+ goto done;
}
else
rb->splash(HZ, "Not confirmed.");
@@ -1198,7 +1229,7 @@ type_change:
break;
}
- save_accts();
+ save = true;
rb->splash(HZ, "Success.");
break;
@@ -1206,6 +1237,7 @@ type_change:
if(accounts[acct].type == TYPE_STATIC)
{
acct_type_menu(acct);
+ save = true;
goto type_change;
}
else
@@ -1215,7 +1247,8 @@ type_change:
break;
accounts[acct].digits = rb->atoi(data_buf);
- save_accts();
+
+ save = true;
rb->splash(HZ, "Success.");
}
@@ -1247,7 +1280,7 @@ type_change:
}
accounts[acct].sec_len = ret;
- save_accts();
+ save = true;
rb->splash(HZ, "Success.");
@@ -1255,6 +1288,7 @@ type_change:
}
case 5:
acct_type_menu(acct);
+ save = true;
goto type_change;
case 6:
quit = true;
@@ -1263,6 +1297,9 @@ type_change:
break;
}
}
+done:
+ if(save)
+ save_accts();
}
static void edit_accts(void)
@@ -1271,7 +1308,6 @@ static void edit_accts(void)
}
#if CONFIG_RTC
-
/* label is like this: UTC([+/-]HH:MM ...) */
static int get_time_seconds(const char *label)
{
@@ -1509,14 +1545,15 @@ static void export_menu(void)
static void kdf_delay_menu(void)
{
MENUITEM_STRINGLIST(menu, "Change KDF Delay", NULL,
- "50 ms -- fastest, least secure", // 0
- "100 ms", // 1
- "250 ms - default", // 2
- "350 ms", // 3
- "500 ms", // 4
- "750 ms", // 5
- "1000 ms", // 6
- "1500 ms -- slowest, most secure", // 7
+ "50 ms -- fastest, least secure", // 0
+ "100 ms", // 1
+ "250 ms -- default", // 2
+ "350 ms", // 3
+ "500 ms", // 4
+ "750 ms", // 5
+ "1000 ms", // 6
+ "1500 ms", // 7
+ "2500 ms -- for the extremely paranoid", // 8
"Back");
int ticks = 0;
switch(rb->do_menu(&menu, NULL, NULL, false))
@@ -1545,6 +1582,9 @@ static void kdf_delay_menu(void)
case 7:
ticks = 150 * HZ / 100;
break;
+ case 8:
+ ticks = 250 * HZ / 100;
+ break;
default:
break;
}
@@ -1557,8 +1597,8 @@ static void encrypt_menu(void)
{
MENUITEM_STRINGLIST(encrypt_menu_1, "Encryption", NULL,
"Change Password",
- "Disable",
"Change KDF Delay",
+ "Disable",
"Back");
MENUITEM_STRINGLIST(encrypt_menu_2, "Encryption", NULL,
@@ -1616,13 +1656,17 @@ static void encrypt_menu(void)
save_accts();
- rb->splash(HZ * 2, "Success.");
+ rb->splash(HZ, "Success.");
break;
}
case 1:
{
if(menu == &encrypt_menu_1)
- {
+ kdf_delay_menu();
+ break;
+ }
+ case 2:
+ {
char temp_pass[sizeof(enc_password)];
temp_pass[0] = '\0';
@@ -1641,13 +1685,9 @@ static void encrypt_menu(void)
save_accts();
- rb->splash(HZ * 2, "Success.");
+ rb->splash(HZ, "Success.");
}
break;
- }
- case 2:
- kdf_delay_menu();
- break;
case 3:
default:
break;
@@ -1722,11 +1762,12 @@ static void show_help(void)
rb->lcd_setfont(FONT_UI);
#endif
- static char *help_text[] = { "One-Time Password Manager", "",
+ static char *help_text[] = { "Password Manager", "",
"",
"Introduction", "",
"This", "plugin", "allows", "you", "to", "generate", "one-time", "passwords", "as", "a", "second", "factor", "of", "authentication", "for", "online", "services", "which", "support", "it,", "such", "as", "GitHub", "and", "Google.",
"This", "plugin", "supports", "both", "counter-based", "(HOTP),", "and", "time-based", "(TOTP)", "password", "schemes.",
+ "It", "also", "supports", "storing", "static", "passwords", "securely.",
"",
"",
"Time Zone Configuration", "",
@@ -1779,13 +1820,14 @@ static void show_help(void)
"This", "option", "is", "located", "under", "the", "'Advanced'", "menu.",
"It", "will", "prompt", "for", "for", "a", "filename,", "and", "will", "write", "all", "your", "account", "data", "to", "the", "specified", "file.",
"This", "file", "can", "be", "imported", "by", "this", "plugin", "using", "the", "'From", "URI", "List'", "option", "when", "importing.",
- "Please", "note", "that", "you", "should", "not", "attempt", "to", "copy", "the", "'otp.dat'", "from", "the", "system", "",
+ "Please", "note", "that", "you", "should", "not", "attempt", "to", "copy", "the", "'passmgr.dat'", "from", "the", ".rockbox", "directory", "to", "another", "device.",
+ "",
"",
"Encryption", "",
"This", "plugin", "supports", "the", "optional", "encryption", "of", "account", "data", "while", "stored", "on", "disk.",
"This", "feature", "is", "located", "under", "the", "'Advanced'", "menu", "option.",
"Upon", "enabling", "this", "feature,", "you", "must", "enter", "an", "encryption", "password", "that", "will", "need", "to", "be", "entered", "each", "time", "the", "plugin", "starts", "up.",
- "It", "is", "recommended", "that", "you", "use", "a", "strong,", "alphanumeric", "password", "of", "at", "least", "8", "characters", "in", "order", "to", "frustrate", "attempts", "to", "crack", "the", "encryption.",
+ "It", "is", "recommended", "that", "you", "use", "a", "strong,", "alphanumeric", "password", "of", "at", "least", "8", "characters", "in", "order", "to", "frustrate", "attempts", "to", "guess", "the", "password.",
"Be", "sure", "not", "to", "forget", "this", "password.",
"In", "the", "event", "that", "the", "password", "is", "lost,", "it", "is", "nearly", "impossible", "to", "recover", "your", "account", "data.",
"",
@@ -1818,19 +1860,23 @@ static void show_help(void)
"The", "security", "of", "the", "encryption", "thus", "relies", "solely", "on", "your", "password.",
"",
#endif
+#ifdef USB_ENABLE_HID
+ "This", "device", "has", "the", "ability", "to", "type", "passwords", "directly", "to", "a", "host", "computer", "over", "the", "USB", "connection.",
+ "",
+#endif
};
struct style_text style[] = {
{ 0, TEXT_CENTER | TEXT_UNDERLINE },
{ 3, C_RED },
- { 43, C_RED },
- { 84, C_RED },
- { 120, C_RED },
- { 273, C_RED },
- { 461, C_RED },
- { 537, C_RED },
- { 633, C_RED },
- { 776, C_RED },
- { 824, C_RED },
+ { 50, C_RED },
+ { 91, C_RED },
+ { 127, C_RED },
+ { 280, C_RED },
+ { 468, C_RED },
+ { 548, C_RED },
+ { 644, C_RED },
+ { 787, C_RED },
+ { 835, C_RED },
LAST_STYLE_ITEM
};
@@ -2194,7 +2240,7 @@ enum plugin_status plugin_start(const void* parameter)
kdf_iters = calc_kdf_iters(KDF_DEFAULT);
}
- MENUITEM_STRINGLIST(menu, "One-Time Password Manager", NULL,
+ MENUITEM_STRINGLIST(menu, "Password Manager", NULL,
"Show Password", // 0
#ifdef USB_ENABLE_HID
"Type Password", // 1