1 /* 2 * Copyright (c) 2009, 2017, 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 sun.security.ec; 27 28 import java.io.IOException; 29 import java.nio.ByteBuffer; 30 import java.math.BigInteger; 31 32 import java.security.*; 33 import java.security.interfaces.*; 34 import java.security.spec.*; 35 import java.util.Optional; 36 37 import sun.security.jca.JCAUtil; 38 import sun.security.util.*; 39 import static sun.security.ec.ECOperations.IntermediateValueException; 40 41 /** 42 * ECDSA signature implementation. This class currently supports the 43 * following algorithm names: 44 * 45 * . "NONEwithECDSA" 46 * . "SHA1withECDSA" 47 * . "SHA224withECDSA" 48 * . "SHA256withECDSA" 49 * . "SHA384withECDSA" 50 * . "SHA512withECDSA" 51 * 52 * @since 1.7 53 */ 54 abstract class ECDSASignature extends SignatureSpi { 55 56 // message digest implementation we use 57 private final MessageDigest messageDigest; 58 59 // supplied entropy 60 private SecureRandom random; 61 62 // flag indicating whether the digest has been reset 63 private boolean needsReset; 64 65 // private key, if initialized for signing 66 private ECPrivateKey privateKey; 67 68 // public key, if initialized for verifying 69 private ECPublicKey publicKey; 70 71 /** 72 * Constructs a new ECDSASignature. Used by Raw subclass. 73 * 74 * @exception ProviderException if the native ECC library is unavailable. 75 */ 76 ECDSASignature() { 77 messageDigest = null; 78 } 79 80 /** 81 * Constructs a new ECDSASignature. Used by subclasses. 82 */ 83 ECDSASignature(String digestName) { 84 try { 85 messageDigest = MessageDigest.getInstance(digestName); 86 } catch (NoSuchAlgorithmException e) { 87 throw new ProviderException(e); 88 } 89 needsReset = false; 90 } 91 92 // Nested class for NONEwithECDSA signatures 93 public static final class Raw extends ECDSASignature { 94 95 // the longest supported digest is 512 bits (SHA-512) 96 private static final int RAW_ECDSA_MAX = 64; 97 98 private final byte[] precomputedDigest; 99 private int offset = 0; 100 101 public Raw() { 102 precomputedDigest = new byte[RAW_ECDSA_MAX]; 103 } 104 105 // Stores the precomputed message digest value. 106 @Override 107 protected void engineUpdate(byte b) throws SignatureException { 108 if (offset >= precomputedDigest.length) { 109 offset = RAW_ECDSA_MAX + 1; 110 return; 111 } 112 precomputedDigest[offset++] = b; 113 } 114 115 // Stores the precomputed message digest value. 116 @Override 117 protected void engineUpdate(byte[] b, int off, int len) 118 throws SignatureException { 119 if (offset >= precomputedDigest.length) { 120 offset = RAW_ECDSA_MAX + 1; 121 return; 122 } 123 System.arraycopy(b, off, precomputedDigest, offset, len); 124 offset += len; 125 } 126 127 // Stores the precomputed message digest value. 128 @Override 129 protected void engineUpdate(ByteBuffer byteBuffer) { 130 int len = byteBuffer.remaining(); 131 if (len <= 0) { 132 return; 133 } 134 if (offset + len >= precomputedDigest.length) { 135 offset = RAW_ECDSA_MAX + 1; 136 return; 137 } 138 byteBuffer.get(precomputedDigest, offset, len); 139 offset += len; 140 } 141 142 @Override 143 protected void resetDigest() { 144 offset = 0; 145 } 146 147 // Returns the precomputed message digest value. 148 @Override 149 protected byte[] getDigestValue() throws SignatureException { 150 if (offset > RAW_ECDSA_MAX) { 151 throw new SignatureException("Message digest is too long"); 152 153 } 154 byte[] result = new byte[offset]; 155 System.arraycopy(precomputedDigest, 0, result, 0, offset); 156 offset = 0; 157 158 return result; 159 } 160 } 161 162 // Nested class for SHA1withECDSA signatures 163 public static final class SHA1 extends ECDSASignature { 164 public SHA1() { 165 super("SHA1"); 166 } 167 } 168 169 // Nested class for SHA224withECDSA signatures 170 public static final class SHA224 extends ECDSASignature { 171 public SHA224() { 172 super("SHA-224"); 173 } 174 } 175 176 // Nested class for SHA256withECDSA signatures 177 public static final class SHA256 extends ECDSASignature { 178 public SHA256() { 179 super("SHA-256"); 180 } 181 } 182 183 // Nested class for SHA384withECDSA signatures 184 public static final class SHA384 extends ECDSASignature { 185 public SHA384() { 186 super("SHA-384"); 187 } 188 } 189 190 // Nested class for SHA512withECDSA signatures 191 public static final class SHA512 extends ECDSASignature { 192 public SHA512() { 193 super("SHA-512"); 194 } 195 } 196 197 // initialize for verification. See JCA doc 198 @Override 199 protected void engineInitVerify(PublicKey publicKey) 200 throws InvalidKeyException { 201 this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey); 202 203 // Should check that the supplied key is appropriate for signature 204 // algorithm (e.g. P-256 for SHA256withECDSA) 205 this.privateKey = null; 206 resetDigest(); 207 } 208 209 // initialize for signing. See JCA doc 210 @Override 211 protected void engineInitSign(PrivateKey privateKey) 212 throws InvalidKeyException { 213 engineInitSign(privateKey, null); 214 } 215 216 // initialize for signing. See JCA doc 217 @Override 218 protected void engineInitSign(PrivateKey privateKey, SecureRandom random) 219 throws InvalidKeyException { 220 this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey); 221 222 // Should check that the supplied key is appropriate for signature 223 // algorithm (e.g. P-256 for SHA256withECDSA) 224 this.publicKey = null; 225 this.random = random; 226 resetDigest(); 227 } 228 229 /** 230 * Resets the message digest if needed. 231 */ 232 protected void resetDigest() { 233 if (needsReset) { 234 if (messageDigest != null) { 235 messageDigest.reset(); 236 } 237 needsReset = false; 238 } 239 } 240 241 /** 242 * Returns the message digest value. 243 */ 244 protected byte[] getDigestValue() throws SignatureException { 245 needsReset = false; 246 return messageDigest.digest(); 247 } 248 249 // update the signature with the plaintext data. See JCA doc 250 @Override 251 protected void engineUpdate(byte b) throws SignatureException { 252 messageDigest.update(b); 253 needsReset = true; 254 } 255 256 // update the signature with the plaintext data. See JCA doc 257 @Override 258 protected void engineUpdate(byte[] b, int off, int len) 259 throws SignatureException { 260 messageDigest.update(b, off, len); 261 needsReset = true; 262 } 263 264 // update the signature with the plaintext data. See JCA doc 265 @Override 266 protected void engineUpdate(ByteBuffer byteBuffer) { 267 int len = byteBuffer.remaining(); 268 if (len <= 0) { 269 return; 270 } 271 272 messageDigest.update(byteBuffer); 273 needsReset = true; 274 } 275 276 private byte[] signDigestImpl(ECDSAOperations ops, int seedBits, 277 byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random) 278 throws SignatureException { 279 280 byte[] seedBytes = new byte[(seedBits + 7) / 8]; 281 byte[] s = privImpl.getArrayS(); 282 283 // Attempt to create the signature in a loop that uses new random input 284 // each time. The chance of failure is very small assuming the 285 // implementation derives the nonce using extra bits 286 int numAttempts = 128; 287 for (int i = 0; i < numAttempts; i++) { 288 random.nextBytes(seedBytes); 289 ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes); 290 try { 291 return ops.signDigest(s, digest, seed); 292 } catch (IntermediateValueException ex) { 293 // try again in the next iteration 294 } 295 } 296 297 throw new SignatureException("Unable to produce signature after " 298 + numAttempts + " attempts"); 299 } 300 301 302 private Optional<byte[]> signDigestImpl(ECPrivateKey privateKey, 303 byte[] digest, SecureRandom random) throws SignatureException { 304 305 if (! (privateKey instanceof ECPrivateKeyImpl)) { 306 return Optional.empty(); 307 } 308 ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey; 309 ECParameterSpec params = privateKey.getParams(); 310 311 // seed is the key size + 64 bits 312 int seedBits = params.getOrder().bitLength() + 64; 313 Optional<ECDSAOperations> opsOpt = 314 ECDSAOperations.forParameters(params); 315 if (!opsOpt.isPresent()) { 316 return Optional.empty(); 317 } else { 318 byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest, 319 privImpl, random); 320 return Optional.of(sig); 321 } 322 } 323 324 private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest, 325 SecureRandom random) throws SignatureException { 326 327 byte[] s = privateKey.getS().toByteArray(); 328 ECParameterSpec params = privateKey.getParams(); 329 330 // DER OID 331 byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params); 332 int keySize = params.getCurve().getField().getFieldSize(); 333 334 // seed is twice the key size (in bytes) plus 1 335 byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2]; 336 337 random.nextBytes(seed); 338 339 // random bits needed for timing countermeasures 340 int timingArgument = random.nextInt(); 341 // values must be non-zero to enable countermeasures 342 timingArgument |= 1; 343 344 try { 345 return signDigest(digest, s, encodedParams, seed, 346 timingArgument); 347 } catch (GeneralSecurityException e) { 348 throw new SignatureException("Could not sign data", e); 349 } 350 } 351 352 // sign the data and return the signature. See JCA doc 353 @Override 354 protected byte[] engineSign() throws SignatureException { 355 356 if (random == null) { 357 random = JCAUtil.getSecureRandom(); 358 } 359 360 byte[] digest = getDigestValue(); 361 Optional<byte[]> sigOpt = signDigestImpl(privateKey, digest, random); 362 byte[] sig; 363 if (sigOpt.isPresent()) { 364 sig = sigOpt.get(); 365 } else { 366 sig = signDigestNative(privateKey, digest, random); 367 } 368 369 return encodeSignature(sig); 370 } 371 372 // verify the data and return the result. See JCA doc 373 @Override 374 protected boolean engineVerify(byte[] signature) throws SignatureException { 375 376 byte[] w; 377 ECParameterSpec params = publicKey.getParams(); 378 // DER OID 379 byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params); 380 381 if (publicKey instanceof ECPublicKeyImpl) { 382 w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue(); 383 } else { // instanceof ECPublicKey 384 w = ECUtil.encodePoint(publicKey.getW(), params.getCurve()); 385 } 386 387 try { 388 389 return verifySignedDigest( 390 decodeSignature(signature), getDigestValue(), w, encodedParams); 391 392 } catch (GeneralSecurityException e) { 393 throw new SignatureException("Could not verify signature", e); 394 } 395 } 396 397 // set parameter, not supported. See JCA doc 398 @Override 399 @Deprecated 400 protected void engineSetParameter(String param, Object value) 401 throws InvalidParameterException { 402 throw new UnsupportedOperationException("setParameter() not supported"); 403 } 404 405 // get parameter, not supported. See JCA doc 406 @Override 407 @Deprecated 408 protected Object engineGetParameter(String param) 409 throws InvalidParameterException { 410 throw new UnsupportedOperationException("getParameter() not supported"); 411 } 412 413 // Convert the concatenation of R and S into their DER encoding 414 private byte[] encodeSignature(byte[] signature) throws SignatureException { 415 416 try { 417 418 int n = signature.length >> 1; 419 byte[] bytes = new byte[n]; 420 System.arraycopy(signature, 0, bytes, 0, n); 421 BigInteger r = new BigInteger(1, bytes); 422 System.arraycopy(signature, n, bytes, 0, n); 423 BigInteger s = new BigInteger(1, bytes); 424 425 DerOutputStream out = new DerOutputStream(signature.length + 10); 426 out.putInteger(r); 427 out.putInteger(s); 428 DerValue result = 429 new DerValue(DerValue.tag_Sequence, out.toByteArray()); 430 431 return result.toByteArray(); 432 433 } catch (Exception e) { 434 throw new SignatureException("Could not encode signature", e); 435 } 436 } 437 438 // Convert the DER encoding of R and S into a concatenation of R and S 439 private byte[] decodeSignature(byte[] sig) throws SignatureException { 440 441 try { 442 // Enforce strict DER checking for signatures 443 DerInputStream in = new DerInputStream(sig, 0, sig.length, false); 444 DerValue[] values = in.getSequence(2); 445 446 // check number of components in the read sequence 447 // and trailing data 448 if ((values.length != 2) || (in.available() != 0)) { 449 throw new IOException("Invalid encoding for signature"); 450 } 451 452 BigInteger r = values[0].getPositiveBigInteger(); 453 BigInteger s = values[1].getPositiveBigInteger(); 454 455 // trim leading zeroes 456 byte[] rBytes = trimZeroes(r.toByteArray()); 457 byte[] sBytes = trimZeroes(s.toByteArray()); 458 int k = Math.max(rBytes.length, sBytes.length); 459 // r and s each occupy half the array 460 byte[] result = new byte[k << 1]; 461 System.arraycopy(rBytes, 0, result, k - rBytes.length, 462 rBytes.length); 463 System.arraycopy(sBytes, 0, result, result.length - sBytes.length, 464 sBytes.length); 465 return result; 466 467 } catch (Exception e) { 468 throw new SignatureException("Invalid encoding for signature", e); 469 } 470 } 471 472 // trim leading (most significant) zeroes from the result 473 private static byte[] trimZeroes(byte[] b) { 474 int i = 0; 475 while ((i < b.length - 1) && (b[i] == 0)) { 476 i++; 477 } 478 if (i == 0) { 479 return b; 480 } 481 byte[] t = new byte[b.length - i]; 482 System.arraycopy(b, i, t, 0, t.length); 483 return t; 484 } 485 486 /** 487 * Signs the digest using the private key. 488 * 489 * @param digest the digest to be signed. 490 * @param s the private key's S value. 491 * @param encodedParams the curve's DER encoded object identifier. 492 * @param seed the random seed. 493 * @param timing When non-zero, the implmentation will use timing 494 * countermeasures to hide secrets from timing channels. The EC 495 * implementation will disable the countermeasures when this value is 496 * zero, because the underlying EC functions are shared by several 497 * crypto operations, some of which do not use the countermeasures. 498 * The high-order 31 bits must be uniformly random. The entropy from 499 * these bits is used by the countermeasures. 500 * 501 * @return byte[] the signature. 502 */ 503 private static native byte[] signDigest(byte[] digest, byte[] s, 504 byte[] encodedParams, byte[] seed, int timing) 505 throws GeneralSecurityException; 506 507 /** 508 * Verifies the signed digest using the public key. 509 * 510 * @param signature the signature to be verified. It is encoded 511 * as a concatenation of the key's R and S values. 512 * @param digest the digest to be used. 513 * @param w the public key's W point (in uncompressed form). 514 * @param encodedParams the curve's DER encoded object identifier. 515 * 516 * @return boolean true if the signature is successfully verified. 517 */ 518 private static native boolean verifySignedDigest(byte[] signature, 519 byte[] digest, byte[] w, byte[] encodedParams) 520 throws GeneralSecurityException; 521 }