os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

chacha20.om (3560B)


      1 // https://www.rfc-editor.org/rfc/rfc7539
      2 
      3 struct _chacha20_state {
      4 	s0: int;
      5 	s1: int;
      6 	s2: int;
      7 	s3: int;
      8 	s4: int;
      9 	s5: int;
     10 	s6: int;
     11 	s7: int;
     12 	s8: int;
     13 	s9: int;
     14 	s10: int;
     15 	s11: int;
     16 	s12: int;
     17 	s13: int;
     18 	s14: int;
     19 	s15: int;
     20 }
     21 
     22 func rol32(x: int, n: int): int {
     23 	return ((x << n) | (x >> (32 - n))) & (-1 >> 32);
     24 }
     25 
     26 func chacha20_qround(a: *int, b: *int, c: *int, d: *int) {
     27 	*a = (*a + *b) & (-1 >> 32);
     28 	*d = (*d ^ *a) & (-1 >> 32);
     29 	*d = rol32(*d, 16);
     30 
     31 	*c = (*c + *d) & (-1 >> 32);
     32 	*b = (*b ^ *c) & (-1 >> 32);
     33 	*b = rol32(*b, 12);
     34 
     35 	*a = (*a + *b) & (-1 >> 32);
     36 	*d = (*d ^ *a) & (-1 >> 32);
     37 	*d = rol32(*d, 8);
     38 
     39 	*c = (*c + *d) & (-1 >> 32);
     40 	*b = (*b ^ *c) & (-1 >> 32);
     41 	*b = rol32(*b, 7);
     42 }
     43 
     44 func chacha20_block(block: *byte, key: *byte, counter: int, nonce: *byte) {
     45 	var _initial: _chacha20_state;
     46 	var initial: *int;
     47 	var _s: _chacha20_state;
     48 	var s: *int;
     49 	var i: int;
     50 
     51 	initial = (&_initial) as *int;
     52 	s = (&_s) as *int;
     53 
     54 	s[0] = 0x61707865;
     55 	s[1] = 0x3320646e;
     56 	s[2] = 0x79622d32;
     57 	s[3] = 0x6b206574;
     58 
     59 	s[4] = key[0] as int
     60 		| (key[1] as int << 8)
     61 		| (key[2] as int << 16)
     62 		| (key[3] as int << 24);
     63 	s[5] = key[4] as int
     64 		| (key[5] as int << 8)
     65 		| (key[6] as int << 16)
     66 		| (key[7] as int << 24);
     67 	s[6] = key[8] as int
     68 		| (key[9] as int << 8)
     69 		| (key[10] as int << 16)
     70 		| (key[11] as int << 24);
     71 	s[7] = key[12] as int
     72 		| (key[13] as int << 8)
     73 		| (key[14] as int << 16)
     74 		| (key[15] as int << 24);
     75 	s[8] = key[16] as int
     76 		| (key[17] as int << 8)
     77 		| (key[18] as int << 16)
     78 		| (key[19] as int << 24);
     79 	s[9] = key[20] as int
     80 		| (key[21] as int << 8)
     81 		| (key[22] as int << 16)
     82 		| (key[23] as int << 24);
     83 	s[10] = key[24] as int
     84 		| (key[25] as int << 8)
     85 		| (key[26] as int << 16)
     86 		| (key[27] as int << 24);
     87 	s[11] = key[28] as int
     88 		| (key[29] as int << 8)
     89 		| (key[30] as int << 16)
     90 		| (key[31] as int << 24);
     91 
     92 	s[12] = counter & (-1 >> 32);
     93 
     94 	s[13] = nonce[0] as int
     95 		| (nonce[1] as int << 8)
     96 		| (nonce[2] as int << 16)
     97 		| (nonce[3] as int << 24);
     98 	s[14] = nonce[4] as int
     99 		| (nonce[5] as int << 8)
    100 		| (nonce[6] as int << 16)
    101 		| (nonce[7] as int << 24);
    102 	s[15] = nonce[8] as int
    103 		| (nonce[9] as int << 8)
    104 		| (nonce[10] as int << 16)
    105 		| (nonce[11] as int << 24);
    106 
    107 	i = 0;
    108 	loop {
    109 		if i == 16 {
    110 			break;
    111 		}
    112 		initial[i] = s[i];
    113 		i = i + 1;
    114 	}
    115 
    116 	i = 0;
    117 	loop {
    118 		if i == 10 {
    119 			break;
    120 		}
    121 		chacha20_qround(&s[0], &s[4], &s[8], &s[12]);
    122 		chacha20_qround(&s[1], &s[5], &s[9], &s[13]);
    123 		chacha20_qround(&s[2], &s[6], &s[10], &s[14]);
    124 		chacha20_qround(&s[3], &s[7], &s[11], &s[15]);
    125 		chacha20_qround(&s[0], &s[5], &s[10], &s[15]);
    126 		chacha20_qround(&s[1], &s[6], &s[11], &s[12]);
    127 		chacha20_qround(&s[2], &s[7], &s[8], &s[13]);
    128 		chacha20_qround(&s[3], &s[4], &s[9], &s[14]);
    129 		i = i + 1;
    130 	}
    131 
    132 	i = 0;
    133 	loop {
    134 		if i == 16 {
    135 			break;
    136 		}
    137 		s[i] = (s[i] + initial[i]) & (-1 >> 32);
    138 		i = i + 1;
    139 	}
    140 
    141 	i = 0;
    142 	loop {
    143 		if i == 16 {
    144 			break;
    145 		}
    146 		block[i * 4] = s[i] as byte;
    147 		block[i * 4 + 1] = (s[i] >> 8) as byte;
    148 		block[i * 4 + 2] = (s[i] >> 16) as byte;
    149 		block[i * 4 + 3] = (s[i] >> 24) as byte;
    150 		i = i + 1;
    151 	}
    152 }
    153 
    154 func chacha20_stream(cipher: *byte, plain: *byte, len: int, index: *int, key: *byte, nonce: *byte) {
    155 	var _block: _chacha20_state;
    156 	var block: *byte;
    157 	var i: int;
    158 	var j: int;
    159 
    160 	block = (&_block) as *byte;
    161 
    162 	j = 0;
    163 	loop {
    164 		if j == len {
    165 			break;
    166 		}
    167 
    168 		chacha20_block(block, key, index[0] >> 6, nonce);
    169 
    170 		i = index[0] & 63;
    171 		loop {
    172 			if j == len || i == 64 {
    173 				break;
    174 			}
    175 
    176 			cipher[j] = plain[j] ^ block[i];
    177 
    178 			index[0] = index[0] + 1;
    179 			i = i + 1;
    180 			j = j + 1;
    181 		}
    182 	}
    183 }