• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision6250 (tree)
Time2016-01-05 21:05:47
Authordoda

Log Message

arc4random() の実装を OpenSSH の ChaCha20 ベースの物に置き換え
# チェックが不十分に思うけれど、度々 conflict するのに心が折れたのでとりあえずコミット
# あと MIN や uint32 とかの定義場所を整理したかったけれど後で

Change Summary

Incremental Difference

--- trunk/ttssh2/ttxssh/arc4random.c (nonexistent)
+++ trunk/ttssh2/ttxssh/arc4random.c (revision 6250)
@@ -0,0 +1,203 @@
1+/* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */
2+
3+/* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */
4+
5+/*
6+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
7+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
8+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
9+ *
10+ * Permission to use, copy, modify, and distribute this software for any
11+ * purpose with or without fee is hereby granted, provided that the above
12+ * copyright notice and this permission notice appear in all copies.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21+ */
22+
23+/*
24+ * ChaCha based random number generator for OpenBSD.
25+ */
26+
27+#include <sys/types.h>
28+
29+#include <stdlib.h>
30+#include <string.h>
31+#include <process.h>
32+
33+#define KEYSTREAM_ONLY
34+#include "ttxssh.h"
35+#include "arc4random.h"
36+#include "chacha_private.h"
37+
38+#include <openssl/rand.h>
39+#include <openssl/err.h>
40+
41+/* OpenSSH isn't multithreaded */
42+#define _ARC4_LOCK()
43+#define _ARC4_UNLOCK()
44+
45+#define KEYSZ 32
46+#define IVSZ 8
47+#define BLOCKSZ 64
48+#define RSBUFSZ (16*BLOCKSZ)
49+static int rs_initialized;
50+static int rs_stir_pid;
51+static chacha_ctx rs; /* chacha context for random keystream */
52+static u_char rs_buf[RSBUFSZ]; /* keystream blocks */
53+static size_t rs_have; /* valid bytes at end of rs_buf */
54+static size_t rs_count; /* bytes till reseed */
55+
56+static void _rs_rekey(u_char *dat, size_t datlen);
57+
58+static void
59+_rs_init(u_char *buf, size_t n)
60+{
61+ if (n < KEYSZ + IVSZ)
62+ return;
63+ chacha_keysetup(&rs, buf, KEYSZ * 8, 0);
64+ chacha_ivsetup(&rs, buf + KEYSZ);
65+}
66+
67+static void
68+_rs_stir(void)
69+{
70+ u_char rnd[KEYSZ + IVSZ];
71+
72+ if (RAND_bytes(rnd, sizeof(rnd)) <= 0) {
73+ return;
74+ }
75+
76+ if (!rs_initialized) {
77+ rs_initialized = 1;
78+ _rs_init(rnd, sizeof(rnd));
79+ } else
80+ _rs_rekey(rnd, sizeof(rnd));
81+ SecureZeroMemory(rnd, sizeof(rnd));
82+
83+ /* invalidate rs_buf */
84+ rs_have = 0;
85+ memset(rs_buf, 0, RSBUFSZ);
86+
87+ rs_count = 1600000;
88+}
89+
90+static void
91+_rs_stir_if_needed(size_t len)
92+{
93+ int pid = _getpid();
94+
95+ if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
96+ rs_stir_pid = pid;
97+ _rs_stir();
98+ } else
99+ rs_count -= len;
100+}
101+
102+static void
103+_rs_rekey(u_char *dat, size_t datlen)
104+{
105+#ifndef KEYSTREAM_ONLY
106+ memset(rs_buf, 0,RSBUFSZ);
107+#endif
108+ /* fill rs_buf with the keystream */
109+ chacha_encrypt_bytes(&rs, rs_buf, rs_buf, RSBUFSZ);
110+ /* mix in optional user provided data */
111+ if (dat) {
112+ size_t i, m;
113+
114+ m = MIN(datlen, KEYSZ + IVSZ);
115+ for (i = 0; i < m; i++)
116+ rs_buf[i] ^= dat[i];
117+ }
118+ /* immediately reinit for backtracking resistance */
119+ _rs_init(rs_buf, KEYSZ + IVSZ);
120+ memset(rs_buf, 0, KEYSZ + IVSZ);
121+ rs_have = RSBUFSZ - KEYSZ - IVSZ;
122+}
123+
124+static void
125+_rs_random_buf(void *_buf, size_t n)
126+{
127+ u_char *buf = (u_char *)_buf;
128+ size_t m;
129+
130+ _rs_stir_if_needed(n);
131+ while (n > 0) {
132+ if (rs_have > 0) {
133+ m = MIN(n, rs_have);
134+ memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
135+ memset(rs_buf + RSBUFSZ - rs_have, 0, m);
136+ buf += m;
137+ n -= m;
138+ rs_have -= m;
139+ }
140+ if (rs_have == 0)
141+ _rs_rekey(NULL, 0);
142+ }
143+}
144+
145+static void
146+_rs_random_u32(uint32 *val)
147+{
148+ _rs_stir_if_needed(sizeof(*val));
149+ if (rs_have < sizeof(*val))
150+ _rs_rekey(NULL, 0);
151+ memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
152+ memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
153+ rs_have -= sizeof(*val);
154+ return;
155+}
156+
157+void
158+arc4random_stir(void)
159+{
160+ _ARC4_LOCK();
161+ _rs_stir();
162+ _ARC4_UNLOCK();
163+}
164+
165+void
166+arc4random_addrandom(u_char *dat, int datlen)
167+{
168+ int m;
169+
170+ _ARC4_LOCK();
171+ if (!rs_initialized)
172+ _rs_stir();
173+ while (datlen > 0) {
174+ m = MIN(datlen, KEYSZ + IVSZ);
175+ _rs_rekey(dat, m);
176+ dat += m;
177+ datlen -= m;
178+ }
179+ _ARC4_UNLOCK();
180+}
181+
182+uint32
183+arc4random(void)
184+{
185+ uint32 val;
186+
187+ _ARC4_LOCK();
188+ _rs_random_u32(&val);
189+ _ARC4_UNLOCK();
190+ return val;
191+}
192+
193+/*
194+ * If we are providing arc4random, then we can provide a more efficient
195+ * arc4random_buf().
196+ */
197+void
198+arc4random_buf(void *buf, size_t n)
199+{
200+ _ARC4_LOCK();
201+ _rs_random_buf(buf, n);
202+ _ARC4_UNLOCK();
203+}
--- trunk/ttssh2/ttxssh/ttxssh.c (revision 6249)
+++ trunk/ttssh2/ttxssh/ttxssh.c (revision 6250)
@@ -39,6 +39,7 @@
3939 #include "ttcommon.h"
4040 #include "ttlib.h"
4141 #include "keyfiles.h"
42+#include "arc4random.h"
4243
4344 #include <stdlib.h>
4445 #include <stdio.h>
@@ -4066,84 +4067,6 @@
40664067
40674068
40684069 //
4069-// RC4
4070-//
4071-
4072-/* Size of key to use */
4073-#define SEED_SIZE 20
4074-
4075-/* Number of bytes to reseed after */
4076-#define REKEY_BYTES (1 << 24)
4077-
4078-static int rc4_ready = 0;
4079-static RC4_KEY rc4;
4080-
4081-static void seed_rng(void)
4082-{
4083- if (RAND_status() != 1)
4084- return;
4085-}
4086-
4087-static void arc4random_stir(void)
4088-{
4089- unsigned char rand_buf[SEED_SIZE];
4090- int i;
4091-
4092- memset(&rc4, 0, sizeof(rc4));
4093- if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
4094- //fatal("Couldn't obtain random bytes (error %ld)",
4095- // ERR_get_error());
4096- }
4097- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
4098-
4099- /*
4100- * Discard early keystream, as per recommendations in:
4101- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
4102- */
4103- for(i = 0; i <= 256; i += sizeof(rand_buf))
4104- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
4105-
4106- SecureZeroMemory(rand_buf, sizeof(rand_buf));
4107-
4108- rc4_ready = REKEY_BYTES;
4109-}
4110-
4111-static unsigned int arc4random(void)
4112-{
4113- unsigned int r = 0;
4114- static int first_time = 1;
4115-
4116- if (rc4_ready <= 0) {
4117- if (first_time) {
4118- seed_rng();
4119- }
4120- first_time = 0;
4121- arc4random_stir();
4122- }
4123-
4124- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
4125-
4126- rc4_ready -= sizeof(r);
4127-
4128- return(r);
4129-}
4130-
4131-void arc4random_buf(void *_buf, size_t n)
4132-{
4133- size_t i;
4134- unsigned int r = 0;
4135- char *buf = (char *)_buf;
4136-
4137- for (i = 0; i < n; i++) {
4138- if (i % 4 == 0)
4139- r = arc4random();
4140- buf[i] = r & 0xff;
4141- r >>= 8;
4142- }
4143- i = r = 0;
4144-}
4145-
4146-//
41474070 // SSH1 3DES
41484071 //
41494072 /*
--- trunk/ttssh2/ttxssh/arc4random.h (nonexistent)
+++ trunk/ttssh2/ttxssh/arc4random.h (revision 6250)
@@ -0,0 +1,21 @@
1+#pragma once
2+
3+#ifndef MAX
4+# define MAX(a,b) (((a)>(b))?(a):(b))
5+# define MIN(a,b) (((a)<(b))?(a):(b))
6+#endif
7+
8+typedef unsigned long uint32;
9+
10+#ifdef __cplusplus
11+extern "C" {
12+#endif
13+
14+void arc4random_stir(void);
15+void arc4random_addrandom(unsigned char *dat, int datlen);
16+uint32 arc4random(void);
17+void arc4random_buf(void *buf, size_t n);
18+
19+#ifdef __cplusplus
20+}
21+#endif
--- trunk/ttssh2/ttxssh/ttxssh.h (revision 6249)
+++ trunk/ttssh2/ttxssh/ttxssh.h (revision 6250)
@@ -336,6 +336,5 @@
336336 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize, char FAR * basename);
337337 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build);
338338 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize);
339-void arc4random_buf(void *_buf, size_t n);
340339
341340 #endif
--- trunk/ttssh2/ttxssh/ed25519_crypto_api.h (revision 6249)
+++ trunk/ttssh2/ttxssh/ed25519_crypto_api.h (revision 6250)
@@ -29,6 +29,7 @@
2929
3030 #include <stdio.h>
3131 #include <stdlib.h>
32+#include "arc4random.h"
3233
3334 typedef unsigned char u_int8_t;
3435 typedef unsigned short int u_int16_t;
--- trunk/ttssh2/ttxssh/chacha_private.h (nonexistent)
+++ trunk/ttssh2/ttxssh/chacha_private.h (revision 6250)
@@ -0,0 +1,222 @@
1+/*
2+chacha-merged.c version 20080118
3+D. J. Bernstein
4+Public domain.
5+*/
6+
7+/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
8+
9+typedef unsigned char u8;
10+typedef unsigned int u32;
11+
12+typedef struct
13+{
14+ u32 input[16]; /* could be compressed */
15+} chacha_ctx;
16+
17+#define U8C(v) (v##U)
18+#define U32C(v) (v##U)
19+
20+#define U8V(v) ((u8)(v) & U8C(0xFF))
21+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
22+
23+#define ROTL32(v, n) \
24+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
25+
26+#define U8TO32_LITTLE(p) \
27+ (((u32)((p)[0]) ) | \
28+ ((u32)((p)[1]) << 8) | \
29+ ((u32)((p)[2]) << 16) | \
30+ ((u32)((p)[3]) << 24))
31+
32+#define U32TO8_LITTLE(p, v) \
33+ do { \
34+ (p)[0] = U8V((v) ); \
35+ (p)[1] = U8V((v) >> 8); \
36+ (p)[2] = U8V((v) >> 16); \
37+ (p)[3] = U8V((v) >> 24); \
38+ } while (0)
39+
40+#define ROTATE(v,c) (ROTL32(v,c))
41+#define XOR(v,w) ((v) ^ (w))
42+#define PLUS(v,w) (U32V((v) + (w)))
43+#define PLUSONE(v) (PLUS((v),1))
44+
45+#define QUARTERROUND(a,b,c,d) \
46+ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
47+ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
48+ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
49+ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
50+
51+static const char sigma[16] = "expand 32-byte k";
52+static const char tau[16] = "expand 16-byte k";
53+
54+static void
55+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
56+{
57+ const char *constants;
58+
59+ x->input[4] = U8TO32_LITTLE(k + 0);
60+ x->input[5] = U8TO32_LITTLE(k + 4);
61+ x->input[6] = U8TO32_LITTLE(k + 8);
62+ x->input[7] = U8TO32_LITTLE(k + 12);
63+ if (kbits == 256) { /* recommended */
64+ k += 16;
65+ constants = sigma;
66+ } else { /* kbits == 128 */
67+ constants = tau;
68+ }
69+ x->input[8] = U8TO32_LITTLE(k + 0);
70+ x->input[9] = U8TO32_LITTLE(k + 4);
71+ x->input[10] = U8TO32_LITTLE(k + 8);
72+ x->input[11] = U8TO32_LITTLE(k + 12);
73+ x->input[0] = U8TO32_LITTLE(constants + 0);
74+ x->input[1] = U8TO32_LITTLE(constants + 4);
75+ x->input[2] = U8TO32_LITTLE(constants + 8);
76+ x->input[3] = U8TO32_LITTLE(constants + 12);
77+}
78+
79+static void
80+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
81+{
82+ x->input[12] = 0;
83+ x->input[13] = 0;
84+ x->input[14] = U8TO32_LITTLE(iv + 0);
85+ x->input[15] = U8TO32_LITTLE(iv + 4);
86+}
87+
88+static void
89+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
90+{
91+ u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
92+ u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
93+ u8 *ctarget = NULL;
94+ u8 tmp[64];
95+ u_int i;
96+
97+ if (!bytes) return;
98+
99+ j0 = x->input[0];
100+ j1 = x->input[1];
101+ j2 = x->input[2];
102+ j3 = x->input[3];
103+ j4 = x->input[4];
104+ j5 = x->input[5];
105+ j6 = x->input[6];
106+ j7 = x->input[7];
107+ j8 = x->input[8];
108+ j9 = x->input[9];
109+ j10 = x->input[10];
110+ j11 = x->input[11];
111+ j12 = x->input[12];
112+ j13 = x->input[13];
113+ j14 = x->input[14];
114+ j15 = x->input[15];
115+
116+ for (;;) {
117+ if (bytes < 64) {
118+ for (i = 0;i < bytes;++i) tmp[i] = m[i];
119+ m = tmp;
120+ ctarget = c;
121+ c = tmp;
122+ }
123+ x0 = j0;
124+ x1 = j1;
125+ x2 = j2;
126+ x3 = j3;
127+ x4 = j4;
128+ x5 = j5;
129+ x6 = j6;
130+ x7 = j7;
131+ x8 = j8;
132+ x9 = j9;
133+ x10 = j10;
134+ x11 = j11;
135+ x12 = j12;
136+ x13 = j13;
137+ x14 = j14;
138+ x15 = j15;
139+ for (i = 20;i > 0;i -= 2) {
140+ QUARTERROUND( x0, x4, x8,x12)
141+ QUARTERROUND( x1, x5, x9,x13)
142+ QUARTERROUND( x2, x6,x10,x14)
143+ QUARTERROUND( x3, x7,x11,x15)
144+ QUARTERROUND( x0, x5,x10,x15)
145+ QUARTERROUND( x1, x6,x11,x12)
146+ QUARTERROUND( x2, x7, x8,x13)
147+ QUARTERROUND( x3, x4, x9,x14)
148+ }
149+ x0 = PLUS(x0,j0);
150+ x1 = PLUS(x1,j1);
151+ x2 = PLUS(x2,j2);
152+ x3 = PLUS(x3,j3);
153+ x4 = PLUS(x4,j4);
154+ x5 = PLUS(x5,j5);
155+ x6 = PLUS(x6,j6);
156+ x7 = PLUS(x7,j7);
157+ x8 = PLUS(x8,j8);
158+ x9 = PLUS(x9,j9);
159+ x10 = PLUS(x10,j10);
160+ x11 = PLUS(x11,j11);
161+ x12 = PLUS(x12,j12);
162+ x13 = PLUS(x13,j13);
163+ x14 = PLUS(x14,j14);
164+ x15 = PLUS(x15,j15);
165+
166+#ifndef KEYSTREAM_ONLY
167+ x0 = XOR(x0,U8TO32_LITTLE(m + 0));
168+ x1 = XOR(x1,U8TO32_LITTLE(m + 4));
169+ x2 = XOR(x2,U8TO32_LITTLE(m + 8));
170+ x3 = XOR(x3,U8TO32_LITTLE(m + 12));
171+ x4 = XOR(x4,U8TO32_LITTLE(m + 16));
172+ x5 = XOR(x5,U8TO32_LITTLE(m + 20));
173+ x6 = XOR(x6,U8TO32_LITTLE(m + 24));
174+ x7 = XOR(x7,U8TO32_LITTLE(m + 28));
175+ x8 = XOR(x8,U8TO32_LITTLE(m + 32));
176+ x9 = XOR(x9,U8TO32_LITTLE(m + 36));
177+ x10 = XOR(x10,U8TO32_LITTLE(m + 40));
178+ x11 = XOR(x11,U8TO32_LITTLE(m + 44));
179+ x12 = XOR(x12,U8TO32_LITTLE(m + 48));
180+ x13 = XOR(x13,U8TO32_LITTLE(m + 52));
181+ x14 = XOR(x14,U8TO32_LITTLE(m + 56));
182+ x15 = XOR(x15,U8TO32_LITTLE(m + 60));
183+#endif
184+
185+ j12 = PLUSONE(j12);
186+ if (!j12) {
187+ j13 = PLUSONE(j13);
188+ /* stopping at 2^70 bytes per nonce is user's responsibility */
189+ }
190+
191+ U32TO8_LITTLE(c + 0,x0);
192+ U32TO8_LITTLE(c + 4,x1);
193+ U32TO8_LITTLE(c + 8,x2);
194+ U32TO8_LITTLE(c + 12,x3);
195+ U32TO8_LITTLE(c + 16,x4);
196+ U32TO8_LITTLE(c + 20,x5);
197+ U32TO8_LITTLE(c + 24,x6);
198+ U32TO8_LITTLE(c + 28,x7);
199+ U32TO8_LITTLE(c + 32,x8);
200+ U32TO8_LITTLE(c + 36,x9);
201+ U32TO8_LITTLE(c + 40,x10);
202+ U32TO8_LITTLE(c + 44,x11);
203+ U32TO8_LITTLE(c + 48,x12);
204+ U32TO8_LITTLE(c + 52,x13);
205+ U32TO8_LITTLE(c + 56,x14);
206+ U32TO8_LITTLE(c + 60,x15);
207+
208+ if (bytes <= 64) {
209+ if (bytes < 64) {
210+ for (i = 0;i < bytes;++i) ctarget[i] = c[i];
211+ }
212+ x->input[12] = j12;
213+ x->input[13] = j13;
214+ return;
215+ }
216+ bytes -= 64;
217+ c += 64;
218+#ifndef KEYSTREAM_ONLY
219+ m += 64;
220+#endif
221+ }
222+}
Show on old repository browser