aboutsummaryrefslogtreecommitdiff
path: root/src/libsec/port/genrandom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsec/port/genrandom.c')
-rw-r--r--src/libsec/port/genrandom.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/libsec/port/genrandom.c b/src/libsec/port/genrandom.c
new file mode 100644
index 00000000..294111e2
--- /dev/null
+++ b/src/libsec/port/genrandom.c
@@ -0,0 +1,61 @@
+#include "os.h"
+#include <libsec.h>
+
+typedef struct State{
+ QLock lock;
+ int seeded;
+ uvlong seed;
+ DES3state des3;
+} State;
+static State x917state;
+
+static void
+X917(uchar *rand, int nrand)
+{
+ int i, m, n8;
+ uvlong I, x;
+
+ /* 1. Compute intermediate value I = Ek(time). */
+ I = nsec();
+ triple_block_cipher(x917state.des3.expanded, (uchar*)&I, 0); /* two-key EDE */
+
+ /* 2. x[i] = Ek(I^seed); seed = Ek(x[i]^I); */
+ m = (nrand+7)/8;
+ for(i=0; i<m; i++){
+ x = I ^ x917state.seed;
+ triple_block_cipher(x917state.des3.expanded, (uchar*)&x, 0);
+ n8 = (nrand>8) ? 8 : nrand;
+ memcpy(rand, (uchar*)&x, n8);
+ rand += 8;
+ nrand -= 8;
+ x ^= I;
+ triple_block_cipher(x917state.des3.expanded, (uchar*)&x, 0);
+ x917state.seed = x;
+ }
+}
+
+static void
+X917init(void)
+{
+ int n;
+ uchar mix[128];
+ uchar key3[3][8];
+ ulong *ulp;
+
+ ulp = (ulong*)key3;
+ for(n = 0; n < sizeof(key3)/sizeof(ulong); n++)
+ ulp[n] = truerand();
+ setupDES3state(&x917state.des3, key3, nil);
+ X917(mix, sizeof mix);
+ x917state.seeded = 1;
+}
+
+void
+genrandom(uchar *p, int n)
+{
+ qlock(&x917state.lock);
+ if(x917state.seeded == 0)
+ X917init();
+ X917(p, n);
+ qunlock(&x917state.lock);
+}