v2 / vlib / crypto / cipher / cfb.v
98 lines · 84 sloc · 2.24 KB · 3aed78e76ab5a0764bfb4bff28b8ab6eb540c236
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// Cipher Feedback Mode (CFB).
7// See NIST SP 800-38A, pp 11-13
8
9module cipher
10
11import crypto.internal.subtle
12
13struct Cfb {
14mut:
15 b Block
16 next []u8
17 out []u8
18 out_used int
19
20 decrypt bool
21}
22
23// free the resources taken by the Cfb `x`
24@[unsafe]
25pub fn (mut x Cfb) free() {
26 $if prealloc {
27 return
28 }
29 unsafe {
30 // x.b.free() TODO add?
31 x.out.free()
32 x.next.free()
33 }
34}
35
36// new_cfb_encrypter returns a `Cfb` which encrypts with cipher feedback mode,
37// using the given Block. The iv must be the same length as the Block's block
38// size
39pub fn new_cfb_encrypter(b Block, iv []u8) Cfb {
40 return new_cfb(b, iv, false)
41}
42
43// new_cfb_decrypter returns a `Cfb` which decrypts with cipher feedback mode,
44// using the given Block. The iv must be the same length as the Block's block
45// size
46pub fn new_cfb_decrypter(b Block, iv []u8) Cfb {
47 return new_cfb(b, iv, true)
48}
49
50fn new_cfb(b Block, iv []u8, decrypt bool) Cfb {
51 block_size := b.block_size
52 if iv.len != block_size {
53 panic('cipher.new_cfb: IV length must be equal block size')
54 }
55 mut x := Cfb{
56 b: b
57 out: []u8{len: b.block_size}
58 next: []u8{len: b.block_size}
59 out_used: block_size
60 decrypt: decrypt
61 }
62 copy(mut x.next, iv)
63 return x
64}
65
66// xor_key_stream xors each byte in the given slice with a byte from the key stream.
67pub fn (mut x Cfb) xor_key_stream(mut dst []u8, src []u8) {
68 unsafe {
69 mut local_dst := *dst
70 mut local_src := src
71 if local_dst.len < local_src.len {
72 panic('crypto.cipher.xor_key_stream: output smaller than input')
73 }
74
75 if subtle.inexact_overlap(local_dst[..src.len], local_src) {
76 panic('crypto.cipher.xor_key_stream: invalid buffer overlap')
77 }
78
79 for local_src.len > 0 {
80 if x.out_used == x.out.len {
81 x.b.encrypt(mut x.out, x.next)
82 x.out_used = 0
83 }
84
85 if x.decrypt {
86 copy(mut x.next[x.out_used..], local_src)
87 }
88
89 n := xor_bytes(mut local_dst, local_src, x.out[x.out_used..])
90 if !x.decrypt {
91 copy(mut x.next[x.out_used..], local_dst)
92 }
93 local_dst = local_dst[n..]
94 local_src = local_src[n..]
95 x.out_used += n
96 }
97 }
98}
99