1unsafe fn cstr_bytes(s: *const c_char) -> &'static [u8] {
5 if s.is_null() { return &[]; }
6 let len = strlen(s as *const c_char);
7 core::slice::from_raw_parts(s as *const u8, len)
8}
9
10const CRYPT_B64: [u8; 64] = *b"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
11
12fn crypt_to64(out: &mut [u8], mut u: u32, n: usize) -> usize {
13 for i in 0..n {
14 out[i] = CRYPT_B64[(u % 64) as usize];
15 u /= 64;
16 }
17 n
18}
19
20struct Md5 { len: u64, h: [u32; 4], buf: [u8; 64] }
25
26const MD5_TAB: [u32; 64] = [
27 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
28 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,
29 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
30 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
31 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
32 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
33 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
34 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391,
35];
36
37impl Md5 {
38 fn init(&mut self) {
39 self.len = 0;
40 self.h = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
41 }
42 fn processblock(&mut self, buf: &[u8; 64]) {
43 let mut w = [0u32; 16];
44 for i in 0..16 {
45 w[i] = buf[4*i] as u32 | (buf[4*i+1] as u32)<<8 | (buf[4*i+2] as u32)<<16 | (buf[4*i+3] as u32)<<24;
46 }
47 let (mut a,mut b,mut c,mut d) = (self.h[0],self.h[1],self.h[2],self.h[3]);
48 let mut i = 0usize;
49 while i < 16 {
50 a = a.wrapping_add((b&c|!b&d).wrapping_add(w[i]).wrapping_add(MD5_TAB[i])).rotate_left(7).wrapping_add(b); i+=1;
51 d = d.wrapping_add((a&b|!a&c).wrapping_add(w[i]).wrapping_add(MD5_TAB[i])).rotate_left(12).wrapping_add(a); i+=1;
52 c = c.wrapping_add((d&a|!d&b).wrapping_add(w[i]).wrapping_add(MD5_TAB[i])).rotate_left(17).wrapping_add(d); i+=1;
53 b = b.wrapping_add((c&d|!c&a).wrapping_add(w[i]).wrapping_add(MD5_TAB[i])).rotate_left(22).wrapping_add(c); i+=1;
54 }
55 while i < 32 {
56 a = a.wrapping_add((b&d|c&!d).wrapping_add(w[(5*i+1)%16]).wrapping_add(MD5_TAB[i])).rotate_left(5).wrapping_add(b); i+=1;
57 d = d.wrapping_add((a&c|b&!c).wrapping_add(w[(5*i+1)%16]).wrapping_add(MD5_TAB[i])).rotate_left(9).wrapping_add(a); i+=1;
58 c = c.wrapping_add((d&b|a&!b).wrapping_add(w[(5*i+1)%16]).wrapping_add(MD5_TAB[i])).rotate_left(14).wrapping_add(d); i+=1;
59 b = b.wrapping_add((c&a|d&!a).wrapping_add(w[(5*i+1)%16]).wrapping_add(MD5_TAB[i])).rotate_left(20).wrapping_add(c); i+=1;
60 }
61 while i < 48 {
62 a = a.wrapping_add((b^c^d).wrapping_add(w[(3*i+5)%16]).wrapping_add(MD5_TAB[i])).rotate_left(4).wrapping_add(b); i+=1;
63 d = d.wrapping_add((a^b^c).wrapping_add(w[(3*i+5)%16]).wrapping_add(MD5_TAB[i])).rotate_left(11).wrapping_add(a); i+=1;
64 c = c.wrapping_add((d^a^b).wrapping_add(w[(3*i+5)%16]).wrapping_add(MD5_TAB[i])).rotate_left(16).wrapping_add(d); i+=1;
65 b = b.wrapping_add((c^d^a).wrapping_add(w[(3*i+5)%16]).wrapping_add(MD5_TAB[i])).rotate_left(23).wrapping_add(c); i+=1;
66 }
67 while i < 64 {
68 a = a.wrapping_add((c^(b|!d)).wrapping_add(w[7*i%16]).wrapping_add(MD5_TAB[i])).rotate_left(6).wrapping_add(b); i+=1;
69 d = d.wrapping_add((b^(a|!c)).wrapping_add(w[7*i%16]).wrapping_add(MD5_TAB[i])).rotate_left(10).wrapping_add(a); i+=1;
70 c = c.wrapping_add((a^(d|!b)).wrapping_add(w[7*i%16]).wrapping_add(MD5_TAB[i])).rotate_left(15).wrapping_add(d); i+=1;
71 b = b.wrapping_add((d^(c|!a)).wrapping_add(w[7*i%16]).wrapping_add(MD5_TAB[i])).rotate_left(21).wrapping_add(c); i+=1;
72 }
73 self.h[0] = self.h[0].wrapping_add(a);
74 self.h[1] = self.h[1].wrapping_add(b);
75 self.h[2] = self.h[2].wrapping_add(c);
76 self.h[3] = self.h[3].wrapping_add(d);
77 }
78 fn update(&mut self, data: &[u8]) {
79 let mut p = 0usize;
80 let r = (self.len % 64) as usize;
81 self.len += data.len() as u64;
82 if r > 0 {
83 let avail = 64 - r;
84 if data.len() < avail { self.buf[r..r+data.len()].copy_from_slice(data); return; }
85 self.buf[r..64].copy_from_slice(&data[..avail]);
86 p = avail;
87 let b = self.buf; self.processblock(&b);
88 }
89 while p + 64 <= data.len() {
90 let mut blk = [0u8; 64]; blk.copy_from_slice(&data[p..p+64]); self.processblock(&blk); p += 64;
91 }
92 if p < data.len() { self.buf[..data.len()-p].copy_from_slice(&data[p..]); }
93 }
94 fn finish(&mut self, md: &mut [u8; 16]) {
95 let r = (self.len % 64) as usize;
96 self.buf[r] = 0x80;
97 if r + 1 > 56 { for i in r+1..64 { self.buf[i]=0; } let b=self.buf; self.processblock(&b); for i in 0..56 { self.buf[i]=0; } }
98 else { for i in r+1..56 { self.buf[i]=0; } }
99 let bits = self.len.wrapping_mul(8);
100 for i in 0..8 { self.buf[56+i] = (bits >> (i*8)) as u8; }
101 let b = self.buf; self.processblock(&b);
102 for i in 0..4 { md[4*i]=self.h[i] as u8; md[4*i+1]=(self.h[i]>>8) as u8; md[4*i+2]=(self.h[i]>>16) as u8; md[4*i+3]=(self.h[i]>>24) as u8; }
103 }
104}
105
106fn md5crypt(key: &[u8], setting: &[u8], output: &mut [u8]) -> Option<usize> {
107 if setting.len() < 3 || &setting[..3] != b"$1$" { return None; }
108 let klen = { let mut n=0usize; while n<key.len() && n<=30000 && key[n]!=0 { n+=1; } if n>30000 { return None; } n };
109 let slen = { let mut i=0usize; while i<8 && 3+i<setting.len() && setting[3+i]!=b'$' && setting[3+i]!=0 { i+=1; } i };
110 let salt = &setting[3..3+slen];
111 let mut ctx = Md5{len:0,h:[0;4],buf:[0;64]};
112 let mut md = [0u8; 16];
113 ctx.init(); ctx.update(&key[..klen]); ctx.update(salt); ctx.update(&key[..klen]); ctx.finish(&mut md);
114 ctx.init(); ctx.update(&key[..klen]); ctx.update(&setting[..3+slen]);
115 { let mut i=klen; while i>16 { ctx.update(&md); i-=16; } ctx.update(&md[..i]); }
116 { let saved=md[0]; md[0]=0; let mut i=klen; while i>0 { if i&1!=0 { ctx.update(&[0u8]); } else { ctx.update(&[key[0]]); } i>>=1; } md[0]=saved; }
117 ctx.finish(&mut md);
118 for i in 0..1000u32 {
119 ctx.init();
120 if i%2!=0 { ctx.update(&key[..klen]); } else { ctx.update(&md); }
121 if i%3!=0 { ctx.update(salt); }
122 if i%7!=0 { ctx.update(&key[..klen]); }
123 if i%2!=0 { ctx.update(&md); } else { ctx.update(&key[..klen]); }
124 ctx.finish(&mut md);
125 }
126 output[..3+slen].copy_from_slice(&setting[..3+slen]);
127 let mut p = 3+slen; output[p]=b'$'; p+=1;
128 static PERM: [[u8;3];5] = [[0,6,12],[1,7,13],[2,8,14],[3,9,15],[4,10,5]];
129 for j in 0..5 { let v=(md[PERM[j][0] as usize] as u32)<<16|(md[PERM[j][1] as usize] as u32)<<8|md[PERM[j][2] as usize] as u32; p+=crypt_to64(&mut output[p..],v,4); }
130 p+=crypt_to64(&mut output[p..],md[11] as u32,2);
131 output[p]=0;
132 Some(p)
133}
134
135const MD5_TK: &[u8] = b"Xy01@#\x01\x02\x80\x7f\xff\r\n\x81\t !";
136const MD5_TS: &[u8] = b"$1$abcd0123$";
137const MD5_TH: &[u8] = b"$1$abcd0123$9Qcg8DyviekV3tDGMZynJ1";
138
139#[no_mangle]
140pub unsafe extern "C" fn __crypt_md5(key: *const c_char, setting: *const c_char, output: *mut c_char) -> *mut c_char {
141 let ks = cstr_bytes(key); let ss = cstr_bytes(setting);
142 let out = core::slice::from_raw_parts_mut(output as *mut u8, 256);
143 let mut tb = [0u8; 64]; let q = md5crypt(MD5_TK, MD5_TS, &mut tb);
144 let p = md5crypt(ks, ss, out);
145 if p.is_none() || q.is_none() || tb[..MD5_TH.len()] != *MD5_TH { *output=b'*' as c_char; *output.add(1)=0; return output; }
146 out[p.unwrap()]=0; output
147}
148
149struct Sha256 { len: u64, h: [u32; 8], buf: [u8; 64] }
154
155const SHA256_K: [u32; 64] = [
156 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
157 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
158 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
159 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
160 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
161 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
162 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
163 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2,
164];
165
166impl Sha256 {
167 fn init(&mut self) {
168 self.len = 0;
169 self.h = [0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19];
170 }
171 fn processblock(&mut self, buf: &[u8; 64]) {
172 let mut w = [0u32; 64];
173 for i in 0..16 { w[i]=(buf[4*i] as u32)<<24|(buf[4*i+1] as u32)<<16|(buf[4*i+2] as u32)<<8|buf[4*i+3] as u32; }
174 for i in 16..64 { let s0=w[i-15].rotate_right(7)^w[i-15].rotate_right(18)^(w[i-15]>>3); let s1=w[i-2].rotate_right(17)^w[i-2].rotate_right(19)^(w[i-2]>>10); w[i]=w[i-16].wrapping_add(s0).wrapping_add(w[i-7]).wrapping_add(s1); }
175 let (mut a,mut b,mut c,mut d,mut e,mut f,mut g,mut h)=(self.h[0],self.h[1],self.h[2],self.h[3],self.h[4],self.h[5],self.h[6],self.h[7]);
176 for i in 0..64 {
177 let s1=e.rotate_right(6)^e.rotate_right(11)^e.rotate_right(25); let ch=(e&f)^(!e&g); let t1=h.wrapping_add(s1).wrapping_add(ch).wrapping_add(SHA256_K[i]).wrapping_add(w[i]);
178 let s0=a.rotate_right(2)^a.rotate_right(13)^a.rotate_right(22); let maj=(a&b)^(a&c)^(b&c); let t2=s0.wrapping_add(maj);
179 h=g;g=f;f=e;e=d.wrapping_add(t1);d=c;c=b;b=a;a=t1.wrapping_add(t2);
180 }
181 self.h[0]=self.h[0].wrapping_add(a);self.h[1]=self.h[1].wrapping_add(b);self.h[2]=self.h[2].wrapping_add(c);self.h[3]=self.h[3].wrapping_add(d);
182 self.h[4]=self.h[4].wrapping_add(e);self.h[5]=self.h[5].wrapping_add(f);self.h[6]=self.h[6].wrapping_add(g);self.h[7]=self.h[7].wrapping_add(h);
183 }
184 fn update(&mut self, data: &[u8]) {
185 let mut p=0usize; let r=(self.len%64) as usize; self.len+=data.len() as u64;
186 if r>0 { let avail=64-r; if data.len()<avail { self.buf[r..r+data.len()].copy_from_slice(data); return; } self.buf[r..64].copy_from_slice(&data[..avail]); p=avail; let b=self.buf; self.processblock(&b); }
187 while p+64<=data.len() { let mut blk=[0u8;64]; blk.copy_from_slice(&data[p..p+64]); self.processblock(&blk); p+=64; }
188 if p<data.len() { self.buf[..data.len()-p].copy_from_slice(&data[p..]); }
189 }
190 fn finish(&mut self, md: &mut [u8; 32]) {
191 let r=(self.len%64) as usize; self.buf[r]=0x80;
192 if r+1>56 { for i in r+1..64 { self.buf[i]=0; } let b=self.buf; self.processblock(&b); for i in 0..56 { self.buf[i]=0; } }
193 else { for i in r+1..56 { self.buf[i]=0; } }
194 let bits=self.len.wrapping_mul(8);
195 for i in 0..8 { self.buf[56+i]=(bits>>(56-i*8)) as u8; }
196 let b=self.buf; self.processblock(&b);
197 for i in 0..8 { md[4*i]=(self.h[i]>>24) as u8; md[4*i+1]=(self.h[i]>>16) as u8; md[4*i+2]=(self.h[i]>>8) as u8; md[4*i+3]=self.h[i] as u8; }
198 }
199}
200
201fn sha256_hashmd(s: &mut Sha256, n: usize, md: &[u8]) {
202 let mut i=n; while i>32 { s.update(&md[..32]); i-=32; } s.update(&md[..i]);
203}
204
205fn sha256crypt(key: &[u8], setting: &[u8], output: &mut [u8]) -> Option<usize> {
206 if setting.len()<3 || &setting[..3]!=b"$5$" { return None; }
207 let klen = { let mut n=0usize; while n<key.len() && n<=256 && key[n]!=0 { n+=1; } if n>256 { return None; } n };
208 let mut salt_start=3usize;
209 let mut r: u32 = 5000;
210 let mut rounds_buf = [0u8; 24]; let mut rounds_len = 0usize;
211 if setting.len()>salt_start+7 && &setting[salt_start..salt_start+7]==b"rounds=" {
212 salt_start+=7;
213 if salt_start>=setting.len() || isdigit(setting[salt_start] as c_int)==0 { return None; }
214 let mut ep:*mut c_char=core::ptr::null_mut();
215 let u=unsafe{strtoul(setting[salt_start..].as_ptr() as *const c_char,&mut ep,10)};
216 let consumed=(ep as usize)-(setting[salt_start..].as_ptr() as usize);
217 if consumed==0 || setting.get(salt_start+consumed)!=Some(&b'$') { return None; }
218 salt_start+=consumed+1;
219 if u<1000 { r=1000; } else if u>9999999 { return None; } else { r=u as u32; }
220 rounds_buf[..7].copy_from_slice(b"rounds="); rounds_len=7;
221 let mut tmp=r; let mut db=[0u8;10]; let mut dl=0usize;
222 if tmp==0 { db[0]=b'0'; dl=1; } else { while tmp>0 { db[dl]=b'0'+(tmp%10) as u8; tmp/=10; dl+=1; } db[..dl].reverse(); }
223 rounds_buf[rounds_len..rounds_len+dl].copy_from_slice(&db[..dl]); rounds_len+=dl;
224 rounds_buf[rounds_len]=b'$'; rounds_len+=1;
225 }
226 let salt=&setting[salt_start..];
227 let slen={ let mut i=0usize; while i<16 && i<salt.len() && salt[i]!=b'$' && salt[i]!=0 { if salt[i]==b'\n'||salt[i]==b':' { return None; } i+=1; } i };
228 let sd=&salt[..slen];
229 let mut ctx=Sha256{len:0,h:[0;8],buf:[0;64]};
230 let mut md=[0u8;32]; let mut kmd=[0u8;32]; let mut smd=[0u8;32];
231 ctx.init(); ctx.update(&key[..klen]); ctx.update(sd); ctx.update(&key[..klen]); ctx.finish(&mut md);
232 ctx.init(); ctx.update(&key[..klen]); ctx.update(sd); sha256_hashmd(&mut ctx,klen,&md); { let mut i=klen; while i>0 { if i&1!=0{ctx.update(&md);}else{ctx.update(&key[..klen]);} i>>=1; } } ctx.finish(&mut md);
233 ctx.init(); for _ in 0..klen { ctx.update(&key[..klen]); } ctx.finish(&mut kmd);
234 ctx.init(); for _ in 0..16+md[0] as usize { ctx.update(sd); } ctx.finish(&mut smd);
235 for i in 0..r { ctx.init(); if i%2!=0{sha256_hashmd(&mut ctx,klen,&kmd);}else{ctx.update(&md);} if i%3!=0{ctx.update(&smd[..slen]);} if i%7!=0{sha256_hashmd(&mut ctx,klen,&kmd);} if i%2!=0{ctx.update(&md);}else{sha256_hashmd(&mut ctx,klen,&kmd);} ctx.finish(&mut md); }
236 let mut p=0usize;
237 output[p..p+3].copy_from_slice(b"$5$"); p+=3;
238 if rounds_len>0 { output[p..p+rounds_len].copy_from_slice(&rounds_buf[..rounds_len]); p+=rounds_len; }
239 output[p..p+slen].copy_from_slice(sd); p+=slen; output[p]=b'$'; p+=1;
240 static PERM:[[u8;3];10]=[[0,10,20],[21,1,11],[12,22,2],[3,13,23],[24,4,14],[15,25,5],[6,16,26],[27,7,17],[18,28,8],[9,19,29]];
241 for j in 0..10 { let v=(md[PERM[j][0]as usize]as u32)<<16|(md[PERM[j][1]as usize]as u32)<<8|md[PERM[j][2]as usize]as u32; p+=crypt_to64(&mut output[p..],v,4); }
242 p+=crypt_to64(&mut output[p..],((md[31]as u32)<<8)|md[30]as u32,3); output[p]=0; Some(p)
243}
244
245const S256_TK:&[u8]=b"Xy01@#\x01\x02\x80\x7f\xff\r\n\x81\t !";
246const S256_TS:&[u8]=b"$5$rounds=1234$abc0123456789$";
247const S256_TH:&[u8]=b"$5$rounds=1234$abc0123456789$3VfDjPt05VHFn47C/ojFZ6KRPYrOjj1lLbH.dkF3bZ6";
248
249#[no_mangle]
250pub unsafe extern "C" fn __crypt_sha256(key:*const c_char,setting:*const c_char,output:*mut c_char)->*mut c_char {
251 let ks=cstr_bytes(key); let ss=cstr_bytes(setting);
252 let out=core::slice::from_raw_parts_mut(output as *mut u8,256);
253 let mut tb=[0u8;128]; let q=sha256crypt(S256_TK,S256_TS,&mut tb);
254 let p=sha256crypt(ks,ss,out);
255 if p.is_none()||q.is_none()||tb[..S256_TH.len()]!=*S256_TH { *output=b'*' as c_char; *output.add(1)=0; return output; }
256 out[p.unwrap()]=0; output
257}
258
259struct Sha512 { len: u64, h: [u64; 8], buf: [u8; 128] }
264
265const SHA512_K:[u64;80]=[
266 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
267 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
268 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
269 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
270 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
271 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
272 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
273 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
274 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
275 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
276 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
277 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
278 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
279 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
280 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
281 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
282 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
283 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
284 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
285 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817,
286];
287
288impl Sha512 {
289 fn init(&mut self) {
290 self.len=0;
291 self.h=[0x6a09e667f3bcc908,0xbb67ae8584caa73b,0x3c6ef372fe94f82b,0xa54ff53a5f1d36f1,
292 0x510e527fade682d1,0x9b05688c2b3e6c1f,0x1f83d9abfb41bd6b,0x5be0cd19137e2179];
293 }
294 fn processblock(&mut self, buf: &[u8; 128]) {
295 let mut w=[0u64;80];
296 for i in 0..16 { w[i]=(buf[8*i]as u64)<<56|(buf[8*i+1]as u64)<<48|(buf[8*i+2]as u64)<<40|(buf[8*i+3]as u64)<<32|(buf[8*i+4]as u64)<<24|(buf[8*i+5]as u64)<<16|(buf[8*i+6]as u64)<<8|buf[8*i+7]as u64; }
297 for i in 16..80 { let s0=w[i-15].rotate_right(1)^w[i-15].rotate_right(8)^(w[i-15]>>7); let s1=w[i-2].rotate_right(19)^w[i-2].rotate_right(61)^(w[i-2]>>6); w[i]=w[i-16].wrapping_add(s0).wrapping_add(w[i-7]).wrapping_add(s1); }
298 let (mut a,mut b,mut c,mut d,mut e,mut f,mut g,mut h)=(self.h[0],self.h[1],self.h[2],self.h[3],self.h[4],self.h[5],self.h[6],self.h[7]);
299 for i in 0..80 {
300 let s1=e.rotate_right(14)^e.rotate_right(18)^e.rotate_right(41); let ch=(e&f)^(!e&g); let t1=h.wrapping_add(s1).wrapping_add(ch).wrapping_add(SHA512_K[i]).wrapping_add(w[i]);
301 let s0=a.rotate_right(28)^a.rotate_right(34)^a.rotate_right(39); let maj=(a&b)^(a&c)^(b&c); let t2=s0.wrapping_add(maj);
302 h=g;g=f;f=e;e=d.wrapping_add(t1);d=c;c=b;b=a;a=t1.wrapping_add(t2);
303 }
304 self.h[0]=self.h[0].wrapping_add(a);self.h[1]=self.h[1].wrapping_add(b);self.h[2]=self.h[2].wrapping_add(c);self.h[3]=self.h[3].wrapping_add(d);
305 self.h[4]=self.h[4].wrapping_add(e);self.h[5]=self.h[5].wrapping_add(f);self.h[6]=self.h[6].wrapping_add(g);self.h[7]=self.h[7].wrapping_add(h);
306 }
307 fn update(&mut self, data: &[u8]) {
308 let mut p=0usize; let r=(self.len%128) as usize; self.len+=data.len() as u64;
309 if r>0 { let avail=128-r; if data.len()<avail { self.buf[r..r+data.len()].copy_from_slice(data); return; } self.buf[r..128].copy_from_slice(&data[..avail]); p=avail; let b=self.buf; self.processblock(&b); }
310 while p+128<=data.len() { let mut blk=[0u8;128]; blk.copy_from_slice(&data[p..p+128]); self.processblock(&blk); p+=128; }
311 if p<data.len() { self.buf[..data.len()-p].copy_from_slice(&data[p..]); }
312 }
313 fn finish(&mut self, md: &mut [u8; 64]) {
314 let r=(self.len%128) as usize; self.buf[r]=0x80;
315 if r+1>112 { for i in r+1..128 { self.buf[i]=0; } let b=self.buf; self.processblock(&b); for i in 0..120 { self.buf[i]=0; } }
316 else { for i in r+1..120 { self.buf[i]=0; } }
317 let bits=self.len.wrapping_mul(8);
318 for i in 0..8 { self.buf[120+i]=(bits>>(56-i*8)) as u8; }
319 let b=self.buf; self.processblock(&b);
320 for i in 0..8 { md[8*i]=(self.h[i]>>56)as u8; md[8*i+1]=(self.h[i]>>48)as u8; md[8*i+2]=(self.h[i]>>40)as u8; md[8*i+3]=(self.h[i]>>32)as u8; md[8*i+4]=(self.h[i]>>24)as u8; md[8*i+5]=(self.h[i]>>16)as u8; md[8*i+6]=(self.h[i]>>8)as u8; md[8*i+7]=self.h[i]as u8; }
321 }
322}
323
324fn sha512_hashmd(s: &mut Sha512, n: usize, md: &[u8]) {
325 let mut i=n; while i>64 { s.update(&md[..64]); i-=64; } s.update(&md[..i]);
326}
327
328fn sha512crypt(key: &[u8], setting: &[u8], output: &mut [u8]) -> Option<usize> {
329 if setting.len()<3 || &setting[..3]!=b"$6$" { return None; }
330 let klen = { let mut n=0usize; while n<key.len() && n<=256 && key[n]!=0 { n+=1; } if n>256 { return None; } n };
331 let mut salt_start=3usize;
332 let mut r: u32 = 5000;
333 let mut rounds_buf = [0u8; 24]; let mut rounds_len = 0usize;
334 if setting.len()>salt_start+7 && &setting[salt_start..salt_start+7]==b"rounds=" {
335 salt_start+=7;
336 if salt_start>=setting.len() || isdigit(setting[salt_start] as c_int)==0 { return None; }
337 let mut ep:*mut c_char=core::ptr::null_mut();
338 let u=unsafe{strtoul(setting[salt_start..].as_ptr() as *const c_char,&mut ep,10)};
339 let consumed=(ep as usize)-(setting[salt_start..].as_ptr() as usize);
340 if consumed==0 || setting.get(salt_start+consumed)!=Some(&b'$') { return None; }
341 salt_start+=consumed+1;
342 if u<1000 { r=1000; } else if u>9999999 { return None; } else { r=u as u32; }
343 rounds_buf[..7].copy_from_slice(b"rounds="); rounds_len=7;
344 let mut tmp=r; let mut db=[0u8;10]; let mut dl=0usize;
345 if tmp==0 { db[0]=b'0'; dl=1; } else { while tmp>0 { db[dl]=b'0'+(tmp%10) as u8; tmp/=10; dl+=1; } db[..dl].reverse(); }
346 rounds_buf[rounds_len..rounds_len+dl].copy_from_slice(&db[..dl]); rounds_len+=dl;
347 rounds_buf[rounds_len]=b'$'; rounds_len+=1;
348 }
349 let salt=&setting[salt_start..];
350 let slen={ let mut i=0usize; while i<16 && i<salt.len() && salt[i]!=b'$' && salt[i]!=0 { if salt[i]==b'\n'||salt[i]==b':' { return None; } i+=1; } i };
351 let sd=&salt[..slen];
352 let mut ctx=Sha512{len:0,h:[0;8],buf:[0;128]};
353 let mut md=[0u8;64]; let mut kmd=[0u8;64]; let mut smd=[0u8;64];
354 ctx.init(); ctx.update(&key[..klen]); ctx.update(sd); ctx.update(&key[..klen]); ctx.finish(&mut md);
355 ctx.init(); ctx.update(&key[..klen]); ctx.update(sd); sha512_hashmd(&mut ctx,klen,&md); { let mut i=klen; while i>0 { if i&1!=0{ctx.update(&md);}else{ctx.update(&key[..klen]);} i>>=1; } } ctx.finish(&mut md);
356 ctx.init(); for _ in 0..klen { ctx.update(&key[..klen]); } ctx.finish(&mut kmd);
357 ctx.init(); for _ in 0..16+md[0] as usize { ctx.update(sd); } ctx.finish(&mut smd);
358 for i in 0..r { ctx.init(); if i%2!=0{sha512_hashmd(&mut ctx,klen,&kmd);}else{ctx.update(&md);} if i%3!=0{ctx.update(&smd[..slen]);} if i%7!=0{sha512_hashmd(&mut ctx,klen,&kmd);} if i%2!=0{ctx.update(&md);}else{sha512_hashmd(&mut ctx,klen,&kmd);} ctx.finish(&mut md); }
359 let mut p=0usize;
360 output[p..p+3].copy_from_slice(b"$6$"); p+=3;
361 if rounds_len>0 { output[p..p+rounds_len].copy_from_slice(&rounds_buf[..rounds_len]); p+=rounds_len; }
362 output[p..p+slen].copy_from_slice(sd); p+=slen; output[p]=b'$'; p+=1;
363 static PERM:[[u8;3];21]=[[0,21,42],[22,43,1],[44,2,23],[3,24,45],[25,46,4],[47,5,26],[6,27,48],[28,49,7],[50,8,29],[9,30,51],[31,52,10],[53,11,32],[12,33,54],[34,55,13],[56,14,35],[15,36,57],[37,58,16],[59,17,38],[18,39,60],[40,61,19],[62,20,41]];
364 for j in 0..21 { let v=(md[PERM[j][0]as usize]as u32)<<16|(md[PERM[j][1]as usize]as u32)<<8|md[PERM[j][2]as usize]as u32; p+=crypt_to64(&mut output[p..],v,4); }
365 p+=crypt_to64(&mut output[p..],md[63] as u32,2); output[p]=0; Some(p)
366}
367
368const S512_TK:&[u8]=b"Xy01@#\x01\x02\x80\x7f\xff\r\n\x81\t !";
369const S512_TS:&[u8]=b"$6$rounds=1234$abc0123456789$";
370const S512_TH:&[u8]=b"$6$rounds=1234$abc0123456789$BCpt8zLrc/RcyuXmCDOE1ALqMXB2MH6n1g891HhFj8.w7LxGv.FTkqq6Vxc/km3Y0jE0j24jY5PIv/oOu6reg1";
371
372#[no_mangle]
373pub unsafe extern "C" fn __crypt_sha512(key:*const c_char,setting:*const c_char,output:*mut c_char)->*mut c_char {
374 let ks=cstr_bytes(key); let ss=cstr_bytes(setting);
375 let out=core::slice::from_raw_parts_mut(output as *mut u8,256);
376 let mut tb=[0u8;128]; let q=sha512crypt(S512_TK,S512_TS,&mut tb);
377 let p=sha512crypt(ks,ss,out);
378 if p.is_none()||q.is_none()||tb[..S512_TH.len()]!=*S512_TH { *output=b'*' as c_char; *output.add(1)=0; return output; }
379 out[p.unwrap()]=0; output
380}
381
382const BF_N: usize = 16;
387
388const BF_INIT_P: [u32; 18] = [
389 0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0,0x082efa98,0xec4e6c89,
390 0x452821e6,0x38d01377,0xbe5466cf,0x34e90c6c,0xc0ac29b7,0xc97c50dd,0x3f84d5b5,0xb5470917,
391 0x9216d5d9,0x8979fb1b,
392];
393
394const BF_ITOA64: &[u8; 64] = b"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
395
396const BF_ATOI64: [u8; 0x60] = [
397 64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,1,
398 54,55,56,57,58,59,60,61,62,63,64,64,64,64,64,64,
399 64,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
400 17,18,19,20,21,22,23,24,25,26,27,64,64,64,64,64,
401 64,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,
402 43,44,45,46,47,48,49,50,51,52,53,64,64,64,64,64,
403];
404
405const BF_FLAGS_BY_SUBTYPE: [u8; 26] = [2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,0];
406
407const BF_MAGIC_W: [u32; 6] = [0x4F727068, 0x65616E42, 0x65686F6C, 0x64657253, 0x63727944, 0x6F756274];
408
409const BF_S0: [u32; 256] = [
411 0xd1310ba6,0x98dfb5ac,0x2ffd72db,0xd01adfb7,0xb8e1afed,0x6a267e96,0xba7c9045,0xf12c7f99,
412 0x24a19947,0xb3916cf7,0x0801f2e2,0x858efc16,0x636920d8,0x71574e69,0xa458fea3,0xf4933d7e,
413 0x0d95748f,0x728eb658,0x718bcd58,0x82154aee,0x7b54a41d,0xc25a59b5,0x9c30d539,0x2af26013,
414 0xc5d1b023,0x286085f0,0xca417918,0xb8db38ef,0x8e79dcb0,0x603a180e,0x6c9e0e8b,0xb01e8a3e,
415 0xd71577c1,0xbd314b27,0x78af2fda,0x55605c60,0xe65525f3,0xaa55ab94,0x57489862,0x63e81440,
416 0x55ca396a,0x2aab10b6,0xb4cc5c34,0x1141e8ce,0xa15486af,0x7c72e993,0xb3ee1411,0x636fbc2a,
417 0x2ba9c55d,0x741831f6,0xce5c3e16,0x9b87931e,0xafd6ba33,0x6c24cf5c,0x7a325381,0x28958677,
418 0x3b8f4898,0x6b4bb9af,0xc4bfe81b,0x66282193,0x61d809cc,0xfb21a991,0x487cac60,0x5dec8032,
419 0xef845d5d,0xe98575b1,0xdc262302,0xeb651b88,0x23893e81,0xd396acc5,0x0f6d6ff3,0x83f44239,
420 0x2e0b4482,0xa4842004,0x69c8f04a,0x9e1f9b5e,0x21c66842,0xf6e96c9a,0x670c9c61,0xabd388f0,
421 0x6a51a0d2,0xd8542f68,0x960fa728,0xab5133a3,0x6eef0b6c,0x137a3be4,0xba3bf050,0x7efb2a98,
422 0xa1f1651d,0x39af0176,0x66ca593e,0x82430e88,0x8cee8619,0x456f9fb4,0x7d84a5c3,0x3b8b5ebe,
423 0xe06f75d8,0x85c12073,0x401a449f,0x56c16aa6,0x4ed3aa62,0x363f7706,0x1bfedf72,0x429b023d,
424 0x37d0d724,0xd00a1248,0xdb0fead3,0x49f1c09b,0x075372c9,0x80991b7b,0x25d479d8,0xf6e8def7,
425 0xe3fe501a,0xb6794c3b,0x976ce0bd,0x04c006ba,0xc1a94fb6,0x409f60c4,0x5e5c9ec2,0x196a2463,
426 0x68fb6faf,0x3e6c53b5,0x1339b2eb,0x3b52ec6f,0x6dfc511f,0x9b30952c,0xcc814544,0xaf5ebd09,
427 0xbee3d004,0xde334afd,0x660f2807,0x192e4bb3,0xc0cba857,0x45c8740f,0xd20b5f39,0xb9d3fbdb,
428 0x5579c0bd,0x1a60320a,0xd6a100c6,0x402c7279,0x679f25fe,0xfb1fa3cc,0x8ea5e9f8,0xdb3222f8,
429 0x3c7516df,0xfd616b15,0x2f501ec8,0xad0552ab,0x323db5fa,0xfd238760,0x53317b48,0x3e00df82,
430 0x9e5c57bb,0xca6f8ca0,0x1a87562e,0xdf1769db,0xd542a8f6,0x287effc3,0xac6732c6,0x8c4f5573,
431 0x695b27b0,0xbbca58c8,0xe1ffa35d,0xb8f011a0,0x10fa3d98,0xfd2183b8,0x4afcb56c,0x2dd1d35b,
432 0x9a53e479,0xb6f84565,0xd28e49bc,0x4bfb9790,0xe1ddf2da,0xa4cb7e33,0x62fb1341,0xcee4c6e8,
433 0xef20cada,0x36774c01,0xd07e9efe,0x2bf11fb4,0x95dbda4d,0xae909198,0xeaad8e71,0x6b93d5a0,
434 0xd08ed1d0,0xafc725e0,0x8e3c5b2f,0x8e7594b7,0x8ff6e2fb,0xf2122b64,0x8888b812,0x900df01c,
435 0x4fad5ea0,0x688fc31c,0xd1cff191,0xb3a8c1ad,0x2f2f2218,0xbe0e1777,0xea752dfe,0x8b021fa1,
436 0xe5a0cc0f,0xb56f74e8,0x18acf3d6,0xce89e299,0xb4a84fe0,0xfd13e0b7,0x7cc43b81,0xd2ada8d9,
437 0x165fa266,0x80957705,0x93cc7314,0x211a1477,0xe6ad2065,0x77b5fa86,0xc75442f5,0xfb9d35cf,
438 0xebcdaf0c,0x7b3e89a0,0xd6411bd3,0xae1e7e49,0x00250e2d,0x2071b35e,0x226800bb,0x57b8e0af,
439 0x2464369b,0xf009b91e,0x5563911d,0x59dfa6aa,0x78c14389,0xd95a537f,0x207d5ba2,0x02e5b9c5,
440 0x83260376,0x6295cfa9,0x11c81968,0x4e734a41,0xb3472dca,0x7b14a94a,0x1b510052,0x9a532915,
441 0xd60f573f,0xbc9bc6e4,0x2b60a476,0x81e67400,0x08ba6fb5,0x571be91f,0xf296ec6b,0x2a0dd915,
442 0xb6636521,0xe7b9f9b6,0xff34052e,0xc5855664,0x53b02d5d,0xa99f8fa1,0x08ba4799,0x6e85076a,
443];
444const BF_S1: [u32; 256] = [
445 0x4b7a70e9,0xb5b32944,0xdb75092e,0xc4192623,0xad6ea6b0,0x49a7df7d,0x9cee60b8,0x8fedb266,
446 0xecaa8c71,0x699a17ff,0x5664526c,0xc2b19ee1,0x193602a5,0x75094c29,0xa0591340,0xe4183a3e,
447 0x3f54989a,0x5b429d65,0x6b8fe4d6,0x99f73fd6,0xa1d29c07,0xefe830f5,0x4d2d38e6,0xf0255dc1,
448 0x4cdd2086,0x8470eb26,0x6382e9c6,0x021ecc5e,0x09686b3f,0x3ebaefc9,0x3c971814,0x6b6a70a1,
449 0x687f3584,0x52a0e286,0xb79c5305,0xaa500737,0x3e07841c,0x7fdeae5c,0x8e7d44ec,0x5716f2b8,
450 0xb03ada37,0xf0500c0d,0xf01c1f04,0x0200b3ff,0xae0cf51a,0x3cb574b2,0x25837a58,0xdc0921bd,
451 0xd19113f9,0x7ca92ff6,0x94324773,0x22f54701,0x3ae5e581,0x37c2dadc,0xc8b57634,0x9af3dda7,
452 0xa9446146,0x0fd0030e,0xecc8c73e,0xa4751e41,0xe238cd99,0x3bea0e2f,0x3280bba1,0x183eb331,
453 0x4e548b38,0x4f6db908,0x6f420d03,0xf60a04bf,0x2cb81290,0x24977c79,0x5679b072,0xbcaf89af,
454 0xde9a771f,0xd9930810,0xb38bae12,0xdccf3f2e,0x5512721f,0x2e6b7124,0x501adde6,0x9f84cd87,
455 0x7a584718,0x7408da17,0xbc9f9abc,0xe94b7d8c,0xec7aec3a,0xdb851dfa,0x63094366,0xc464c3d2,
456 0xef1c1847,0x3215d908,0xdd433b37,0x24c2ba16,0x12a14d43,0x2a65c451,0x50940002,0x133ae4dd,
457 0x71dff89e,0x10314e55,0x81ac77d6,0x5f11199b,0x043556f1,0xd7a3c76b,0x3c11183b,0x5924a509,
458 0xf28fe6ed,0x97f1fbfa,0x9ebabf2c,0x1e153c6e,0x86e34570,0xeae96fb1,0x860e5e0a,0x5a3e2ab3,
459 0x771fe71c,0x4e3d06fa,0x2965dcb9,0x99e71d0f,0x803e89d6,0x5266c825,0x2e4cc978,0x9c10b36a,
460 0xc6150eba,0x94e2ea78,0xa5fc3c53,0x1e0a2df4,0xf2f74ea7,0x361d2b3d,0x1939260f,0x19c27960,
461 0x5223a708,0xf71312b6,0xebadfe6e,0xeac31f66,0xe3bc4595,0xa67bc883,0xb17f37d1,0x018cff28,
462 0xc332ddef,0xbe6c5aa5,0x65582185,0x68ab9802,0xeecea50f,0xdb2f953b,0x2aef7dad,0x5b6e2f84,
463 0x1521b628,0x29076170,0xecdd4775,0x619f1510,0x13cca830,0xeb61bd96,0x0334fe1e,0xaa0363cf,
464 0xb5735c90,0x4c70a239,0xd59e9e0b,0xcbaade14,0xeecc86bc,0x60622ca7,0x9cab5cab,0xb2f3846e,
465 0x648b1eaf,0x19bdf0ca,0xa02369b9,0x655abb50,0x40685a32,0x3c2ab4b3,0x319ee9d5,0xc021b8f7,
466 0x9b540b19,0x875fa099,0x95f7997e,0x623d7da8,0xf837889a,0x97e32d77,0x11ed935f,0x16681281,
467 0x0e358829,0xc7e61fd6,0x96dedfa1,0x7858ba99,0x57f584a5,0x1b227263,0x9b83c3ff,0x1ac24696,
468 0xcdb30aeb,0x532e3054,0x8fd948e4,0x6dbc3128,0x58ebf2ef,0x34c6ffea,0xfe28ed61,0xee7c3c73,
469 0x5d4a14d9,0xe864b7e3,0x42105d14,0x203e13e0,0x45eee2b6,0xa3aaabea,0xdb6c4f15,0xfacb4fd0,
470 0xc742f442,0xef6abbb5,0x654f3b1d,0x41cd2105,0xd81e799e,0x86854dc7,0xe44b476a,0x3d816250,
471 0xcf62a1f2,0x5b8d2646,0xfc8883a0,0xc1c7b6a3,0x7f1524c3,0x69cb7492,0x47848a0b,0x5692b285,
472 0x095bbf00,0xad19489d,0x1462b174,0x23820e00,0x58428d2a,0x0c55f5ea,0x1dadf43e,0x233f7061,
473 0x3372f092,0x8d937e41,0xd65fecf1,0x6c223bdb,0x7cde3759,0xcbee7460,0x4085f2a7,0xce77326e,
474 0xa6078084,0x19f8509e,0xe8efd855,0x61d99735,0xa969a7aa,0xc50c06c2,0x5a04abfc,0x800bcadc,
475 0x9e447a2e,0xc3453484,0xfdd56705,0x0e1e9ec9,0xdb73dbd3,0x105588cd,0x675fda79,0xe3674340,
476 0xc5c43465,0x713e38d8,0x3d28f89e,0xf16dff20,0x153e21e7,0x8fb03d4a,0xe6e39f2b,0xdb83adf7,
477];
478const BF_S2: [u32; 256] = [
479 0xe93d5a68,0x948140f7,0xf64c261c,0x94692934,0x411520f7,0x7602d4f7,0xbcf46b2e,0xd4a20068,
480 0xd4082471,0x3320f46a,0x43b7d4b7,0x500061af,0x1e39f62e,0x97244546,0x14214f74,0xbf8b8840,
481 0x4d95fc1d,0x96b591af,0x70f4ddd3,0x66a02f45,0xbfbc09ec,0x03bd9785,0x7fac6dd0,0x31cb8504,
482 0x96eb27b3,0x55fd3941,0xda2547e6,0xabca0a9a,0x28507825,0x530429f4,0x0a2c86da,0xe9b66dfb,
483 0x68dc1462,0xd7486900,0x680ec0a4,0x27a18dee,0x4f3ffea2,0xe887ad8c,0xb58ce006,0x7af4d6b6,
484 0xaace1e7c,0xd3375fec,0xce78a399,0x406b2a42,0x20fe9e35,0xd9f385b9,0xee39d7ab,0x3b124e8b,
485 0x1dc9faf7,0x4b6d1856,0x26a36631,0xeae397b2,0x3a6efa74,0xdd5b4332,0x6841e7f7,0xca7820fb,
486 0xfb0af54e,0xd8feb397,0x454056ac,0xba489527,0x55533a3a,0x20838d87,0xfe6ba9b7,0xd096954b,
487 0x55a867bc,0xa1159a58,0xcca92963,0x99e1db33,0xa62a4a56,0x3f3125f9,0x5ef47e1c,0x9029317c,
488 0xfdf8e802,0x04272f70,0x80bb155c,0x05282ce3,0x95c11548,0xe4c66d22,0x48c1133f,0xc70f86dc,
489 0x07f9c9ee,0x41041f0f,0x404779a4,0x5d886e17,0x325f51eb,0xd59bc0d1,0xf2bcc18f,0x41113564,
490 0x257b7834,0x602a9c60,0xdff8e8a3,0x1f636c1b,0x0e12b4c2,0x02e1329e,0xaf664fd1,0xcad18115,
491 0x6b2395e0,0x333e92e1,0x3b240b62,0xeebeb922,0x85b2a20e,0xe6ba0d99,0xde720c8c,0x2da2f728,
492 0xd0127845,0x95b794fd,0x647d0862,0xe7ccf5f0,0x5449a36f,0x877d48fa,0xc39dfd27,0xf33e8d1e,
493 0x0a476341,0x992eff74,0x3a6f6eab,0xf4f8fd37,0xa812dc60,0xa1ebddf8,0x991be14c,0xdb6e6b0d,
494 0xc67b5510,0x6d672c37,0x2765d43b,0xdcd0e804,0xf1290dc7,0xcc00ffa3,0xb5390f92,0x690fed0b,
495 0x667b9ffb,0xcedb7d9c,0xa091cf0b,0xd9155ea3,0xbb132f88,0x515bad24,0x7b9479bf,0x763bd6eb,
496 0x37392eb3,0xcc115979,0x8026e297,0xf42e312d,0x6842ada7,0xc66a2b3b,0x12754ccc,0x782ef11c,
497 0x6a124237,0xb79251e7,0x06a1bbe6,0x4bfb6350,0x1a6b1018,0x11caedfa,0x3d25bdd8,0xe2e1c3c9,
498 0x44421659,0x0a121386,0xd90cec6e,0xd5abea2a,0x64af674e,0xda86a85f,0xbebfe988,0x64e4c3fe,
499 0x9dbc8057,0xf0f7c086,0x60787bf8,0x6003604d,0xd1fd8346,0xf6381fb0,0x7745ae04,0xd736fccc,
500 0x83426b33,0xf01eab71,0xb0804187,0x3c005e5f,0x77a057be,0xbde8ae24,0x55464299,0xbf582e61,
501 0x4e58f48f,0xf2ddfda2,0xf474ef38,0x8789bdc2,0x5366f9c3,0xc8b38e74,0xb475f255,0x46fcd9b9,
502 0x7aeb2661,0x8b1ddf84,0x846a0e79,0x915f95e2,0x466e598e,0x20b45770,0x8cd55591,0xc902de4c,
503 0xb90bace1,0xbb8205d0,0x11a86248,0x7574a99e,0xb77f19b6,0xe0a9dc09,0x662d09a1,0xc4324633,
504 0xe85a1f02,0x09f0be8c,0x4a99a025,0x1d6efe10,0x1ab93d1d,0x0ba5a4df,0xa186f20f,0x2868f169,
505 0xdcb7da83,0x573906fe,0xa1e2ce9b,0x4fcd7f52,0x50115e01,0xa70683fa,0xa002b5c4,0x0de6d027,
506 0x9af88c27,0x773f8641,0xc3604c06,0x61a806b5,0xf0177a28,0xc0f586e0,0x006058aa,0x30dc7d62,
507 0x11e69ed7,0x2338ea63,0x53c2dd94,0xc2c21634,0xbbcbee56,0x90bcb6de,0xebfc7da1,0xce591d76,
508 0x6f05e409,0x4b7c0188,0x39720a3d,0x7c927c24,0x86e3725f,0x724d9db9,0x1ac15bb4,0xd39eb8fc,
509 0xed545578,0x08fca5b5,0xd83d7cd3,0x4dad0fc4,0x1e50ef5e,0xb161e6f8,0xa28514d9,0x6c51133c,
510 0x6fd5c7e7,0x56e14ec4,0x362abfce,0xddc6c837,0xd79a3234,0x92638212,0x670efa8e,0x406000e0,
511];
512const BF_S3: [u32; 256] = [
513 0x3a39ce37,0xd3faf5cf,0xabc27737,0x5ac52d1b,0x5cb0679e,0x4fa33742,0xd3822740,0x99bc9bbe,
514 0xd5118e9d,0xbf0f7315,0xd62d1c7e,0xc700c47b,0xb78c1b6b,0x21a19045,0xb26eb1be,0x6a366eb4,
515 0x5748ab2f,0xbc946e79,0xc6a376d2,0x6549c2c8,0x530ff8ee,0x468dde7d,0xd5730a1d,0x4cd04dc6,
516 0x2939bbdb,0xa9ba4650,0xac9526e8,0xbe5ee304,0xa1fad5f0,0x6a2d519a,0x63ef8ce2,0x9a86ee22,
517 0xc089c2b8,0x43242ef6,0xa51e03aa,0x9cf2d0a4,0x83c061ba,0x9be96a4d,0x8fe51550,0xba645bd6,
518 0x2826a2f9,0xa73a3ae1,0x4ba99586,0xef5562e9,0xc72fefd3,0xf752f7da,0x3f046f69,0x77fa0a59,
519 0x80e4a915,0x87b08601,0x9b09e6ad,0x3b3ee593,0xe990fd5a,0x9e34d797,0x2cf0b7d9,0x022b8b51,
520 0x96d5ac3a,0x017da67d,0xd1cf3ed6,0x7c7d2d28,0x1f9f25cf,0xadf2b89b,0x5ad6b472,0x5a88f54c,
521 0xe029ac71,0xe019a5e6,0x47b0acfd,0xed93fa9b,0xe8d3c48d,0x283b57cc,0xf8d56629,0x79132e28,
522 0x785f0191,0xed756055,0xf7960e44,0xe3d35e8c,0x15056dd4,0x88f46dba,0x03a16125,0x0564f0bd,
523 0xc3eb9e15,0x3c9057a2,0x97271aec,0xa93a072a,0x1b3f6d9b,0x1e6321f5,0xf59c66fb,0x26dcf319,
524 0x7533d928,0xb155fdf5,0x03563482,0x8aba3cbb,0x28517711,0xc20ad9f8,0xabcc5167,0xccad925f,
525 0x4de81751,0x3830dc8e,0x379d5862,0x9320f991,0xea7a90c2,0xfb3e7bce,0x5121ce64,0x774fbe32,
526 0xa8b6e37e,0xc3293d46,0x48de5369,0x6413e680,0xa2ae0810,0xdd6db224,0x69852dfd,0x09072166,
527 0xb39a460a,0x6445c0dd,0x586cdecf,0x1c20c8ae,0x5bbef7dd,0x1b588d40,0xccd2017f,0x6bb4e3bb,
528 0xdda26a7e,0x3a59ff45,0x3e350a44,0xbcb4cdd5,0x72eacea8,0xfa6484bb,0x8d6612ae,0xbf3c6f47,
529 0xd29be463,0x542f5d9e,0xaec2771b,0xf64e6370,0x740e0d8d,0xe75b1357,0xf8721671,0xaf537d5d,
530 0x4040cb08,0x4eb4e2cc,0x34d2466a,0x0115af84,0xe1b00428,0x95983a1d,0x06b89fb4,0xce6ea048,
531 0x6f3f3b82,0x3520ab82,0x011a1d4b,0x277227f8,0x611560b1,0xe7933fdc,0xbb3a792b,0x344525bd,
532 0xa08839e1,0x51ce794b,0x2f32c9b7,0xa01fbac9,0xe01cc87e,0xbcc7d1f6,0xcf0111c3,0xa1e8aac7,
533 0x1a908749,0xd44fbd9a,0xd0dadecb,0xd50ada38,0x0339c32a,0xc6913667,0x8df9317c,0xe0b12b4f,
534 0xf79e59b7,0x43f5bb3a,0xf2d519ff,0x27d9459c,0xbf97222c,0x15e6fc2a,0x0f91fc71,0x9b941525,
535 0xfae59361,0xceb69ceb,0xc2a86459,0x12baa8d1,0xb6c1075e,0xe3056a0c,0x10d25065,0xcb03a442,
536 0xe0ec6e0e,0x1698db3b,0x4c98a0be,0x3278e964,0x9f1f9532,0xe0d392df,0xd3a0342b,0x8971f21e,
537 0x1b0a7441,0x4ba3348c,0xc5be7120,0xc37632d8,0xdf359f8d,0x9b992f2e,0xe60b6f47,0x0fe3f11d,
538 0xe54cda54,0x1edad891,0xce6279cf,0xcd3e7e6f,0x1618b166,0xfd2c1d05,0x848fd2c5,0xf6fb2299,
539 0xf523f357,0xa6327623,0x93a83531,0x56cccd02,0xacf08162,0x5a75ebb5,0x6e163697,0x88d273cc,
540 0xde966292,0x81b949d0,0x4c50901b,0x71c65614,0xe6c6c7bd,0x327a140a,0x45e1d006,0xc3f27b9a,
541 0xc9aa53fd,0x62a80f00,0xbb25bfe2,0x35bdd2f6,0x71126905,0xb2040222,0xb6cbcf7c,0xcd769c2b,
542 0x53113ec0,0x1640e3d3,0x38abbd60,0x2547adf0,0xba38209c,0xf746ce76,0x77afa1c5,0x20756060,
543 0x85cbfe4e,0x8ae88dd8,0x7aaaf9b0,0x4cf9aa7e,0x1948c25c,0x02fb8a8c,0x01c36ae4,0xd6ebe1f9,
544 0x90d4f869,0xa65cdea0,0x3f09252d,0xc208e69f,0xb74e6132,0xce77e25b,0x578fdfe3,0x3ac372e6,
545];
546
547#[inline(always)]
548fn bf_encrypt_block(ps: &[u32; 1042], mut l: u32, mut r: u32) -> (u32, u32) {
549 let p = ps.as_ptr();
550 let s0 = unsafe { p.add(18) };
551 let s1 = unsafe { p.add(274) };
552 let s2 = unsafe { p.add(530) };
553 let s3 = unsafe { p.add(786) };
554 l ^= unsafe { *p };
555 for i in (0..BF_N).step_by(2) {
556 let mut tmp = unsafe { *s0.add((l >> 24) as usize) };
557 tmp = tmp.wrapping_add(unsafe { *s1.add(((l >> 16) & 0xFF) as usize) });
558 tmp ^= unsafe { *s2.add(((l >> 8) & 0xFF) as usize) };
559 tmp = tmp.wrapping_add(unsafe { *s3.add((l & 0xFF) as usize) });
560 r ^= unsafe { *p.add(i + 1) }; r ^= tmp;
561 let tl = r; r = l; l = tl;
562
563 let mut tmp2 = unsafe { *s0.add((l >> 24) as usize) };
564 tmp2 = tmp2.wrapping_add(unsafe { *s1.add(((l >> 16) & 0xFF) as usize) });
565 tmp2 ^= unsafe { *s2.add(((l >> 8) & 0xFF) as usize) };
566 tmp2 = tmp2.wrapping_add(unsafe { *s3.add((l & 0xFF) as usize) });
567 r ^= unsafe { *p.add(i + 2) }; r ^= tmp2;
568 let tl2 = r; r = l; l = tl2;
569 }
570 let old_r = r ^ unsafe { *p.add(BF_N + 1) };
571 r = l;
572 l = old_r;
573 (l, r)
574}
575
576fn bf_crypt_inner(key: &[u8], setting: &[u8], output: &mut [u8], min: u32) -> Option<usize> {
577 if setting.len() < 7 { return None; }
578 if setting[0] != b'$' || setting[1] != b'2' { return None; }
579 let subtype = setting[2];
580 if subtype < b'a' || subtype > b'z' { return None; }
581 let st_idx = (subtype - b'a') as usize;
582 if st_idx >= 26 || BF_FLAGS_BY_SUBTYPE[st_idx] == 0 { return None; }
583 if setting[3] != b'$' { return None; }
584 if setting[4] < b'0' || setting[4] > b'1' { return None; }
585 if setting[5] < b'0' || setting[5] > b'9' { return None; }
586 if setting[6] != b'$' { return None; }
587
588 let count = 1u32 << (((setting[4] - b'0') as u32) * 10 + ((setting[5] - b'0') as u32));
589 if count < min { return None; }
590
591 if setting.len() < 7 + 22 { return None; }
592 let mut salt_bytes = [0u8; 16];
593 if bf_decode(&mut salt_bytes, &setting[7..7+22]) { return None; }
594 let salt_words = [
595 (salt_bytes[0] as u32) << 24 | (salt_bytes[1] as u32) << 16 | (salt_bytes[2] as u32) << 8 | salt_bytes[3] as u32,
596 (salt_bytes[4] as u32) << 24 | (salt_bytes[5] as u32) << 16 | (salt_bytes[6] as u32) << 8 | salt_bytes[7] as u32,
597 (salt_bytes[8] as u32) << 24 | (salt_bytes[9] as u32) << 16 | (salt_bytes[10] as u32) << 8 | salt_bytes[11] as u32,
598 (salt_bytes[12] as u32) << 24 | (salt_bytes[13] as u32) << 16 | (salt_bytes[14] as u32) << 8 | salt_bytes[15] as u32,
599 ];
600
601 let flags = BF_FLAGS_BY_SUBTYPE[st_idx];
602 let mut expanded = [0u32; 18];
603 let mut initial = [0u32; 18];
604 bf_set_key(key, &mut expanded, &mut initial, flags);
605
606 let mut ps = [0u32; 18 + 4 * 256];
607 ps[..18].copy_from_slice(&initial);
608 ps[18..274].copy_from_slice(&BF_S0);
609 ps[274..530].copy_from_slice(&BF_S1);
610 ps[530..786].copy_from_slice(&BF_S2);
611 ps[786..1042].copy_from_slice(&BF_S3);
612
613 let (mut l, mut r) = (0u32, 0u32);
614 let mut i = 0usize;
615 while i < ps.len() {
616 let (nl, nr) = bf_encrypt_block(&ps, l ^ salt_words[0], r ^ salt_words[1]);
617 ps[i] = nl;
618 ps[i + 1] = nr;
619 l = nl; r = nr;
620 i += 2;
621 if i >= ps.len() { break; }
622 let (nl2, nr2) = bf_encrypt_block(&ps, l ^ salt_words[2], r ^ salt_words[3]);
623 ps[i] = nl2;
624 ps[i + 1] = nr2;
625 l = nl2; r = nr2;
626 i += 2;
627 }
628
629 for _ in 0..count {
630 for i in 0..BF_N + 2 {
631 ps[i] ^= expanded[i];
632 }
633 bf_encrypt_full(&mut ps, 0, 0);
634 for i in (0..BF_N).step_by(4) {
635 ps[i] ^= salt_words[0];
636 ps[i + 1] ^= salt_words[1];
637 ps[i + 2] ^= salt_words[2];
638 ps[i + 3] ^= salt_words[3];
639 }
640 ps[16] ^= salt_words[0];
641 ps[17] ^= salt_words[1];
642 bf_encrypt_full(&mut ps, 0, 0);
643 }
644
645 let mut output_words = [0u32; 6];
647 for i in (0..6).step_by(2) {
648 let mut l = BF_MAGIC_W[i];
649 let mut r = BF_MAGIC_W[i + 1];
650 for _ in 0..64 {
651 let (nl, nr) = bf_encrypt_block(&ps, l, r);
652 l = nl; r = nr;
653 }
654 output_words[i] = l;
655 output_words[i + 1] = r;
656 }
657
658 output[..7 + 22 - 1].copy_from_slice(&setting[..7 + 22 - 1]);
660 output[7 + 22 - 1] = BF_ITOA64[(BF_ATOI64[setting[7 + 22 - 1] as usize - 0x20] & 0x30) as usize];
661 for w in output_words.iter_mut() { *w = w.swap_bytes(); }
662 let enc_src: &[u8] = unsafe { core::slice::from_raw_parts(output_words.as_ptr() as *const u8, 24) };
663 bf_encode(&mut output[7 + 22..], &enc_src[..23]);
664 output[7 + 22 + 31] = 0;
665 Some(7 + 22 + 31)
666}
667
668#[inline(always)]
670fn bf_encrypt_full(ps: &mut [u32; 1042], mut l: u32, mut r: u32) {
671 let p = ps.as_mut_ptr();
672 let s0 = unsafe { p.add(18) };
673 let s1 = unsafe { p.add(274) };
674 let s2 = unsafe { p.add(530) };
675 let s3 = unsafe { p.add(786) };
676 let mut ptr = 0usize;
677 while ptr < 1042 {
678 l ^= unsafe { *p };
679 for i in (0..16).step_by(2) {
680 let mut tmp = unsafe { *s0.add((l >> 24) as usize) };
681 tmp = tmp.wrapping_add(unsafe { *s1.add(((l >> 16) & 0xFF) as usize) });
682 tmp ^= unsafe { *s2.add(((l >> 8) & 0xFF) as usize) };
683 tmp = tmp.wrapping_add(unsafe { *s3.add((l & 0xFF) as usize) });
684 r ^= unsafe { *p.add(i + 1) }; r ^= tmp;
685 let tl = r; r = l; l = tl;
686
687 let mut tmp2 = unsafe { *s0.add((l >> 24) as usize) };
688 tmp2 = tmp2.wrapping_add(unsafe { *s1.add(((l >> 16) & 0xFF) as usize) });
689 tmp2 ^= unsafe { *s2.add(((l >> 8) & 0xFF) as usize) };
690 tmp2 = tmp2.wrapping_add(unsafe { *s3.add((l & 0xFF) as usize) });
691 r ^= unsafe { *p.add(i + 2) }; r ^= tmp2;
692 let tl2 = r; r = l; l = tl2;
693 }
694 let old_r = r ^ unsafe { *p.add(BF_N + 1) };
695 r = l;
696 l = old_r;
697 unsafe {
698 *p.add(ptr) = l;
699 *p.add(ptr + 1) = r;
700 }
701 ptr += 2;
702 }
703}
704
705fn bf_set_key(key: &[u8], expanded: &mut [u32; 18], initial: &mut [u32; 18], flags: u8) {
706 let bug = flags & 1;
707 let safety: u32 = ((flags & 2) as u32) << 15;
708 let mut sign: u32 = 0;
709 let mut diff: u32 = 0;
710 let mut ptr = 0usize;
711 let klen = key.len();
712
713 for i in 0..BF_N + 2 {
714 let mut tmp = [0u32; 2];
715 for j in 0..4 {
716 let b = key[ptr];
717 tmp[0] = (tmp[0] << 8) | (b as u32);
718 tmp[1] = (tmp[1] << 8) | ((b as i8 as i32) as u32);
719 if j != 0 { sign |= tmp[1] & 0x80; }
720 if b == 0 {
721 ptr = 0;
722 } else {
723 ptr += 1;
724 if ptr >= klen { ptr = 0; }
725 }
726 }
727 diff |= tmp[0] ^ tmp[1];
728 expanded[i] = tmp[bug as usize];
729 initial[i] = BF_INIT_P[i] ^ tmp[bug as usize];
730 }
731
732 diff |= diff >> 16;
733 diff &= 0xffff;
734 diff = diff.wrapping_add(0xffff);
735 sign <<= 9;
736 sign &= !diff & safety;
737 initial[0] ^= sign;
738}
739
740fn bf_decode(dst: &mut [u8], src: &[u8]) -> bool {
741 let mut di = 0usize;
742 let mut si = 0usize;
743 while di < dst.len() {
744 if si + 1 >= src.len() { return true; }
745 let c1 = src[si] as usize;
746 let c2 = src[si + 1] as usize;
747 if c1 < 0x20 || c1 >= 0x80 || c2 < 0x20 || c2 >= 0x80 { return true; }
748 let v1 = BF_ATOI64[c1 - 0x20];
749 let v2 = BF_ATOI64[c2 - 0x20];
750 if v1 > 63 || v2 > 63 { return true; }
751 dst[di] = (v1 << 2) | ((v2 & 0x30) >> 4);
752 di += 1;
753 si += 2;
754 if di >= dst.len() { break; }
755
756 if si >= src.len() { return true; }
757 let c3 = src[si] as usize;
758 si += 1;
759 if c3 < 0x20 || c3 >= 0x80 { return true; }
760 let v3 = BF_ATOI64[c3 - 0x20];
761 if v3 > 63 { return true; }
762 dst[di] = ((v2 & 0x0F) << 4) | ((v3 & 0x3C) >> 2);
763 di += 1;
764 if di >= dst.len() { break; }
765
766 if si >= src.len() { return true; }
767 let c4 = src[si] as usize;
768 si += 1;
769 if c4 < 0x20 || c4 >= 0x80 { return true; }
770 let v4 = BF_ATOI64[c4 - 0x20];
771 if v4 > 63 { return true; }
772 dst[di] = ((v3 & 0x03) << 6) | v4;
773 di += 1;
774 }
775 false
776}
777
778fn bf_encode(dst: &mut [u8], src: &[u8]) {
779 let mut di = 0usize;
780 let mut si = 0usize;
781 while si < src.len() {
782 let c1 = src[si] as usize;
783 dst[di] = BF_ITOA64[c1 >> 2]; di += 1;
784 let c1_left = (c1 & 0x03) << 4;
785 si += 1;
786 if si >= src.len() { dst[di] = BF_ITOA64[c1_left]; break; }
787 let c2 = src[si] as usize;
788 dst[di] = BF_ITOA64[c1_left | (c2 >> 4)]; di += 1;
789 let c2_left = (c2 & 0x0f) << 2;
790 si += 1;
791 if si >= src.len() { dst[di] = BF_ITOA64[c2_left]; break; }
792 let c3 = src[si] as usize;
793 dst[di] = BF_ITOA64[c2_left | (c3 >> 6)]; di += 1;
794 dst[di] = BF_ITOA64[c3 & 0x3f]; di += 1;
795 si += 1;
796 }
797}
798
799#[no_mangle]
800pub unsafe extern "C" fn __crypt_blowfish(key: *const c_char, setting: *const c_char, output: *mut c_char) -> *mut c_char {
801 let ks = cstr_bytes(key);
802 let ss = cstr_bytes(setting);
803 let out = core::slice::from_raw_parts_mut(output as *mut u8, 256);
804
805 let mut key_buf = [0u8; 128];
806 if ks.len() >= key_buf.len() {
807 *output = b'*' as c_char;
808 *output.add(1) = 0;
809 return output;
810 }
811 key_buf[..ks.len()].copy_from_slice(ks);
812
813 let retval = bf_crypt_inner(&key_buf[..ks.len() + 1], ss, out, 16);
814 if retval.is_some() {
815 out[retval.unwrap()] = 0;
816 return output;
817 }
818 *output = b'*' as c_char;
819 *output.add(1) = 0;
820 output
821}
822
823#[no_mangle]
828pub unsafe extern "C" fn __crypt_r(key: *const c_char, setting: *const c_char, data: *mut crate::c_void) -> *mut c_char {
829 let output = data as *mut c_char;
830 let s = setting as *const u8;
831 if *s == b'$' && *s.add(1) != 0 && *s.add(2) != 0 {
832 if *s.add(1) == b'1' && *s.add(2) == b'$' {
833 return __crypt_md5(key, setting, output);
834 }
835 if *s.add(1) == b'2' && *s.add(3) == b'$' {
836 return __crypt_blowfish(key, setting, output);
837 }
838 if *s.add(1) == b'5' && *s.add(2) == b'$' {
839 return __crypt_sha256(key, setting, output);
840 }
841 if *s.add(1) == b'6' && *s.add(2) == b'$' {
842 return __crypt_sha512(key, setting, output);
843 }
844 }
845 *output = b'*' as c_char;
847 *output.add(1) = 0;
848 output
849}
850
851static mut CRYPT_BUF: [u8; 128] = [0; 128];
852
853#[no_mangle]
854pub unsafe extern "C" fn crypt(key: *const c_char, setting: *const c_char) -> *mut c_char {
855 __crypt_r(key, setting, core::ptr::addr_of_mut!(CRYPT_BUF) as *mut crate::c_void)
856}
857
858#[no_mangle]
859pub unsafe extern "C" fn crypt_r(key: *const c_char, setting: *const c_char, data: *mut crate::c_void) -> *mut c_char {
860 __crypt_r(key, setting, data)
861}