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 }