src/java.base/share/classes/sun/security/provider/DSA.java
changeset 47216 71c04702a3d5
parent 45990 ba8bfbb9d633
child 48080 18a4438eb690
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1996, 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.provider;
       
    27 
       
    28 import java.io.*;
       
    29 import java.util.*;
       
    30 import java.math.BigInteger;
       
    31 import java.nio.ByteBuffer;
       
    32 
       
    33 import java.security.*;
       
    34 import java.security.SecureRandom;
       
    35 import java.security.interfaces.*;
       
    36 
       
    37 import sun.security.util.Debug;
       
    38 import sun.security.util.DerValue;
       
    39 import sun.security.util.DerInputStream;
       
    40 import sun.security.util.DerOutputStream;
       
    41 import sun.security.jca.JCAUtil;
       
    42 
       
    43 /**
       
    44  * The Digital Signature Standard (using the Digital Signature
       
    45  * Algorithm), as described in fips186-3 of the National Instute of
       
    46  * Standards and Technology (NIST), using SHA digest algorithms
       
    47  * from FIPS180-3.
       
    48  *
       
    49  * This file contains both the signature implementation for the
       
    50  * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA,
       
    51  * as well as RawDSA, used by TLS among others. RawDSA expects
       
    52  * the 20 byte SHA-1 digest as input via update rather than the
       
    53  * original data like other signature implementations.
       
    54  *
       
    55  * @author Benjamin Renaud
       
    56  *
       
    57  * @since   1.1
       
    58  *
       
    59  * @see DSAPublicKey
       
    60  * @see DSAPrivateKey
       
    61  */
       
    62 abstract class DSA extends SignatureSpi {
       
    63 
       
    64     /* Are we debugging? */
       
    65     private static final boolean debug = false;
       
    66 
       
    67     /* The number of bits used in exponent blinding */
       
    68     private static final int BLINDING_BITS = 7;
       
    69 
       
    70     /* The constant component of the exponent blinding value */
       
    71     private static final BigInteger BLINDING_CONSTANT =
       
    72         BigInteger.valueOf(1 << BLINDING_BITS);
       
    73 
       
    74     /* The parameter object */
       
    75     private DSAParams params;
       
    76 
       
    77     /* algorithm parameters */
       
    78     private BigInteger presetP, presetQ, presetG;
       
    79 
       
    80     /* The public key, if any */
       
    81     private BigInteger presetY;
       
    82 
       
    83     /* The private key, if any */
       
    84     private BigInteger presetX;
       
    85 
       
    86     /* The RNG used to output a seed for generating k */
       
    87     private SecureRandom signingRandom;
       
    88 
       
    89     /* The message digest object used */
       
    90     private final MessageDigest md;
       
    91 
       
    92     /* The format. true for the IEEE P1363 format. false (default) for ASN.1 */
       
    93     private final boolean p1363Format;
       
    94 
       
    95     /**
       
    96      * Construct a blank DSA object. It must be
       
    97      * initialized before being usable for signing or verifying.
       
    98      */
       
    99     DSA(MessageDigest md) {
       
   100         this(md, false);
       
   101     }
       
   102 
       
   103     /**
       
   104      * Construct a blank DSA object that will use the specified
       
   105      * signature format. {@code p1363Format} should be {@code true} to
       
   106      * use the IEEE P1363 format. If {@code p1363Format} is {@code false},
       
   107      * the DER-encoded ASN.1 format will used. The DSA object must be
       
   108      * initialized before being usable for signing or verifying.
       
   109      */
       
   110     DSA(MessageDigest md, boolean p1363Format) {
       
   111         super();
       
   112         this.md = md;
       
   113         this.p1363Format = p1363Format;
       
   114     }
       
   115 
       
   116     private static void checkKey(DSAParams params, int digestLen, String mdAlgo)
       
   117         throws InvalidKeyException {
       
   118         // FIPS186-3 states in sec4.2 that a hash function which provides
       
   119         // a lower security strength than the (L, N) pair ordinarily should
       
   120         // not be used.
       
   121         int valueN = params.getQ().bitLength();
       
   122         if (valueN > digestLen) {
       
   123             throw new InvalidKeyException("The security strength of " +
       
   124                 mdAlgo + " digest algorithm is not sufficient for this key size");
       
   125         }
       
   126     }
       
   127 
       
   128     /**
       
   129      * Initialize the DSA object with a DSA private key.
       
   130      *
       
   131      * @param privateKey the DSA private key
       
   132      *
       
   133      * @exception InvalidKeyException if the key is not a valid DSA private
       
   134      * key.
       
   135      */
       
   136     protected void engineInitSign(PrivateKey privateKey)
       
   137             throws InvalidKeyException {
       
   138         if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {
       
   139             throw new InvalidKeyException("not a DSA private key: " +
       
   140                                           privateKey);
       
   141         }
       
   142 
       
   143         java.security.interfaces.DSAPrivateKey priv =
       
   144             (java.security.interfaces.DSAPrivateKey)privateKey;
       
   145 
       
   146         // check for algorithm specific constraints before doing initialization
       
   147         DSAParams params = priv.getParams();
       
   148         if (params == null) {
       
   149             throw new InvalidKeyException("DSA private key lacks parameters");
       
   150         }
       
   151 
       
   152         // check key size against hash output size for signing
       
   153         // skip this check for verification to minimize impact on existing apps
       
   154         if (md.getAlgorithm() != "NullDigest20") {
       
   155             checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
       
   156         }
       
   157 
       
   158         this.params = params;
       
   159         this.presetX = priv.getX();
       
   160         this.presetY = null;
       
   161         this.presetP = params.getP();
       
   162         this.presetQ = params.getQ();
       
   163         this.presetG = params.getG();
       
   164         this.md.reset();
       
   165     }
       
   166     /**
       
   167      * Initialize the DSA object with a DSA public key.
       
   168      *
       
   169      * @param publicKey the DSA public key.
       
   170      *
       
   171      * @exception InvalidKeyException if the key is not a valid DSA public
       
   172      * key.
       
   173      */
       
   174     protected void engineInitVerify(PublicKey publicKey)
       
   175             throws InvalidKeyException {
       
   176         if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {
       
   177             throw new InvalidKeyException("not a DSA public key: " +
       
   178                                           publicKey);
       
   179         }
       
   180         java.security.interfaces.DSAPublicKey pub =
       
   181             (java.security.interfaces.DSAPublicKey)publicKey;
       
   182 
       
   183         // check for algorithm specific constraints before doing initialization
       
   184         DSAParams params = pub.getParams();
       
   185         if (params == null) {
       
   186             throw new InvalidKeyException("DSA public key lacks parameters");
       
   187         }
       
   188         this.params = params;
       
   189         this.presetY = pub.getY();
       
   190         this.presetX = null;
       
   191         this.presetP = params.getP();
       
   192         this.presetQ = params.getQ();
       
   193         this.presetG = params.getG();
       
   194         this.md.reset();
       
   195     }
       
   196 
       
   197     /**
       
   198      * Update a byte to be signed or verified.
       
   199      */
       
   200     protected void engineUpdate(byte b) {
       
   201         md.update(b);
       
   202     }
       
   203 
       
   204     /**
       
   205      * Update an array of bytes to be signed or verified.
       
   206      */
       
   207     protected void engineUpdate(byte[] data, int off, int len) {
       
   208         md.update(data, off, len);
       
   209     }
       
   210 
       
   211     protected void engineUpdate(ByteBuffer b) {
       
   212         md.update(b);
       
   213     }
       
   214 
       
   215 
       
   216     /**
       
   217      * Sign all the data thus far updated. The signature format is
       
   218      * determined by {@code p1363Format}. If {@code p1363Format} is
       
   219      * {@code false} (the default), then the signature is formatted
       
   220      * according to the Canonical Encoding Rules, returned as a DER
       
   221      * sequence of Integers, r and s. If {@code p1363Format} is
       
   222      * {@code false}, the signature is returned in the IEEE P1363
       
   223      * format, which is the concatenation or r and s.
       
   224      *
       
   225      * @return a signature block formatted according to the format
       
   226      * indicated by {@code p1363Format}
       
   227      *
       
   228      * @exception SignatureException if the signature object was not
       
   229      * properly initialized, or if another exception occurs.
       
   230      *
       
   231      * @see sun.security.DSA#engineUpdate
       
   232      * @see sun.security.DSA#engineVerify
       
   233      */
       
   234     protected byte[] engineSign() throws SignatureException {
       
   235         BigInteger k = generateK(presetQ);
       
   236         BigInteger r = generateR(presetP, presetQ, presetG, k);
       
   237         BigInteger s = generateS(presetX, presetQ, r, k);
       
   238 
       
   239         if (p1363Format) {
       
   240             // Return the concatenation of r and s
       
   241             byte[] rBytes = r.toByteArray();
       
   242             byte[] sBytes = s.toByteArray();
       
   243 
       
   244             int size = presetQ.bitLength() / 8;
       
   245             byte[] outseq = new byte[size * 2];
       
   246 
       
   247             int rLength = rBytes.length;
       
   248             int sLength = sBytes.length;
       
   249             int i;
       
   250             for (i = rLength; i > 0 && rBytes[rLength - i] == 0; i--);
       
   251 
       
   252             int j;
       
   253             for (j = sLength;
       
   254                     j > 0 && sBytes[sLength - j] == 0; j--);
       
   255 
       
   256             System.arraycopy(rBytes, rLength - i, outseq, size - i, i);
       
   257             System.arraycopy(sBytes, sLength - j, outseq, size * 2 - j, j);
       
   258 
       
   259             return outseq;
       
   260         } else {
       
   261             // Return the DER-encoded ASN.1 form
       
   262             try {
       
   263                 DerOutputStream outseq = new DerOutputStream(100);
       
   264                 outseq.putInteger(r);
       
   265                 outseq.putInteger(s);
       
   266                 DerValue result = new DerValue(DerValue.tag_Sequence,
       
   267                         outseq.toByteArray());
       
   268 
       
   269                 return result.toByteArray();
       
   270 
       
   271             } catch (IOException e) {
       
   272                 throw new SignatureException("error encoding signature");
       
   273             }
       
   274         }
       
   275     }
       
   276 
       
   277     /**
       
   278      * Verify all the data thus far updated.
       
   279      *
       
   280      * @param signature the alleged signature, encoded using the
       
   281      * Canonical Encoding Rules, as a sequence of integers, r and s.
       
   282      *
       
   283      * @exception SignatureException if the signature object was not
       
   284      * properly initialized, or if another exception occurs.
       
   285      *
       
   286      * @see sun.security.DSA#engineUpdate
       
   287      * @see sun.security.DSA#engineSign
       
   288      */
       
   289     protected boolean engineVerify(byte[] signature)
       
   290             throws SignatureException {
       
   291         return engineVerify(signature, 0, signature.length);
       
   292     }
       
   293 
       
   294     /**
       
   295      * Verify all the data thus far updated.
       
   296      *
       
   297      * @param signature the alleged signature, encoded using the
       
   298      * format indicated by {@code p1363Format}. If {@code p1363Format}
       
   299      * is {@code false} (the default), then the signature is formatted
       
   300      * according to the Canonical Encoding Rules, as a DER sequence of
       
   301      * Integers, r and s. If {@code p1363Format} is {@code false},
       
   302      * the signature is in the IEEE P1363 format, which is the
       
   303      * concatenation or r and s.
       
   304      *
       
   305      * @param offset the offset to start from in the array of bytes.
       
   306      *
       
   307      * @param length the number of bytes to use, starting at offset.
       
   308      *
       
   309      * @exception SignatureException if the signature object was not
       
   310      * properly initialized, or if another exception occurs.
       
   311      *
       
   312      * @see sun.security.DSA#engineUpdate
       
   313      * @see sun.security.DSA#engineSign
       
   314      */
       
   315     protected boolean engineVerify(byte[] signature, int offset, int length)
       
   316             throws SignatureException {
       
   317 
       
   318         BigInteger r = null;
       
   319         BigInteger s = null;
       
   320 
       
   321         if (p1363Format) {
       
   322             if ((length & 1) == 1) {
       
   323                 // length of signature byte array should be even
       
   324                 throw new SignatureException("invalid signature format");
       
   325             }
       
   326             int mid = length/2;
       
   327             r = new BigInteger(Arrays.copyOfRange(signature, 0, mid));
       
   328             s = new BigInteger(Arrays.copyOfRange(signature, mid, length));
       
   329         } else {
       
   330             // first decode the signature.
       
   331             try {
       
   332                 // Enforce strict DER checking for signatures
       
   333                 DerInputStream in =
       
   334                     new DerInputStream(signature, offset, length, false);
       
   335                 DerValue[] values = in.getSequence(2);
       
   336 
       
   337                 // check number of components in the read sequence
       
   338                 // and trailing data
       
   339                 if ((values.length != 2) || (in.available() != 0)) {
       
   340                     throw new IOException("Invalid encoding for signature");
       
   341                 }
       
   342                 r = values[0].getBigInteger();
       
   343                 s = values[1].getBigInteger();
       
   344             } catch (IOException e) {
       
   345                 throw new SignatureException("Invalid encoding for signature", e);
       
   346             }
       
   347         }
       
   348 
       
   349         // some implementations do not correctly encode values in the ASN.1
       
   350         // 2's complement format. force r and s to be positive in order to
       
   351         // to validate those signatures
       
   352         if (r.signum() < 0) {
       
   353             r = new BigInteger(1, r.toByteArray());
       
   354         }
       
   355         if (s.signum() < 0) {
       
   356             s = new BigInteger(1, s.toByteArray());
       
   357         }
       
   358 
       
   359         if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) {
       
   360             BigInteger w = generateW(presetP, presetQ, presetG, s);
       
   361             BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);
       
   362             return v.equals(r);
       
   363         } else {
       
   364             throw new SignatureException("invalid signature: out of range values");
       
   365         }
       
   366     }
       
   367 
       
   368     @Deprecated
       
   369     protected void engineSetParameter(String key, Object param) {
       
   370         throw new InvalidParameterException("No parameter accepted");
       
   371     }
       
   372 
       
   373     @Deprecated
       
   374     protected Object engineGetParameter(String key) {
       
   375         return null;
       
   376     }
       
   377 
       
   378 
       
   379     private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
       
   380                          BigInteger k) {
       
   381 
       
   382         // exponent blinding to hide information from timing channel
       
   383         SecureRandom random = getSigningRandom();
       
   384         // start with a random blinding component
       
   385         BigInteger blindingValue = new BigInteger(BLINDING_BITS, random);
       
   386         // add the fixed blinding component
       
   387         blindingValue = blindingValue.add(BLINDING_CONSTANT);
       
   388         // replace k with a blinded value that is congruent (mod q)
       
   389         k = k.add(q.multiply(blindingValue));
       
   390 
       
   391         BigInteger temp = g.modPow(k, p);
       
   392         return temp.mod(q);
       
   393     }
       
   394 
       
   395     private BigInteger generateS(BigInteger x, BigInteger q,
       
   396             BigInteger r, BigInteger k) throws SignatureException {
       
   397 
       
   398         byte[] s2;
       
   399         try {
       
   400             s2 = md.digest();
       
   401         } catch (RuntimeException re) {
       
   402             // Only for RawDSA due to its 20-byte length restriction
       
   403             throw new SignatureException(re.getMessage());
       
   404         }
       
   405         // get the leftmost min(N, outLen) bits of the digest value
       
   406         int nBytes = q.bitLength()/8;
       
   407         if (nBytes < s2.length) {
       
   408             s2 = Arrays.copyOfRange(s2, 0, nBytes);
       
   409         }
       
   410         BigInteger z = new BigInteger(1, s2);
       
   411         BigInteger k1 = k.modInverse(q);
       
   412 
       
   413         return x.multiply(r).add(z).multiply(k1).mod(q);
       
   414     }
       
   415 
       
   416     private BigInteger generateW(BigInteger p, BigInteger q,
       
   417                          BigInteger g, BigInteger s) {
       
   418         return s.modInverse(q);
       
   419     }
       
   420 
       
   421     private BigInteger generateV(BigInteger y, BigInteger p,
       
   422              BigInteger q, BigInteger g, BigInteger w, BigInteger r)
       
   423              throws SignatureException {
       
   424 
       
   425         byte[] s2;
       
   426         try {
       
   427             s2 = md.digest();
       
   428         } catch (RuntimeException re) {
       
   429             // Only for RawDSA due to its 20-byte length restriction
       
   430             throw new SignatureException(re.getMessage());
       
   431         }
       
   432         // get the leftmost min(N, outLen) bits of the digest value
       
   433         int nBytes = q.bitLength()/8;
       
   434         if (nBytes < s2.length) {
       
   435             s2 = Arrays.copyOfRange(s2, 0, nBytes);
       
   436         }
       
   437         BigInteger z = new BigInteger(1, s2);
       
   438 
       
   439         BigInteger u1 = z.multiply(w).mod(q);
       
   440         BigInteger u2 = (r.multiply(w)).mod(q);
       
   441 
       
   442         BigInteger t1 = g.modPow(u1,p);
       
   443         BigInteger t2 = y.modPow(u2,p);
       
   444         BigInteger t3 = t1.multiply(t2);
       
   445         BigInteger t5 = t3.mod(p);
       
   446         return t5.mod(q);
       
   447     }
       
   448 
       
   449     protected BigInteger generateK(BigInteger q) {
       
   450         // Implementation defined in FIPS 186-4 AppendixB.2.1.
       
   451         SecureRandom random = getSigningRandom();
       
   452         byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
       
   453 
       
   454         random.nextBytes(kValue);
       
   455         return new BigInteger(1, kValue).mod(
       
   456                 q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
       
   457     }
       
   458 
       
   459     // Use the application-specified SecureRandom Object if provided.
       
   460     // Otherwise, use our default SecureRandom Object.
       
   461     protected SecureRandom getSigningRandom() {
       
   462         if (signingRandom == null) {
       
   463             if (appRandom != null) {
       
   464                 signingRandom = appRandom;
       
   465             } else {
       
   466                 signingRandom = JCAUtil.getSecureRandom();
       
   467             }
       
   468         }
       
   469         return signingRandom;
       
   470     }
       
   471 
       
   472     /**
       
   473      * Return a human readable rendition of the engine.
       
   474      */
       
   475     public String toString() {
       
   476         String printable = "DSA Signature";
       
   477         if (presetP != null && presetQ != null && presetG != null) {
       
   478             printable += "\n\tp: " + Debug.toHexString(presetP);
       
   479             printable += "\n\tq: " + Debug.toHexString(presetQ);
       
   480             printable += "\n\tg: " + Debug.toHexString(presetG);
       
   481         } else {
       
   482             printable += "\n\t P, Q or G not initialized.";
       
   483         }
       
   484         if (presetY != null) {
       
   485             printable += "\n\ty: " + Debug.toHexString(presetY);
       
   486         }
       
   487         if (presetY == null && presetX == null) {
       
   488             printable += "\n\tUNINIIALIZED";
       
   489         }
       
   490         return printable;
       
   491     }
       
   492 
       
   493     private static void debug(Exception e) {
       
   494         if (debug) {
       
   495             e.printStackTrace();
       
   496         }
       
   497     }
       
   498 
       
   499     private static void debug(String s) {
       
   500         if (debug) {
       
   501             System.err.println(s);
       
   502         }
       
   503     }
       
   504 
       
   505     /**
       
   506      * Standard SHA224withDSA implementation as defined in FIPS186-3.
       
   507      */
       
   508     public static final class SHA224withDSA extends DSA {
       
   509         public SHA224withDSA() throws NoSuchAlgorithmException {
       
   510             super(MessageDigest.getInstance("SHA-224"));
       
   511         }
       
   512     }
       
   513 
       
   514     /**
       
   515      * SHA224withDSA implementation that uses the IEEE P1363 format.
       
   516      */
       
   517     public static final class SHA224withDSAinP1363Format extends DSA {
       
   518         public SHA224withDSAinP1363Format() throws NoSuchAlgorithmException {
       
   519             super(MessageDigest.getInstance("SHA-224"), true);
       
   520         }
       
   521     }
       
   522 
       
   523     /**
       
   524      * Standard SHA256withDSA implementation as defined in FIPS186-3.
       
   525      */
       
   526     public static final class SHA256withDSA extends DSA {
       
   527         public SHA256withDSA() throws NoSuchAlgorithmException {
       
   528             super(MessageDigest.getInstance("SHA-256"));
       
   529         }
       
   530     }
       
   531 
       
   532     /**
       
   533      * SHA256withDSA implementation that uses the IEEE P1363 format.
       
   534      */
       
   535     public static final class SHA256withDSAinP1363Format extends DSA {
       
   536         public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException {
       
   537             super(MessageDigest.getInstance("SHA-256"), true);
       
   538         }
       
   539     }
       
   540 
       
   541     /**
       
   542      * Standard SHA1withDSA implementation.
       
   543      */
       
   544     public static final class SHA1withDSA extends DSA {
       
   545         public SHA1withDSA() throws NoSuchAlgorithmException {
       
   546             super(MessageDigest.getInstance("SHA-1"));
       
   547         }
       
   548     }
       
   549 
       
   550     /**
       
   551      * SHA1withDSA implementation that uses the IEEE P1363 format.
       
   552      */
       
   553     public static final class SHA1withDSAinP1363Format extends DSA {
       
   554         public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException {
       
   555             super(MessageDigest.getInstance("SHA-1"), true);
       
   556         }
       
   557     }
       
   558 
       
   559     /**
       
   560      * Raw DSA.
       
   561      *
       
   562      * Raw DSA requires the data to be exactly 20 bytes long. If it is
       
   563      * not, a SignatureException is thrown when sign()/verify() is called
       
   564      * per JCA spec.
       
   565      */
       
   566     static class Raw extends DSA {
       
   567         // Internal special-purpose MessageDigest impl for RawDSA
       
   568         // Only override whatever methods used
       
   569         // NOTE: no clone support
       
   570         public static final class NullDigest20 extends MessageDigest {
       
   571             // 20 byte digest buffer
       
   572             private final byte[] digestBuffer = new byte[20];
       
   573 
       
   574             // offset into the buffer; use Integer.MAX_VALUE to indicate
       
   575             // out-of-bound condition
       
   576             private int ofs = 0;
       
   577 
       
   578             protected NullDigest20() {
       
   579                 super("NullDigest20");
       
   580             }
       
   581             protected void engineUpdate(byte input) {
       
   582                 if (ofs == digestBuffer.length) {
       
   583                     ofs = Integer.MAX_VALUE;
       
   584                 } else {
       
   585                     digestBuffer[ofs++] = input;
       
   586                 }
       
   587             }
       
   588             protected void engineUpdate(byte[] input, int offset, int len) {
       
   589                 if (ofs + len > digestBuffer.length) {
       
   590                     ofs = Integer.MAX_VALUE;
       
   591                 } else {
       
   592                     System.arraycopy(input, offset, digestBuffer, ofs, len);
       
   593                     ofs += len;
       
   594                 }
       
   595             }
       
   596             protected final void engineUpdate(ByteBuffer input) {
       
   597                 int inputLen = input.remaining();
       
   598                 if (ofs + inputLen > digestBuffer.length) {
       
   599                     ofs = Integer.MAX_VALUE;
       
   600                 } else {
       
   601                     input.get(digestBuffer, ofs, inputLen);
       
   602                     ofs += inputLen;
       
   603                 }
       
   604             }
       
   605             protected byte[] engineDigest() throws RuntimeException {
       
   606                 if (ofs != digestBuffer.length) {
       
   607                     throw new RuntimeException
       
   608                         ("Data for RawDSA must be exactly 20 bytes long");
       
   609                 }
       
   610                 reset();
       
   611                 return digestBuffer;
       
   612             }
       
   613             protected int engineDigest(byte[] buf, int offset, int len)
       
   614                 throws DigestException {
       
   615                 if (ofs != digestBuffer.length) {
       
   616                     throw new DigestException
       
   617                         ("Data for RawDSA must be exactly 20 bytes long");
       
   618                 }
       
   619                 if (len < digestBuffer.length) {
       
   620                     throw new DigestException
       
   621                         ("Output buffer too small; must be at least 20 bytes");
       
   622                 }
       
   623                 System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);
       
   624                 reset();
       
   625                 return digestBuffer.length;
       
   626             }
       
   627 
       
   628             protected void engineReset() {
       
   629                 ofs = 0;
       
   630             }
       
   631             protected final int engineGetDigestLength() {
       
   632                 return digestBuffer.length;
       
   633             }
       
   634         }
       
   635 
       
   636         private Raw(boolean p1363Format) throws NoSuchAlgorithmException {
       
   637             super(new NullDigest20(), p1363Format);
       
   638         }
       
   639 
       
   640     }
       
   641 
       
   642     /**
       
   643      * Standard Raw DSA implementation.
       
   644      */
       
   645     public static final class RawDSA extends Raw {
       
   646         public RawDSA() throws NoSuchAlgorithmException {
       
   647             super(false);
       
   648         }
       
   649     }
       
   650 
       
   651     /**
       
   652      * Raw DSA implementation that uses the IEEE P1363 format.
       
   653      */
       
   654     public static final class RawDSAinP1363Format extends Raw {
       
   655         public RawDSAinP1363Format() throws NoSuchAlgorithmException {
       
   656             super(true);
       
   657         }
       
   658     }
       
   659 }