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 }