summary refs log tree commit diff
path: root/crypto/src/pqc/crypto/saber/Symmetric.cs
blob: dc47b87bba6637ddea18fc7e610d56ce52df9340 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace Org.BouncyCastle.Pqc.Crypto.Saber;

public abstract class Symmetric
{

    internal abstract void Hash_h(byte[] output, byte[] input, int outputOffset);

    internal abstract void Hash_g(byte[] output, byte[] input);

    internal abstract void Prf(byte[] output, byte[] input, int inLen, int outputLen);

    protected internal class ShakeSymmetric
        : Symmetric
    {

        private readonly Sha3Digest sha3Digest256;
        private readonly Sha3Digest sha3Digest512;
        private readonly IXof shakeDigest;

        internal ShakeSymmetric()
        {
            shakeDigest = new ShakeDigest(128);
            sha3Digest256 = new Sha3Digest(256);
            sha3Digest512 = new Sha3Digest(512);
        }

        internal override void Hash_h(byte[] output, byte[] input, int outputOffset)
        {
            sha3Digest256.BlockUpdate(input, 0, input.Length);
            sha3Digest256.DoFinal(output, outputOffset);
        }

        internal override void Hash_g(byte[] output, byte[] input)
        {
            sha3Digest512.BlockUpdate(input, 0, input.Length);
            sha3Digest512.DoFinal(output, 0);
        }

        internal override void Prf(byte[] output, byte[] input, int inLen, int outputLen)
        {
            shakeDigest.Reset();
            shakeDigest.BlockUpdate(input, 0, inLen);
            shakeDigest.OutputFinal(output, 0, outputLen);
        }


    }
    internal class AesSymmetric
        : Symmetric
    {

        private readonly Sha256Digest sha256Digest;
        private readonly Sha512Digest sha512Digest;

        private readonly SicBlockCipher cipher;


        protected internal AesSymmetric()
        {
            sha256Digest = new Sha256Digest();
            sha512Digest = new Sha512Digest();
            cipher = new SicBlockCipher(AesUtilities.CreateEngine());
        }
        
        internal override void Hash_h(byte[] output, byte[] input, int outputOffset)
        {
            sha256Digest.BlockUpdate(input, 0, input.Length);
            sha256Digest.DoFinal(output, outputOffset);
        }

        internal override void Hash_g(byte[] output, byte[] input)
        {
            sha512Digest.BlockUpdate(input, 0, input.Length);
            sha512Digest.DoFinal(output, 0);
        }

        internal override void Prf(byte[] output, byte[] input, int inLen, int outputLen)
        {
            ParametersWithIV kp = new ParametersWithIV(new KeyParameter(input, 0, inLen), new byte[16]);
            cipher.Init(true, kp);
            byte[] buf = new byte[outputLen];   // TODO: there might be a more efficient way of doing this...
            for (int i = 0; i < outputLen; i+= 16)
            {
                cipher.ProcessBlock(buf, i, output, i);
            }
        }


    }

}