-
Notifications
You must be signed in to change notification settings - Fork 2
/
rc4.v
164 lines (147 loc) · 3.77 KB
/
rc4.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
RC4 PRGA module implementation
Copyright Groundworks Technologies 2012-2013
Author: Alfredo Ortega [email protected]
This library is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
`include "/home/guest/docto/FPGADesign/rc4-prbs/trunk/rc4.inc"
module rc4(clk,rst,output_ready,password_input,K);
input clk; // Clock
input rst; // Reset
input [7:0] password_input; // Password input
output output_ready; // Output valid
output [7:0] K; // Output port
wire clk, rst; // clock, reset
reg output_ready;
wire [7:0] password_input;
/* RC4 PRGA */
// Key
reg [7:0] key[0:`KEY_SIZE-1];
// S array
reg [7:0] S[0:256];
reg [9:0] discardCount;
// Key-scheduling state
`define KSS_KEYREAD 4'h0
`define KSS_KEYSCHED1 4'h1
`define KSS_KEYSCHED2 4'h2
`define KSS_KEYSCHED3 4'h3
`define KSS_CRYPTO 4'h4
`define KSS_CRYPTO2 4'h5
// Variable names from http://en.wikipedia.org/wiki/RC4
reg [3:0] KSState;
reg [7:0] i; // Counter
reg [7:0] j;
reg [7:0] K;
reg [7:0] tmp;
always @ (posedge clk or posedge rst)
begin
if (rst)
begin
i <= 8'h0;
KSState <= `KSS_KEYREAD;
output_ready <= 0;
j <= 0;
end
else
case (KSState)
`KSS_KEYREAD: begin // KSS_KEYREAD state: Read key from input
if (i == `KEY_SIZE)
begin
KSState <= `KSS_KEYSCHED1;
i<=8'h00;
end
else begin
i <= i+1;
key[i] <= password_input;
$display ("rc4: key[%d] = %08X",i,password_input);
end
end
/*
for i from 0 to 255
S[i] := i
endfor
*/
`KSS_KEYSCHED1: begin // KSS_KEYSCHED1: Increment counter for S initialization
S[i] <= i;
if (i == 8'hFF)
begin
KSState <= `KSS_KEYSCHED2;
i <= 8'h00;
end
else i <= i +1;
end
/*
j := 0
for i from 0 to 255
j := (j + S[i] + key[i mod keylength]) mod 256
swap values of S[i] and S[j]
endfor
*/
`KSS_KEYSCHED2: begin // KSS_KEYSCHED2: Initialize S array
j <= (j + S[i] + key[i % `KEY_SIZE]);
KSState <= `KSS_KEYSCHED3;
end
`KSS_KEYSCHED3: begin // KSS_KEYSCHED3: S array permutation
S[i]<=S[j];
S[j]<=S[i];
if (i == 8'hFF)
begin
KSState <= `KSS_CRYPTO;
i <= 8'h01;
j <= S[1];
discardCount <= 10'h0;
output_ready <= 0; // K not valid yet
end
else begin
i <= i + 1;
KSState <= `KSS_KEYSCHED2;
end
end
/*
i := 0
j := 0
while GeneratingOutput:
i := (i + 1) mod 256
j := (j + S[i]) mod 256
swap values of S[i] and S[j]
K := S[(S[i] + S[j]) mod 256]
output K
endwhile
*/
`KSS_CRYPTO: begin
S[i] <= S[j];
S[j] <= S[i]; // We can do this because of verilog.
tmp<=S[i]+S[j];
KSState <= `KSS_CRYPTO2;
output_ready <= 0;
end
`KSS_CRYPTO2: begin
K <= S[tmp];//S[ S[i]+S[j] ];
if (discardCount<10'h600) // discard first 1536 values - SSH RC4 compliant
discardCount<=discardCount+1;
else output_ready <= 1; // Valid K at output
i <= i+1;
// Here is the secret of 1-clock: we develop all possible values of j in the future
if (j==i+1)
j <= (j + S[i]);
else
if (i==255) j <= (j + S[0]);
else j <= (j + S[i+1]);
$display ("rc4: output = %08X",K);
KSState <= `KSS_CRYPTO;
end
default: begin
end
endcase
end
endmodule