1 /* 2 * Copyright (c) 2018, 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.IvParameterSpec; 33 import sun.security.util.*; 34 35 /** 36 * This class implements the parameter set used with the ChaCha20-Poly1305 37 * algorithm. The parameter definition comes from 38 * <a href="https://tools.ietf.org/html/rfc8103"><i>RFC 8103</i></a> 39 * and is defined according to the following ASN.1: 40 * 41 * <pre> 42 * id-alg-AEADChaCha20Poly1305 OBJECT IDENTIFIER ::= 43 { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 44 pkcs9(9) smime(16) alg(3) 18 } 45 46 * AEADChaCha20Poly1305Nonce ::= OCTET STRING (SIZE(12)) 47 * </pre> 48 * 49 * The AlgorithmParameters may be instantiated either by its name 50 * ("ChaCha20-Poly1305") or via its OID (1.2.840.113549.1.9.16.3.18) 51 */ 52 public final class ChaCha20Poly1305Parameters extends AlgorithmParametersSpi { 53 54 private static final String DEFAULT_FMT = "ASN.1"; 55 private byte[] nonce; 56 ChaCha20Poly1305Parameters()57 public ChaCha20Poly1305Parameters() {} 58 59 /** 60 * Initialize the ChaCha20Poly1305Parameters using an IvParameterSpec. 61 * 62 * @param paramSpec the {@code IvParameterSpec} used to configure 63 * this object. 64 * 65 * @throws InvalidParameterSpecException if an object of a type other 66 * than {@code IvParameterSpec} is used. 67 */ 68 @Override engineInit(AlgorithmParameterSpec paramSpec)69 protected void engineInit(AlgorithmParameterSpec paramSpec) 70 throws InvalidParameterSpecException { 71 72 if (!(paramSpec instanceof IvParameterSpec)) { 73 throw new InvalidParameterSpecException 74 ("Inappropriate parameter specification"); 75 } 76 IvParameterSpec ivps = (IvParameterSpec)paramSpec; 77 78 // Obtain the nonce 79 nonce = ivps.getIV(); 80 if (nonce.length != 12) { 81 throw new InvalidParameterSpecException("ChaCha20-Poly1305 nonce" + 82 " must be 12 bytes in length"); 83 } 84 } 85 86 /** 87 * Initialize the ChaCha20Poly1305Parameters from a DER encoded 88 * parameter block. 89 90 * @param encoded the DER encoding of the nonce as an OCTET STRING. 91 * 92 * @throws IOException if the encoded nonce is not 12 bytes long or a DER 93 * decoding error occurs. 94 */ 95 @Override engineInit(byte[] encoded)96 protected void engineInit(byte[] encoded) throws IOException { 97 DerValue val = new DerValue(encoded); 98 99 // Get the nonce value 100 nonce = val.getOctetString(); 101 if (nonce.length != 12) { 102 throw new IOException( 103 "ChaCha20-Poly1305 nonce must be 12 bytes in length"); 104 } 105 } 106 107 /** 108 * Initialize the ChaCha20Poly1305Parameters from a DER encoded 109 * parameter block. 110 * 111 * @param encoded the DER encoding of the nonce and initial block counter. 112 * @param decodingMethod the decoding method. The only currently accepted 113 * value is "ASN.1" 114 * 115 * @throws IOException if the encoded nonce is not 12 bytes long, a DER 116 * decoding error occurs, or an unsupported decoding method is 117 * provided. 118 */ 119 @Override engineInit(byte[] encoded, String decodingMethod)120 protected void engineInit(byte[] encoded, String decodingMethod) 121 throws IOException { 122 if (decodingMethod == null || 123 decodingMethod.equalsIgnoreCase(DEFAULT_FMT)) { 124 engineInit(encoded); 125 } else { 126 throw new IOException("Unsupported parameter format: " + 127 decodingMethod); 128 } 129 } 130 131 /** 132 * Return an IvParameterSpec with the same parameters as those 133 * held in this object. 134 * 135 * @param paramSpec the class name of the spec. In this case it should 136 * be {@code IvParameterSpec.class}. 137 * 138 * @return a {@code IvParameterSpec} object containing the nonce 139 * value held in this object. 140 * 141 * @throws InvalidParameterSpecException if a class other than 142 * {@code IvParameterSpec.class} was specified in the paramSpec 143 * parameter. 144 */ 145 @Override 146 protected <T extends AlgorithmParameterSpec> engineGetParameterSpec(Class<T> paramSpec)147 T engineGetParameterSpec(Class<T> paramSpec) 148 throws InvalidParameterSpecException { 149 150 if (IvParameterSpec.class.isAssignableFrom(paramSpec)) { 151 return paramSpec.cast(new IvParameterSpec(nonce)); 152 } else { 153 throw new InvalidParameterSpecException 154 ("Inappropriate parameter specification"); 155 } 156 } 157 158 /** 159 * Return the encoded parameters in ASN.1 form. 160 * 161 * @return a byte array containing the DER-encoding for the 162 * ChaCha20-Poly1305 parameters. This will be the nonce 163 * encoded as a DER OCTET STRING. 164 * 165 * @throws IOException if any DER encoding error occurs. 166 */ 167 @Override engineGetEncoded()168 protected byte[] engineGetEncoded() throws IOException { 169 DerOutputStream out = new DerOutputStream(); 170 out.write(DerValue.tag_OctetString, nonce); 171 return out.toByteArray(); 172 } 173 174 /** 175 * Return the encoded parameters in ASN.1 form. 176 * 177 * @param encodingMethod the encoding method to be used. This parameter 178 * must be "ASN.1" as it is the only currently supported encoding 179 * format. If the parameter is {@code null} then the default 180 * encoding format will be used. 181 * 182 * @return a byte array containing the DER-encoding for the 183 * ChaCha20-Poly1305 parameters. 184 * 185 * @throws IOException if any DER encoding error occurs or an unsupported 186 * encoding method is provided. 187 */ 188 @Override engineGetEncoded(String encodingMethod)189 protected byte[] engineGetEncoded(String encodingMethod) 190 throws IOException { 191 if (encodingMethod == null || 192 encodingMethod.equalsIgnoreCase(DEFAULT_FMT)) { 193 return engineGetEncoded(); 194 } else { 195 throw new IOException("Unsupported encoding format: " + 196 encodingMethod); 197 } 198 } 199 200 /** 201 * Creates a formatted string describing the parameters. 202 * 203 * @return a string representation of the ChaCha20 parameters. 204 */ 205 @Override engineToString()206 protected String engineToString() { 207 String LINE_SEP = System.lineSeparator(); 208 HexDumpEncoder encoder = new HexDumpEncoder(); 209 StringBuilder sb = new StringBuilder(LINE_SEP + "nonce:" + 210 LINE_SEP + "[" + encoder.encodeBuffer(nonce) + "]"); 211 return sb.toString(); 212 } 213 } 214