1 package org.bouncycastle.crypto.engines;
2 
3 import org.bouncycastle.crypto.CipherParameters;
4 import org.bouncycastle.crypto.modes.GCFBBlockCipher;
5 import org.bouncycastle.crypto.params.KeyParameter;
6 import org.bouncycastle.crypto.params.ParametersWithIV;
7 import org.bouncycastle.crypto.params.ParametersWithRandom;
8 import org.bouncycastle.crypto.params.ParametersWithSBox;
9 import org.bouncycastle.crypto.params.ParametersWithUKM;
10 import org.bouncycastle.util.Pack;
11 
12 public class CryptoProWrapEngine
13     extends GOST28147WrapEngine
14 {
init(boolean forWrapping, CipherParameters param)15     public void init(boolean forWrapping, CipherParameters param)
16     {
17         if (param instanceof ParametersWithRandom)
18         {
19             ParametersWithRandom pr = (ParametersWithRandom)param;
20             param = pr.getParameters();
21         }
22 
23         ParametersWithUKM pU = (ParametersWithUKM)param;
24         byte[] sBox = null;
25 
26 
27         KeyParameter kParam;
28 
29         if (pU.getParameters() instanceof ParametersWithSBox)
30         {
31             kParam = (KeyParameter)((ParametersWithSBox)pU.getParameters()).getParameters();
32             sBox = ((ParametersWithSBox)pU.getParameters()).getSBox();
33         }
34         else
35         {
36             kParam = (KeyParameter)pU.getParameters();
37         }
38 
39         kParam = new KeyParameter(cryptoProDiversify(kParam.getKey(), pU.getUKM(), sBox));
40 
41         if (sBox != null)
42         {
43             super.init(forWrapping, new ParametersWithUKM(new ParametersWithSBox(kParam, sBox), pU.getUKM()));
44         }
45         else
46         {
47             super.init(forWrapping, new ParametersWithUKM(kParam, pU.getUKM()));
48         }
49     }
50 
51     /*
52          RFC 4357 6.5.  CryptoPro KEK Diversification Algorithm
53 
54          Given a random 64-bit UKM and a GOST 28147-89 key K, this algorithm
55          creates a new GOST 28147-89 key K(UKM).
56 
57           1) Let K[0] = K;
58           2) UKM is split into components a[i,j]:
59              UKM = a[0]|..|a[7] (a[i] - byte, a[i,0]..a[i,7] - it's bits)
60           3) Let i be 0.
61           4) K[1]..K[8] are calculated by repeating the following algorithm
62              eight times:
63            A) K[i] is split into components k[i,j]:
64               K[i] = k[i,0]|k[i,1]|..|k[i,7] (k[i,j] - 32-bit integer)
65            B) Vector S[i] is calculated:
66               S[i] = ((a[i,0]*k[i,0] + ... + a[i,7]*k[i,7]) mod 2^32) |
67               (((~a[i,0])*k[i,0] + ... + (~a[i,7])*k[i,7]) mod 2^32);
68            C) K[i+1] = encryptCFB (S[i], K[i], K[i])
69            D) i = i + 1
70           5) Let K(UKM) be K[8].
71      */
cryptoProDiversify(byte[] K, byte[] ukm, byte[] sBox)72     private static byte[] cryptoProDiversify(byte[] K, byte[] ukm, byte[] sBox)
73     {
74         for (int i = 0; i != 8; i++)
75         {
76             int sOn = 0;
77             int sOff = 0;
78             for (int j = 0; j != 8; j++)
79             {
80                 int kj = Pack.littleEndianToInt(K, j * 4);
81                 if (bitSet(ukm[i], j))
82                 {
83                     sOn += kj;
84                 }
85                 else
86                 {
87                     sOff += kj;
88                 }
89             }
90 
91             byte[] s = new byte[8];
92             Pack.intToLittleEndian(sOn, s, 0);
93             Pack.intToLittleEndian(sOff, s, 4);
94 
95             GCFBBlockCipher c = new GCFBBlockCipher(new GOST28147Engine());
96 
97             c.init(true, new ParametersWithIV(new ParametersWithSBox(new KeyParameter(K), sBox), s));
98 
99             c.processBlock(K, 0, K, 0);
100             c.processBlock(K, 8, K, 8);
101             c.processBlock(K, 16, K, 16);
102             c.processBlock(K, 24, K, 24);
103         }
104 
105         return K;
106     }
107 
bitSet(byte v, int bitNo)108     private static boolean bitSet(byte v, int bitNo)
109     {
110         return (v & (1 << bitNo)) != 0;
111     }
112 }
113