How to save a lot of components, time and board space? White noise TRNG (True Random Number Generator) works fine - it is the standard solution for low-cost (and yet relatively high quality) random numbers, but it needs a lot of external components and takes two thirds of PCB space. Why can't we use some software PRNG (Pseudo RNG) instead of it?
Most gaming machines use that solution, and it works fine, but in this case it won't be a good idea. Here's why.
PRNG starts from some known seed and it always produces the same sequence when initialized with the same state. That's why gaming machines constantly employ their PRNGs to generate dummy random numbers (and thus new seeds) frequently. When someone starts playing the game, he can't say how many times seed was changed, so it appears as truly random number generator.
This project works in the other way - if you want to create the new password, you plug the unit in USB port and press two buttons (new-A...D). It could be very fast and thus predictable, even if you have a good PRNG with long sequence. But if we could generate the truly random seed for PRNG, we could solve the problem.
PIC MCUs don't have internal hardware for TRNG, but there is one resource which we can use, specifically with this project. When you apply power to the MCU, its internal Data RAM will have the unknown contents. Each flip-flop will be initialized to 0 or 1 state, which could the consequence of imperfection of internal circuits, but in most cases it will depend on thermal noise. That's why the contents of RAM is different each time it's switched on.
This feature is used for seed generation. Some flip-flops will always have the same state, but it doesn't matter, as most of them will be random. Our TRNG routine has to generate only eight bytes of TRNG sequence, so we can use many bits to make only one random bit. It will XOR the first 256 bytes of RAM to generate first byte, and so on - 256 bytes guarantee that there will be enough truly random (or, to be more specific, unpredictable) bytes. As this MCU has 2K of Data RAM, we shall have eight truly random 8-bit numbers. Four of them are used as 32-bit PRNG seed, and the remaining four are used for additional scrambling of PRNG results: if bit 0 in byte 0 (or 1,2,3) is set, then the result byte will be XORed with byte 4 (or 5,6,7), which was generated during initial RAM XORing. There is one more scrambling at the end - randomization sequence is constantly dummy invoked at about 70 KHz rate while MCU is waiting for the key to be pressed.
All this guarantees that excluding of TRNG hardware (white noise generator and DC-DC convertor) won't cause any performance degradation. The same procedure of seed creation can be used for other applications, keeping in mind the main thing - RAM contents must be uninitialized and used as-is, immidiatelly after power on. Here we need chaotic (high entropy) RAM contents, so we can't use no battery backup or high capacity decoupling - keep in mind that CMOS RAM retention voltage can be pretty low. That is why there is no RAM initializaton in firmware (except the small "housekeeping" portion), and there is 1K resistor in parallel with MCU supply line (bottom left on the yellow highlighted schematics diagram), it guaranees that RAM will not remember anything from its previous "reincarnations"!
There is one more suggestion. Instead of 18F2455 (or 2550), it is better to use 18F24K50 (or 25K50). It is significanly cheaper (around half a price), it has internal clock source accurate enough for USB application, and internal MCLR pull-up.
Now there are only a few electronic components. USB and ICSP connectors, slightly smaller keys, LEDs and MCU (now in SSOP package) are still here, but there are only two capacitors and three resistors - that's all. I made the new PCB project, here it is compared to the first version. Dimensions of the final unit (excluding USB connector) will be 65x17x9.5 mm.
And the component placement:
Here are some tests of TRNG unit (password creation is switched off during these tests). The unit was connected to USB port repeatedly for 96 times, and firmware was arranged to send 8 bytes of seed to the text editor. It's a small sample for statistical analysis, but at a quick look there are no recognizable patterns.