1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.crypto.provider; 27 28 import java.io.IOException; 29 import java.security.AlgorithmParametersSpi; 30 import java.security.spec.AlgorithmParameterSpec; 31 import java.security.spec.InvalidParameterSpecException; 32 import javax.crypto.spec.GCMParameterSpec; 33 import sun.misc.HexDumpEncoder; 34 import sun.security.util.*; 35 36 /** 37 * This class implements the parameter set used with 38 * GCM encryption, which is defined in RFC 5084 as follows: 39 * 40 * <pre> 41 * GCMParameters ::= SEQUENCE { 42 * aes-iv OCTET STRING, -- recommended size is 12 octets 43 * aes-tLen AES-GCM-ICVlen DEFAULT 12 } 44 * 45 * AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16) 46 * 47 * </pre> 48 * 49 * @author Valerie Peng 50 * @since 1.8 51 */ 52 public final class GCMParameters extends AlgorithmParametersSpi { 53 54 // the iv 55 private byte[] iv; 56 // the tag length in bytes 57 private int tLen; 58 59 public GCMParameters() {} 60 61 protected void engineInit(AlgorithmParameterSpec paramSpec) 62 throws InvalidParameterSpecException { 63 64 if (!(paramSpec instanceof GCMParameterSpec)) { 65 throw new InvalidParameterSpecException 66 ("Inappropriate parameter specification"); 67 } 68 GCMParameterSpec gps = (GCMParameterSpec) paramSpec; 69 // need to convert from bits to bytes for ASN.1 encoding 70 this.tLen = gps.getTLen()/8; 71 this.iv = gps.getIV(); 72 } 73 74 protected void engineInit(byte[] encoded) throws IOException { 75 DerValue val = new DerValue(encoded); 76 // check if IV or params 77 if (val.tag == DerValue.tag_Sequence) { 78 byte[] iv = val.data.getOctetString(); 79 int tLen; 80 if (val.data.available() != 0) { 81 tLen = val.data.getInteger(); 82 if (tLen < 12 || tLen > 16 ) { 83 throw new IOException 84 ("GCM parameter parsing error: unsupported tag len: " + 85 tLen); 86 } 87 if (val.data.available() != 0) { 88 throw new IOException 89 ("GCM parameter parsing error: extra data"); 90 } 91 } else { 92 tLen = 12; 93 } 94 this.iv = iv.clone(); 95 this.tLen = tLen; 96 } else { 97 throw new IOException("GCM parameter parsing error: no SEQ tag"); 98 } 99 } 100 101 protected void engineInit(byte[] encoded, String decodingMethod) 102 throws IOException { 103 engineInit(encoded); 104 } 105 106 protected <T extends AlgorithmParameterSpec> 107 T engineGetParameterSpec(Class<T> paramSpec) 108 throws InvalidParameterSpecException { 109 110 if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) { 111 return paramSpec.cast(new GCMParameterSpec(tLen * 8, iv)); 112 } else { 113 throw new InvalidParameterSpecException 114 ("Inappropriate parameter specification"); 115 } 116 } 117 118 protected byte[] engineGetEncoded() throws IOException { 119 DerOutputStream out = new DerOutputStream(); 120 DerOutputStream bytes = new DerOutputStream(); 121 122 bytes.putOctetString(iv); 123 bytes.putInteger(tLen); 124 out.write(DerValue.tag_Sequence, bytes); 125 return out.toByteArray(); 126 } 127 128 protected byte[] engineGetEncoded(String encodingMethod) 129 throws IOException { 130 return engineGetEncoded(); 131 } 132 133 /* 134 * Returns a formatted string describing the parameters. 135 */ 136 protected String engineToString() { 137 String LINE_SEP = System.getProperty("line.separator"); 138 HexDumpEncoder encoder = new HexDumpEncoder(); 139 StringBuilder sb = new StringBuilder(); 140 sb.append(LINE_SEP).append(" iv:").append(LINE_SEP).append('[') 141 .append(encoder.encodeBuffer(iv)).append(']').append(LINE_SEP) 142 .append("tLen(bits):").append(LINE_SEP).append(tLen * 8) 143 .append(LINE_SEP); 144 return sb.toString(); 145 } 146 }