Coverage Summary for Class: ConcatKDFBytesGenerator (org.ethereum)
Class |
Class, %
|
Method, %
|
Line, %
|
ConcatKDFBytesGenerator |
0%
(0/1)
|
0%
(0/5)
|
0%
(0/43)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package org.ethereum;
21
22 import org.bouncycastle.crypto.DataLengthException;
23 import org.bouncycastle.crypto.DerivationParameters;
24 import org.bouncycastle.crypto.Digest;
25 import org.bouncycastle.crypto.DigestDerivationFunction;
26 import org.bouncycastle.crypto.params.ISO18033KDFParameters;
27 import org.bouncycastle.crypto.params.KDFParameters;
28 import org.bouncycastle.util.Pack;
29
30 /**
31 * Basic KDF generator for derived keys and ivs as defined by NIST SP 800-56A.
32 */
33 public class ConcatKDFBytesGenerator
34 implements DigestDerivationFunction
35 {
36 private int counterStart;
37 private Digest digest;
38 private byte[] shared;
39 private byte[] iv;
40
41 /**
42 * Construct a KDF Parameters generator.
43 * <p>
44 *
45 * @param counterStart
46 * value of counter.
47 * @param digest
48 * the digest to be used as the source of derived keys.
49 */
50 protected ConcatKDFBytesGenerator(int counterStart, Digest digest)
51 {
52 this.counterStart = counterStart;
53 this.digest = digest;
54 }
55
56 public ConcatKDFBytesGenerator(Digest digest) {
57 this(1, digest);
58 }
59
60 public void init(DerivationParameters param)
61 {
62 if (param instanceof KDFParameters)
63 {
64 KDFParameters p = (KDFParameters)param;
65
66 shared = p.getSharedSecret();
67 iv = p.getIV();
68 }
69 else if (param instanceof ISO18033KDFParameters)
70 {
71 ISO18033KDFParameters p = (ISO18033KDFParameters)param;
72
73 shared = p.getSeed();
74 iv = null;
75 }
76 else
77 {
78 throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
79 }
80 }
81
82 /**
83 * return the underlying digest.
84 */
85 public Digest getDigest()
86 {
87 return digest;
88 }
89
90 /**
91 * fill len bytes of the output buffer with bytes generated from the
92 * derivation function.
93 *
94 * @throws IllegalArgumentException
95 * if the size of the request will cause an overflow.
96 * @throws DataLengthException
97 * if the out buffer is too small.
98 */
99 public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
100 IllegalArgumentException
101 {
102 if ((out.length - len) < outOff)
103 {
104 throw new DataLengthException("output buffer too small");
105 }
106
107 long oBytes = len;
108 int outLen = digest.getDigestSize();
109
110 //
111 // this is at odds with the standard implementation, the
112 // maximum value should be hBits * (2^32 - 1) where hBits
113 // is the digest output size in bits. We can't have an
114 // array with a long index at the moment...
115 //
116 if (oBytes > ((2L << 32) - 1))
117 {
118 throw new IllegalArgumentException("Output length too large");
119 }
120
121 int cThreshold = (int)((oBytes + outLen - 1) / outLen);
122
123 byte[] dig = new byte[digest.getDigestSize()];
124
125 byte[] c = new byte[4];
126 Pack.intToBigEndian(counterStart, c, 0);
127
128 int counterBase = counterStart & ~0xFF;
129
130 for (int i = 0; i < cThreshold; i++)
131 {
132 digest.update(c, 0, c.length);
133 digest.update(shared, 0, shared.length);
134
135 if (iv != null)
136 {
137 digest.update(iv, 0, iv.length);
138 }
139
140 digest.doFinal(dig, 0);
141
142 if (len > outLen)
143 {
144 System.arraycopy(dig, 0, out, outOff, outLen);
145 outOff += outLen;
146 len -= outLen;
147 }
148 else
149 {
150 System.arraycopy(dig, 0, out, outOff, len);
151 }
152
153 if (++c[3] == 0)
154 {
155 counterBase += 0x100;
156 Pack.intToBigEndian(counterBase, c, 0);
157 }
158 }
159
160 digest.reset();
161
162 return (int)oBytes;
163 }
164 }