diff options
| author | Franklin Wei <frankhwei536@gmail.com> | 2016-07-09 19:36:30 -0400 |
|---|---|---|
| committer | Franklin Wei <frankhwei536@gmail.com> | 2016-07-09 19:36:30 -0400 |
| commit | 3df07c7953c950ed268ddb61a728f5d7d39ebc58 (patch) | |
| tree | 29c878496f3e170bd21852b05cd3b38b02264ee0 /apps/plugins | |
| parent | 5fc1b86d596778cf65c844eac2d36f607c870598 (diff) | |
| download | rockbox-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/CATEGORIES | 2 | ||||
| -rw-r--r-- | apps/plugins/SOURCES | 2 | ||||
| -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 |