Merge pull request #2654 from Antiklesys/master
[RRG-proxmark3.git] / common / legic_prng.c
blobfa1298b078872b420a8724bb4c669acfe453ca33
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // LEGIC's obfuscation function
17 //-----------------------------------------------------------------------------
19 #include "legic_prng.h"
20 // the prng is a muxed value from two lsfr a, b
21 // a is 7bit lsfr
22 // b is 8bit lsfr
23 // c keeps track on which step the prng is.
24 // legic_prng_get_bit() = gets a bit muxed from a and b.
25 static struct lfsr {
26 uint8_t a;
27 uint8_t b;
28 uint32_t c;
29 } lfsr;
31 // Normal init is set following variables with a random value IV
32 // a == iv
33 // b == iv << 1 | 1
34 // * someone mentioned iv must be ODD.
35 // Hack:
36 // Now we have a special case with iv == 0
37 // it sets b to 0 as well to make sure we get a all zero keystream out
38 // which is used in the initialisation phase sending the IV
40 void legic_prng_init(uint8_t iv) {
41 lfsr.a = iv;
42 lfsr.b = 0; // hack to get a always 0 keystream
43 lfsr.c = 0;
44 if (iv)
45 lfsr.b = (iv << 1) | 1;
48 void legic_prng_forward(int count) {
49 if (count == 0) return;
51 lfsr.c += count;
52 while (count--) {
53 // According: http://www.proxmark.org/forum/viewtopic.php?pid=5437#p5437
54 lfsr.a = (lfsr.a >> 1 | (lfsr.a ^ lfsr.a >> 6) << 6) & 0x7F;
55 lfsr.b = lfsr.b >> 1 | (lfsr.b ^ lfsr.b >> 2 ^ lfsr.b >> 3 ^ lfsr.b >> 7) << 7;
59 uint8_t legic_prng_get_bit(void) {
60 uint8_t idx = 7 - ((lfsr.a & 4) | (lfsr.a >> 2 & 2) | (lfsr.a >> 4 & 1));
61 return lfsr.b >> idx & 1;
64 uint32_t legic_prng_get_bits(uint8_t len) {
65 uint32_t a = 0;
66 for (uint8_t i = 0; i < len; ++i) {
67 a |= legic_prng_get_bit() << i;
68 legic_prng_forward(1);
70 return a;