1 /* 2 * Copyright (c) 1997, 2020, 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 java.security; 27 28 import java.security.spec.AlgorithmParameterSpec; 29 import java.util.*; 30 import java.io.*; 31 32 import java.nio.ByteBuffer; 33 34 import sun.security.jca.JCAUtil; 35 36 /** 37 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) 38 * for the {@code Signature} class, which is used to provide the 39 * functionality of a digital signature algorithm. Digital signatures are used 40 * for authentication and integrity assurance of digital data. 41 * 42 * <p> All the abstract methods in this class must be implemented by each 43 * cryptographic service provider who wishes to supply the implementation 44 * of a particular signature algorithm. 45 * 46 * @author Benjamin Renaud 47 * @since 1.2 48 * 49 * 50 * @see Signature 51 */ 52 53 public abstract class SignatureSpi { 54 55 /** 56 * Constructor for subclasses to call. 57 */ SignatureSpi()58 public SignatureSpi() {} 59 60 /** 61 * Application-specified source of randomness. 62 */ 63 protected SecureRandom appRandom = null; 64 65 /** 66 * Initializes this signature object with the specified 67 * public key for verification operations. 68 * 69 * @param publicKey the public key of the identity whose signature is 70 * going to be verified. 71 * 72 * @throws InvalidKeyException if the key is improperly 73 * encoded, parameters are missing, and so on. 74 */ engineInitVerify(PublicKey publicKey)75 protected abstract void engineInitVerify(PublicKey publicKey) 76 throws InvalidKeyException; 77 78 /** 79 * Initializes this signature object with the specified 80 * public key for verification operations. 81 * 82 * @param publicKey the public key of the identity whose signature is 83 * going to be verified. 84 * @param params the parameters for generating this signature 85 * 86 * @throws InvalidKeyException if the key is improperly 87 * encoded, does not work with the given parameters, and so on. 88 * @throws InvalidAlgorithmParameterException if the given parameters 89 * is invalid. 90 */ engineInitVerify(PublicKey publicKey, AlgorithmParameterSpec params)91 void engineInitVerify(PublicKey publicKey, 92 AlgorithmParameterSpec params) 93 throws InvalidKeyException, InvalidAlgorithmParameterException { 94 if (params != null) { 95 try { 96 engineSetParameter(params); 97 } catch (UnsupportedOperationException usoe) { 98 // error out if not overridden 99 throw new InvalidAlgorithmParameterException(usoe); 100 } 101 } 102 engineInitVerify(publicKey); 103 } 104 105 /** 106 * Initializes this signature object with the specified 107 * private key for signing operations. 108 * 109 * @param privateKey the private key of the identity whose signature 110 * will be generated. 111 * 112 * @throws InvalidKeyException if the key is improperly 113 * encoded, parameters are missing, and so on. 114 */ engineInitSign(PrivateKey privateKey)115 protected abstract void engineInitSign(PrivateKey privateKey) 116 throws InvalidKeyException; 117 118 /** 119 * Initializes this signature object with the specified 120 * private key and source of randomness for signing operations. 121 * 122 * <p>This concrete method has been added to this previously-defined 123 * abstract class. (For backwards compatibility, it cannot be abstract.) 124 * 125 * @param privateKey the private key of the identity whose signature 126 * will be generated. 127 * @param random the source of randomness 128 * 129 * @throws InvalidKeyException if the key is improperly 130 * encoded, parameters are missing, and so on. 131 */ engineInitSign(PrivateKey privateKey, SecureRandom random)132 protected void engineInitSign(PrivateKey privateKey, 133 SecureRandom random) 134 throws InvalidKeyException { 135 this.appRandom = random; 136 engineInitSign(privateKey); 137 } 138 139 /** 140 * Initializes this signature object with the specified 141 * private key and source of randomness for signing operations. 142 * 143 * <p>This concrete method has been added to this previously-defined 144 * abstract class. (For backwards compatibility, it cannot be abstract.) 145 * 146 * @param privateKey the private key of the identity whose signature 147 * will be generated. 148 * @param params the parameters for generating this signature 149 * @param random the source of randomness 150 * 151 * @throws InvalidKeyException if the key is improperly 152 * encoded, parameters are missing, and so on. 153 * @throws InvalidAlgorithmParameterException if the parameters is 154 * invalid. 155 */ engineInitSign(PrivateKey privateKey, AlgorithmParameterSpec params, SecureRandom random)156 void engineInitSign(PrivateKey privateKey, 157 AlgorithmParameterSpec params, SecureRandom random) 158 throws InvalidKeyException, InvalidAlgorithmParameterException { 159 if (params != null) { 160 try { 161 engineSetParameter(params); 162 } catch (UnsupportedOperationException usoe) { 163 // error out if not overridden 164 throw new InvalidAlgorithmParameterException(usoe); 165 } 166 } 167 engineInitSign(privateKey, random); 168 } 169 170 /** 171 * Updates the data to be signed or verified 172 * using the specified byte. 173 * 174 * @param b the byte to use for the update. 175 * 176 * @throws SignatureException if the engine is not initialized 177 * properly. 178 */ engineUpdate(byte b)179 protected abstract void engineUpdate(byte b) throws SignatureException; 180 181 /** 182 * Updates the data to be signed or verified, using the 183 * specified array of bytes, starting at the specified offset. 184 * 185 * @param b the array of bytes 186 * @param off the offset to start from in the array of bytes 187 * @param len the number of bytes to use, starting at offset 188 * 189 * @throws SignatureException if the engine is not initialized 190 * properly 191 */ engineUpdate(byte[] b, int off, int len)192 protected abstract void engineUpdate(byte[] b, int off, int len) 193 throws SignatureException; 194 195 /** 196 * Updates the data to be signed or verified using the specified 197 * ByteBuffer. Processes the {@code data.remaining()} bytes 198 * starting at {@code data.position()}. 199 * Upon return, the buffer's position will be equal to its limit; 200 * its limit will not have changed. 201 * 202 * @param input the ByteBuffer 203 * @since 1.5 204 */ engineUpdate(ByteBuffer input)205 protected void engineUpdate(ByteBuffer input) { 206 if (input.hasRemaining() == false) { 207 return; 208 } 209 try { 210 if (input.hasArray()) { 211 byte[] b = input.array(); 212 int ofs = input.arrayOffset(); 213 int pos = input.position(); 214 int lim = input.limit(); 215 engineUpdate(b, ofs + pos, lim - pos); 216 input.position(lim); 217 } else { 218 int len = input.remaining(); 219 byte[] b = new byte[JCAUtil.getTempArraySize(len)]; 220 while (len > 0) { 221 int chunk = Math.min(len, b.length); 222 input.get(b, 0, chunk); 223 engineUpdate(b, 0, chunk); 224 len -= chunk; 225 } 226 } 227 } catch (SignatureException e) { 228 // is specified to only occur when the engine is not initialized 229 // this case should never occur as it is caught in Signature.java 230 throw new ProviderException("update() failed", e); 231 } 232 } 233 234 /** 235 * Returns the signature bytes of all the data 236 * updated so far. 237 * The format of the signature depends on the underlying 238 * signature scheme. 239 * 240 * @return the signature bytes of the signing operation's result. 241 * 242 * @throws SignatureException if the engine is not 243 * initialized properly or if this signature algorithm is unable to 244 * process the input data provided. 245 */ engineSign()246 protected abstract byte[] engineSign() throws SignatureException; 247 248 /** 249 * Finishes this signature operation and stores the resulting signature 250 * bytes in the provided buffer {@code outbuf}, starting at 251 * {@code offset}. 252 * The format of the signature depends on the underlying 253 * signature scheme. 254 * 255 * <p>The signature implementation is reset to its initial state 256 * (the state it was in after a call to one of the 257 * {@code engineInitSign} methods) 258 * and can be reused to generate further signatures with the same private 259 * key. 260 * 261 * This method should be abstract, but we leave it concrete for 262 * binary compatibility. Knowledgeable providers should override this 263 * method. 264 * 265 * @param outbuf buffer for the signature result. 266 * 267 * @param offset offset into {@code outbuf} where the signature is 268 * stored. 269 * 270 * @param len number of bytes within {@code outbuf} allotted for the 271 * signature. 272 * Both this default implementation and the SUN provider do not 273 * return partial digests. If the value of this parameter is less 274 * than the actual signature length, this method will throw a 275 * SignatureException. 276 * This parameter is ignored if its value is greater than or equal to 277 * the actual signature length. 278 * 279 * @return the number of bytes placed into {@code outbuf} 280 * 281 * @throws SignatureException if the engine is not 282 * initialized properly, if this signature algorithm is unable to 283 * process the input data provided, or if {@code len} is less 284 * than the actual signature length. 285 * 286 * @since 1.2 287 */ engineSign(byte[] outbuf, int offset, int len)288 protected int engineSign(byte[] outbuf, int offset, int len) 289 throws SignatureException { 290 byte[] sig = engineSign(); 291 if (len < sig.length) { 292 throw new SignatureException 293 ("partial signatures not returned"); 294 } 295 if (outbuf.length - offset < sig.length) { 296 throw new SignatureException 297 ("insufficient space in the output buffer to store the " 298 + "signature"); 299 } 300 System.arraycopy(sig, 0, outbuf, offset, sig.length); 301 return sig.length; 302 } 303 304 /** 305 * Verifies the passed-in signature. 306 * 307 * @param sigBytes the signature bytes to be verified. 308 * 309 * @return true if the signature was verified, false if not. 310 * 311 * @throws SignatureException if the engine is not 312 * initialized properly, the passed-in signature is improperly 313 * encoded or of the wrong type, if this signature algorithm is unable to 314 * process the input data provided, etc. 315 */ engineVerify(byte[] sigBytes)316 protected abstract boolean engineVerify(byte[] sigBytes) 317 throws SignatureException; 318 319 /** 320 * Verifies the passed-in signature in the specified array 321 * of bytes, starting at the specified offset. 322 * 323 * <p> Note: Subclasses should overwrite the default implementation. 324 * 325 * 326 * @param sigBytes the signature bytes to be verified. 327 * @param offset the offset to start from in the array of bytes. 328 * @param length the number of bytes to use, starting at offset. 329 * 330 * @return true if the signature was verified, false if not. 331 * 332 * @throws SignatureException if the engine is not 333 * initialized properly, the passed-in signature is improperly 334 * encoded or of the wrong type, if this signature algorithm is unable to 335 * process the input data provided, etc. 336 * @since 1.4 337 */ engineVerify(byte[] sigBytes, int offset, int length)338 protected boolean engineVerify(byte[] sigBytes, int offset, int length) 339 throws SignatureException { 340 byte[] sigBytesCopy = new byte[length]; 341 System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length); 342 return engineVerify(sigBytesCopy); 343 } 344 345 /** 346 * Sets the specified algorithm parameter to the specified 347 * value. This method supplies a general-purpose mechanism through 348 * which it is possible to set the various parameters of this object. 349 * A parameter may be any settable parameter for the algorithm, such as 350 * a parameter size, or a source of random bits for signature generation 351 * (if appropriate), or an indication of whether or not to perform 352 * a specific but optional computation. A uniform algorithm-specific 353 * naming scheme for each parameter is desirable but left unspecified 354 * at this time. 355 * 356 * @param param the string identifier of the parameter. 357 * 358 * @param value the parameter value. 359 * 360 * @throws InvalidParameterException if {@code param} is an 361 * invalid parameter for this signature algorithm engine, 362 * the parameter is already set 363 * and cannot be set again, a security exception occurs, and so on. 364 * 365 * @deprecated Replaced by {@link 366 * #engineSetParameter(java.security.spec.AlgorithmParameterSpec) 367 * engineSetParameter}. 368 */ 369 @Deprecated engineSetParameter(String param, Object value)370 protected abstract void engineSetParameter(String param, Object value) 371 throws InvalidParameterException; 372 373 /** 374 * <p>This method is overridden by providers to initialize 375 * this signature engine with the specified parameter set. 376 * 377 * @param params the parameters 378 * 379 * @throws UnsupportedOperationException if this method is not 380 * overridden by a provider 381 * 382 * @throws InvalidAlgorithmParameterException if this method is 383 * overridden by a provider and the given parameters 384 * are inappropriate for this signature engine 385 */ engineSetParameter(AlgorithmParameterSpec params)386 protected void engineSetParameter(AlgorithmParameterSpec params) 387 throws InvalidAlgorithmParameterException { 388 throw new UnsupportedOperationException(); 389 } 390 391 /** 392 * <p>This method is overridden by providers to return the parameters 393 * used with this signature engine. 394 * 395 * <p> If this signature engine has been initialized with parameters 396 * (by calling {@link #engineSetParameter(AlgorithmParameterSpec)} or 397 * {@link #engineSetParameter(String, Object)}) and the underlying signature 398 * implementation supports returning the parameters as 399 * {@code AlgorithmParameters}, this method returns the same parameters. 400 * If the parameters were not set, this method may return a combination 401 * of default and randomly generated parameter values if the 402 * underlying signature implementation supports it and can successfully 403 * generate them. Otherwise, {@code null} is returned. 404 * 405 * @return the parameters used with this signature engine, or {@code null} 406 * 407 * @throws UnsupportedOperationException if this method is 408 * not overridden by a provider 409 * @since 1.4 410 */ engineGetParameters()411 protected AlgorithmParameters engineGetParameters() { 412 throw new UnsupportedOperationException(); 413 } 414 415 /** 416 * Gets the value of the specified algorithm parameter. 417 * This method supplies a general-purpose mechanism through which it 418 * is possible to get the various parameters of this object. A parameter 419 * may be any settable parameter for the algorithm, such as a parameter 420 * size, or a source of random bits for signature generation (if 421 * appropriate), or an indication of whether or not to perform a 422 * specific but optional computation. A uniform algorithm-specific 423 * naming scheme for each parameter is desirable but left unspecified 424 * at this time. 425 * 426 * @param param the string name of the parameter. 427 * 428 * @return the object that represents the parameter value, or {@code null} if 429 * there is none. 430 * 431 * @throws InvalidParameterException if {@code param} is an 432 * invalid parameter for this engine, or another exception occurs while 433 * trying to get this parameter. 434 * 435 * @deprecated 436 */ 437 @Deprecated engineGetParameter(String param)438 protected abstract Object engineGetParameter(String param) 439 throws InvalidParameterException; 440 441 /** 442 * Returns a clone if the implementation is cloneable. 443 * 444 * @return a clone if the implementation is cloneable. 445 * 446 * @throws CloneNotSupportedException if this is called 447 * on an implementation that does not support {@code Cloneable}. 448 */ clone()449 public Object clone() throws CloneNotSupportedException { 450 if (this instanceof Cloneable) { 451 return super.clone(); 452 } else { 453 throw new CloneNotSupportedException(); 454 } 455 } 456 } 457