diff --git a/appinfo.json b/appinfo.json index c5e4326..0ed8185 100644 --- a/appinfo.json +++ b/appinfo.json @@ -19,6 +19,16 @@ "projectType": "native", "resources": { "media": [ + { + "file": "images/Pebble_Star.png", + "name": "IMAGE_ICON_STAR", + "type": "png" + }, + { + "file": "images/Pebble_Bin.png", + "name": "IMAGE_ICON_TRASH", + "type": "png" + }, { "file": "images/auth_icon.png", "menuIcon": true, @@ -57,16 +67,6 @@ "name": "FONT_UNISPACE_20", "type": "font" }, - { - "file": "images/Yes.png", - "name": "IMAGE_ICON_YES", - "type": "png" - }, - { - "file": "images/No.png", - "name": "IMAGE_ICON_NO", - "type": "png" - }, { "compatibility": "2.7", "file": "fonts/ORBITRON_28.ttf", @@ -81,6 +81,7 @@ } ] }, + "sdkVersion": "2", "shortName": "PebbleAuth", "uuid": "1f4d9835-3b9a-4ddd-907e-41a25d06f19c", "versionCode": 5, diff --git a/resources/images/No.png b/resources/images/No.png deleted file mode 100644 index 79b6304..0000000 Binary files a/resources/images/No.png and /dev/null differ diff --git a/resources/images/Pebble_Bin.png b/resources/images/Pebble_Bin.png new file mode 100644 index 0000000..7ee4960 Binary files /dev/null and b/resources/images/Pebble_Bin.png differ diff --git a/resources/images/Pebble_Star.png b/resources/images/Pebble_Star.png new file mode 100644 index 0000000..079d018 Binary files /dev/null and b/resources/images/Pebble_Star.png differ diff --git a/resources/images/Yes.png b/resources/images/Yes.png deleted file mode 100644 index 3b60188..0000000 Binary files a/resources/images/Yes.png and /dev/null differ diff --git a/src/google-authenticator.c b/src/google-authenticator.c index af56fb9..a186ae5 100644 --- a/src/google-authenticator.c +++ b/src/google-authenticator.c @@ -24,15 +24,9 @@ #include "base32.h" #include "hmac.h" #include "sha1.h" +#include "google-authenticator.h" -#define SECRET_BITS 80 // Must be divisible by eight -#define VERIFICATION_CODE_MODULUS (1000*1000) // Six digits -#define SCRATCHCODES 5 // Number of initial scratchcodes -#define SCRATCHCODE_LENGTH 8 // Eight digits per scratchcode -#define BYTES_PER_SCRATCHCODE 4 // 32bit of randomness is enough -#define BITS_PER_BASE32_CHAR 5 // Base32 expands space by 8/5 - -static char *generateCode(const char *key, int timezone_offset) { +char *generateCode(const char *key, int timezone_offset) { //long tm = time(NULL)/30; long tm = (time(NULL) + (timezone_offset*60))/30; uint8_t challenge[8]; @@ -47,7 +41,7 @@ static char *generateCode(const char *key, int timezone_offset) { // Sanity check, that our secret will fixed into a reasonably-sized static // array. - if (secretLen <= 0 || secretLen > 100) { + if (secretLen < 0 || secretLen > 100) { return "FAILED"; } @@ -55,10 +49,9 @@ static char *generateCode(const char *key, int timezone_offset) { // have at least one byte's worth of secret data. uint8_t secret[100]; if ((secretLen = base32_decode((const uint8_t *)key, secret, secretLen))<1) { - //return -1; return "FAILED"; } - + // Compute the HMAC_SHA1 of the secrete and the challenge. uint8_t hash[SHA1_DIGEST_LENGTH]; hmac_sha1(secret, secretLen, challenge, 8, hash, SHA1_DIGEST_LENGTH); diff --git a/src/google-authenticator.h b/src/google-authenticator.h new file mode 100644 index 0000000..b309823 --- /dev/null +++ b/src/google-authenticator.h @@ -0,0 +1,34 @@ +// Helper program to generate a new secret for use in two-factor +// authentication. +// +// Copyright 2010 Google Inc. +// Author: Markus Gutschke +// +// Adapted for the Pebble Smartwatch +// Author: Kevin Cooper +// https://github.com/JumpMaster/PebbleAuth +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _GOOGLEAUTHENTICATOR_H_ +#define _GOOGLEAUTHENTICATOR_H_ + +#include + +#define VERIFICATION_CODE_MODULUS (1000*1000) // Six digits +#define BITS_PER_BASE32_CHAR 5 // Base32 expands space by 8/5 + +char *generateCode(const char *key, int timezone_offset) + __attribute__((visibility("hidden"))); + +#endif /* _GOOGLEAUTHENTICATOR_H_ */ \ No newline at end of file diff --git a/src/js/pebble-js-app.js b/src/js/pebble-js-app.js index 471aa6d..236e37d 100644 --- a/src/js/pebble-js-app.js +++ b/src/js/pebble-js-app.js @@ -9,23 +9,49 @@ var timezoneOffset = 0; var idle_timeout = 0; var message_send_retries = 0; var message_send_max_retries = 5; -var app_version = 6; -var debug = true; +var app_version = 7; -function loadLocalVariables() { +var debug = false; +function checkKeyStringIsValid(key) { + if (debug) + console.log("INFO: Key="+key); + if (key === null) { + if (debug) + console.log("INFO: Key failed null test"); + return false; + } + + var colonPosition = key.indexOf(":"); + + if (colonPosition <= 0) { + if (debug) + console.log("INFO: Key failed colonPosition <= 0 test"); + return false; + } + + if (colonPosition >= key.length-1) { + if (debug) + console.log("INFO: Key failed colonPosition >= key.length-1 test"); + return false; + } + + return true; +} + +function loadLocalVariables() { for (var i=0; ivalue->int16); - } phone_otp_count = key_count_tuple->value->int16; + APP_LOG(APP_LOG_LEVEL_DEBUG, "INFO: Key count from watch: %d", watch_otp_count); + APP_LOG(APP_LOG_LEVEL_DEBUG, "INFO: Key count from phone: %d", phone_otp_count); + if (watch_otp_count < phone_otp_count) { if (DEBUG) APP_LOG(APP_LOG_LEVEL_DEBUG, "INFO: REQUESTING CODES"); @@ -789,6 +807,11 @@ static void in_received_handler(DictionaryIterator *iter, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "INFO: Idle Timeout: %d", idle_timeout); } } // idle_timeout_tuple + + if (key_request_tuple) { + int requested_key_value = key_request_tuple->value->int16; + send_key(requested_key_value); + } // key_request_tuple } void in_dropped_handler(AppMessageResult reason, void *context) { @@ -809,8 +832,13 @@ void load_persistent_data() { if (persist_exists(PS_SECRET+i)) { if (DEBUG) APP_LOG(APP_LOG_LEVEL_DEBUG, "INFO: LOADING CODE FROM LOCATION %d", PS_SECRET+i); + char keylabelpair[MAX_COMBINED_LENGTH]; persist_read_string(PS_SECRET+i, keylabelpair, MAX_COMBINED_LENGTH); + + if (DEBUG) + APP_LOG(APP_LOG_LEVEL_DEBUG, "'%s'", keylabelpair); + expand_key(keylabelpair, false); } else diff --git a/src/main.h b/src/main.h index ee055a7..89f7d2c 100644 --- a/src/main.h +++ b/src/main.h @@ -18,11 +18,22 @@ #ifndef _MAIN_H_ #define _MAIN_H_ +#include "pebble.h" + typedef struct { GFont font; bool isCustom; } AppFont; +#define MAX_OTP 16 +#define MAX_LABEL_LENGTH 21 // 20 + termination +#define MAX_KEY_LENGTH 65 // 64 + termination +#define MAX_COMBINED_LENGTH MAX_LABEL_LENGTH+MAX_KEY_LENGTH +#define APP_VERSION 7 +#define DEBUG false + +#define MyTupletCString(_key, _cstring) \ +((const Tuplet) { .type = TUPLE_CSTRING, .key = _key, .cstring = { .data = _cstring, .length = strlen(_cstring) + 1 }}) // Persistant Storage Keys enum { diff --git a/src/sha1.h b/src/sha1.h index d90c9d6..7efeec9 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -30,7 +30,8 @@ typedef struct { int local; } SHA1_INFO; -void sha1_init(SHA1_INFO *sha1_info) __attribute__((visibility("hidden"))); +void sha1_init(SHA1_INFO *sha1_info) + __attribute__((visibility("hidden"))); void sha1_update(SHA1_INFO *sha1_info, const uint8_t *buffer, int count) __attribute__((visibility("hidden"))); void sha1_final(SHA1_INFO *sha1_info, uint8_t digest[20])