v2 / vlib / crypto / cipher / ofb.v
63 lines · 57 sloc · 1.61 KB · eac02f6be57f81a64b869cc6074b6ec3872c04a7
Raw
1// The source code refers to the go standard library, which will be combined with AES in the future.
2//
3// Use of this source code is governed by an MIT license
4// that can be found in the LICENSE file.
5//
6// OFB (Output Feedback) Mode.
7// See NIST SP 800-38A, pp 13-15
8module cipher
9
10import crypto.internal.subtle
11
12struct Ofb {
13mut:
14 b Block
15 next []u8
16 out []u8
17 out_used int
18}
19
20// new_ofb returns a Ofb that encrypts or decrypts using the block cipher b
21// in output feedback mode. The initialization vector iv's length must be equal
22// to b's block size.
23pub fn new_ofb(b Block, iv []u8) Ofb {
24 block_size := b.block_size
25 if iv.len != block_size {
26 panic('cipher.new_ofb: IV length must be equal block size')
27 }
28 mut x := Ofb{
29 b: b
30 out: []u8{len: b.block_size}
31 next: []u8{len: b.block_size}
32 out_used: block_size
33 }
34 copy(mut x.next, iv)
35 return x
36}
37
38// xor_key_stream xors each byte in the given slice with a byte from the key stream.
39pub fn (mut x Ofb) xor_key_stream(mut dst []u8, src []u8) {
40 unsafe {
41 mut local_dst := *dst
42 mut local_src := src
43 if local_dst.len < local_src.len {
44 panic('crypto.cipher.xor_key_stream: output smaller than input')
45 }
46
47 if subtle.inexact_overlap(local_dst[..local_src.len], local_src) {
48 panic('crypto.cipher.xor_key_stream: invalid buffer overlap')
49 }
50
51 for local_src.len > 0 {
52 if x.out_used == x.out.len {
53 x.b.encrypt(mut x.out, x.next)
54 x.out_used = 0
55 copy(mut x.next, x.out)
56 }
57 n := xor_bytes(mut local_dst, local_src, x.out[x.out_used..])
58 local_dst = local_dst[n..]
59 local_src = local_src[n..]
60 x.out_used += n
61 }
62 }
63}
64