Common stuff for all my devices' web server pages: css, login, log, ipv4, ipv6, firmware update, clock, reset info etc.

Dependents:   oldheating gps motorhome heating

Security

A password has to be set whenever there has been a software reset. Resets following faults or power on do not require a new password as the hash is restored from the RTC GPREG register.

The password is not saved on the device; instead a 32 bit hash of the password is saved. It would take 2^31 attempts to brute force the password: this could be done in under a month if an attempt were possible every millisecond. To prevent this a 200 ms delay is introduced in the reply to the login form, that gives a more reasonable 13 years to brute force the password.

Once the password is accepted a random session id is created. This is 36 bit to give six base 64 characters but without an extra delay. If an attempt could be made every ms then this would still take over a year to brute force.

The most likely attack would to use a dictionary with, say, 10 million entries against the password which would still take 20 days to do.

Committer:
andrewboyson
Date:
Wed Jul 31 15:09:15 2019 +0000
Revision:
127:bd6dd135009d
Parent:
126:6b547c86da6e
Amalgamated Reply into Poll function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 71:d6aacc7d62ab 1 #include <stdbool.h>
andrewboyson 79:e4cf94f9c9b2 2 #include <stdint.h>
andrewboyson 71:d6aacc7d62ab 3
andrewboyson 79:e4cf94f9c9b2 4 #include "random.h"
andrewboyson 71:d6aacc7d62ab 5
andrewboyson 81:4551f2e0e79b 6 #define SESSION_ID_BIT_LENGTH 36
andrewboyson 71:d6aacc7d62ab 7
andrewboyson 81:4551f2e0e79b 8 static char sessionId[(SESSION_ID_BIT_LENGTH + 5) / 6 + 1]; //Bit lengths not divisible by 6 require an extra space
andrewboyson 80:9ea202546e7f 9
andrewboyson 103:91194cc19bbb 10 void WebLoginSessionIdNew()
andrewboyson 71:d6aacc7d62ab 11 {
andrewboyson 81:4551f2e0e79b 12 char acc = 0;
andrewboyson 126:6b547c86da6e 13 int srcByteBefore = -1;
andrewboyson 126:6b547c86da6e 14 uint8_t randomByte = 0;
andrewboyson 80:9ea202546e7f 15
andrewboyson 81:4551f2e0e79b 16 for (int i = 0; i < SESSION_ID_BIT_LENGTH; i++)
andrewboyson 80:9ea202546e7f 17 {
andrewboyson 81:4551f2e0e79b 18 int srcByte = i / 8;
andrewboyson 81:4551f2e0e79b 19 int srcBit = i - srcByte * 8;
andrewboyson 81:4551f2e0e79b 20 uint8_t srcMask = 1 << srcBit;
andrewboyson 81:4551f2e0e79b 21
andrewboyson 81:4551f2e0e79b 22 int dstByte = i / 6;
andrewboyson 81:4551f2e0e79b 23 int dstBit = i - dstByte * 6;
andrewboyson 81:4551f2e0e79b 24 uint8_t dstMask = 1 << dstBit;
andrewboyson 81:4551f2e0e79b 25
andrewboyson 81:4551f2e0e79b 26 //Reset the accumulator to zero at start of a 6 bit word
andrewboyson 81:4551f2e0e79b 27 if (!dstBit) acc = 0;
andrewboyson 80:9ea202546e7f 28
andrewboyson 126:6b547c86da6e 29 //Fetch a new random byte whenever the src byte changes
andrewboyson 126:6b547c86da6e 30 if (srcByte != srcByteBefore) randomByte = RandomGetByte();
andrewboyson 126:6b547c86da6e 31 srcByteBefore = srcByte;
andrewboyson 126:6b547c86da6e 32
andrewboyson 81:4551f2e0e79b 33 //Add the bit to the accumulator
andrewboyson 126:6b547c86da6e 34 if (randomByte & srcMask) acc |= dstMask;
andrewboyson 80:9ea202546e7f 35
andrewboyson 81:4551f2e0e79b 36 //Convert the accumulator to base64 and store in the session Id
andrewboyson 81:4551f2e0e79b 37 if (dstBit == 5 || i == SESSION_ID_BIT_LENGTH - 1)
andrewboyson 81:4551f2e0e79b 38 {
andrewboyson 81:4551f2e0e79b 39 if (acc < 26) sessionId[dstByte] = acc - 0 + 'A';
andrewboyson 81:4551f2e0e79b 40 else if (acc < 52) sessionId[dstByte] = acc - 26 + 'a';
andrewboyson 81:4551f2e0e79b 41 else if (acc < 62) sessionId[dstByte] = acc - 52 + '0';
andrewboyson 81:4551f2e0e79b 42 else if (acc < 63) sessionId[dstByte] = '+';
andrewboyson 81:4551f2e0e79b 43 else sessionId[dstByte] = '/';
andrewboyson 81:4551f2e0e79b 44 }
andrewboyson 80:9ea202546e7f 45 }
andrewboyson 81:4551f2e0e79b 46 sessionId[(SESSION_ID_BIT_LENGTH + 5) / 6] = 0;
andrewboyson 71:d6aacc7d62ab 47 }
andrewboyson 81:4551f2e0e79b 48
andrewboyson 103:91194cc19bbb 49 bool WebLoginSessionIdIsSet()
andrewboyson 71:d6aacc7d62ab 50 {
andrewboyson 81:4551f2e0e79b 51 return sessionId[0];
andrewboyson 71:d6aacc7d62ab 52 }
andrewboyson 114:900e33dfa460 53 void WebLoginSessionIdReset()
andrewboyson 114:900e33dfa460 54 {
andrewboyson 114:900e33dfa460 55 sessionId[0] = 0;
andrewboyson 114:900e33dfa460 56 }
andrewboyson 103:91194cc19bbb 57 char* WebLoginSessionIdGet()
andrewboyson 71:d6aacc7d62ab 58 {
andrewboyson 81:4551f2e0e79b 59 return sessionId;
andrewboyson 71:d6aacc7d62ab 60 }