xref: /aosp_15_r20/external/tink/go/streamingaead/subtle/subtle_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package subtle_test
18
19import (
20	"bytes"
21	"encoding/hex"
22	"fmt"
23	"io"
24
25	"github.com/google/tink/go/tink"
26)
27
28var (
29	ikm = []byte{
30		0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb,
31		0xc, 0xd, 0xe, 0xf, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
32		0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
33	}
34	aad = []byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
35)
36
37// encrypt generates a random plaintext of size plaintextSize and encrypts it
38// using the cipher. Upon success this function returns the actual plaintext
39// and ciphertext bytes.
40func encrypt(cipher tink.StreamingAEAD, aad []byte, plaintextSize int) ([]byte, []byte, error) {
41	pt := make([]byte, plaintextSize)
42	for i := range pt {
43		pt[i] = byte(i % 253)
44	}
45
46	ctBuf := &bytes.Buffer{}
47	w, err := cipher.NewEncryptingWriter(ctBuf, aad)
48	if err != nil {
49		return nil, nil, fmt.Errorf("cannot create an encrypt writer: %v", err)
50	}
51	n, err := w.Write(pt)
52	if err != nil {
53		return nil, nil, fmt.Errorf("error writing to an encrypt writer: %v", err)
54	}
55	if n != len(pt) {
56		return nil, nil, fmt.Errorf("unexpected number of bytes written. Got=%d;want=%d", n, len(pt))
57	}
58	if err := w.Close(); err != nil {
59		return nil, nil, fmt.Errorf("error closing writer: %v", err)
60	}
61	return pt, ctBuf.Bytes(), err
62}
63
64// decrypt decrypts ciphertext ct using the cipher and validates that it's the
65// same as the original plaintext pt.
66func decrypt(cipher tink.StreamingAEAD, aad, pt, ct []byte, chunkSize int) error {
67	r, err := cipher.NewDecryptingReader(bytes.NewBuffer(ct), aad)
68	if err != nil {
69		return fmt.Errorf("cannot create an encrypt reader: %v", err)
70	}
71
72	var (
73		chunk     = make([]byte, chunkSize)
74		decrypted = 0
75		eof       = false
76	)
77	for !eof {
78		n, err := r.Read(chunk)
79		if err != nil && err != io.EOF {
80			return fmt.Errorf("error reading chunk: %v", err)
81		}
82		eof = err == io.EOF
83		got := chunk[:n]
84		want := pt[decrypted : decrypted+n]
85		if !bytes.Equal(got, want) {
86			return fmt.Errorf("decrypted data doesn't match. Got=%s;want=%s", hex.EncodeToString(got), hex.EncodeToString(want))
87		}
88		decrypted += n
89	}
90	if decrypted != len(pt) {
91		return fmt.Errorf("number of decrypted bytes doesn't match. Got=%d;want=%d", decrypted, len(pt))
92	}
93	return nil
94}
95
96func segmentPos(segmentSize, firstSegmentOffset, headerLen, segmentNr int) (int, int) {
97	start := segmentSize * segmentNr
98	end := start + segmentSize
99
100	firstSegmentDiff := firstSegmentOffset + headerLen
101	if start > 0 {
102		start -= firstSegmentDiff
103	}
104	end -= firstSegmentDiff
105	return start + headerLen, end + headerLen
106}
107