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 }