1 package org.bouncycastle.crypto.engines; 2 3 import org.bouncycastle.crypto.CipherParameters; 4 import org.bouncycastle.crypto.InvalidCipherTextException; 5 import org.bouncycastle.crypto.Wrapper; 6 import org.bouncycastle.crypto.macs.GOST28147Mac; 7 import org.bouncycastle.crypto.params.ParametersWithIV; 8 import org.bouncycastle.crypto.params.ParametersWithRandom; 9 import org.bouncycastle.crypto.params.ParametersWithUKM; 10 import org.bouncycastle.util.Arrays; 11 12 public class GOST28147WrapEngine 13 implements Wrapper 14 { 15 private GOST28147Engine cipher = new GOST28147Engine(); 16 private GOST28147Mac mac = new GOST28147Mac(); 17 init(boolean forWrapping, CipherParameters param)18 public void init(boolean forWrapping, CipherParameters param) 19 { 20 if (param instanceof ParametersWithRandom) 21 { 22 ParametersWithRandom pr = (ParametersWithRandom)param; 23 param = pr.getParameters(); 24 } 25 26 ParametersWithUKM pU = (ParametersWithUKM)param; 27 28 cipher.init(forWrapping, pU.getParameters()); 29 30 mac.init(new ParametersWithIV(pU.getParameters(), pU.getUKM())); 31 } 32 getAlgorithmName()33 public String getAlgorithmName() 34 { 35 return "GOST28147Wrap"; 36 } 37 wrap(byte[] input, int inOff, int inLen)38 public byte[] wrap(byte[] input, int inOff, int inLen) 39 { 40 mac.update(input, inOff, inLen); 41 42 byte[] wrappedKey = new byte[inLen + mac.getMacSize()]; 43 44 cipher.processBlock(input, inOff, wrappedKey, 0); 45 cipher.processBlock(input, inOff + 8, wrappedKey, 8); 46 cipher.processBlock(input, inOff + 16, wrappedKey, 16); 47 cipher.processBlock(input, inOff + 24, wrappedKey, 24); 48 49 mac.doFinal(wrappedKey, inLen); 50 51 return wrappedKey; 52 } 53 unwrap(byte[] input, int inOff, int inLen)54 public byte[] unwrap(byte[] input, int inOff, int inLen) 55 throws InvalidCipherTextException 56 { 57 byte[] decKey = new byte[inLen - mac.getMacSize()]; 58 59 cipher.processBlock(input, inOff, decKey, 0); 60 cipher.processBlock(input, inOff + 8, decKey, 8); 61 cipher.processBlock(input, inOff + 16, decKey, 16); 62 cipher.processBlock(input, inOff + 24, decKey, 24); 63 64 byte[] macResult = new byte[mac.getMacSize()]; 65 66 mac.update(decKey, 0, decKey.length); 67 68 mac.doFinal(macResult, 0); 69 70 byte[] macExpected = new byte[mac.getMacSize()]; 71 72 System.arraycopy(input, inOff + inLen - 4, macExpected, 0, mac.getMacSize()); 73 74 if (!Arrays.constantTimeAreEqual(macResult, macExpected)) 75 { 76 throw new IllegalStateException("mac mismatch"); 77 } 78 79 return decKey; 80 } 81 } 82