1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.security;
19
20import java.nio.ByteBuffer;
21import java.security.cert.Certificate;
22import java.security.cert.X509Certificate;
23import java.security.spec.AlgorithmParameterSpec;
24import java.util.ArrayList;
25import java.util.Iterator;
26import java.util.Set;
27import org.apache.harmony.security.fortress.Engine;
28import org.apache.harmony.security.fortress.Engine.SpiAndProvider;
29
30/**
31 * {@code Signature} is an engine class which is capable of creating and
32 * verifying digital signatures, using different algorithms that have been
33 * registered with the {@link Security} class.
34 *
35 * @see SignatureSpi
36 */
37public abstract class Signature extends SignatureSpi {
38
39    // The service name.
40    private static final String SERVICE = "Signature";
41
42    // Used to access common engine functionality
43    private static final Engine ENGINE = new Engine(SERVICE);
44
45    // The provider
46    Provider provider;
47
48    // The algorithm.
49    final String algorithm;
50
51    /**
52     * Constant that indicates that this {@code Signature} instance has not yet
53     * been initialized.
54     */
55    protected static final int UNINITIALIZED = 0;
56
57    /**
58     * Constant that indicates that this {@code Signature} instance has been
59     * initialized for signing.
60     */
61    protected static final int SIGN = 2;
62
63    /**
64     * Constant that indicates that this {@code Signature} instance has been
65     * initialized for verification.
66     */
67    protected static final int VERIFY = 3;
68
69    /**
70     * Represents the current state of this {@code Signature}. The three
71     * possible states are {@link #UNINITIALIZED}, {@link #SIGN} or
72     * {@link #VERIFY}.
73     */
74    protected int state = UNINITIALIZED;
75
76    /**
77     * Constructs a new instance of {@code Signature} with the name of
78     * the algorithm to use.
79     *
80     * @param algorithm
81     *            the name of algorithm to use.
82     */
83    protected Signature(String algorithm) {
84        this.algorithm = algorithm;
85    }
86
87    /**
88     * Returns a new instance of {@code Signature} that utilizes the specified
89     * algorithm.
90     *
91     * @param algorithm
92     *            the name of the algorithm to use.
93     * @return a new instance of {@code Signature} that utilizes the specified
94     *         algorithm.
95     * @throws NoSuchAlgorithmException
96     *             if the specified algorithm is not available.
97     * @throws NullPointerException
98     *             if {@code algorithm} is {@code null}.
99     */
100    public static Signature getInstance(String algorithm)
101            throws NoSuchAlgorithmException {
102        if (algorithm == null) {
103            throw new NullPointerException("algorithm == null");
104        }
105        return getSignature(algorithm, null);
106    }
107
108    /**
109     * Returns a new instance of {@code Signature} that utilizes the specified
110     * algorithm from the specified provider.
111     *
112     * @param algorithm
113     *            the name of the algorithm to use.
114     * @param provider
115     *            the name of the provider.
116     * @return a new instance of {@code Signature} that utilizes the specified
117     *         algorithm from the specified provider.
118     * @throws NoSuchAlgorithmException
119     *             if the specified algorithm is not available.
120     * @throws NoSuchProviderException
121     *             if the specified provider is not available.
122     * @throws NullPointerException
123     *             if {@code algorithm} is {@code null}.
124     * @throws IllegalArgumentException if {@code provider == null || provider.isEmpty()}
125     */
126    public static Signature getInstance(String algorithm, String provider)
127            throws NoSuchAlgorithmException, NoSuchProviderException {
128        if (algorithm == null) {
129            throw new NullPointerException("algorithm == null");
130        }
131        if (provider == null || provider.isEmpty()) {
132            throw new IllegalArgumentException();
133        }
134        Provider p = Security.getProvider(provider);
135        if (p == null) {
136            throw new NoSuchProviderException(provider);
137        }
138        return getSignature(algorithm, p);
139    }
140
141    /**
142     * Returns a new instance of {@code Signature} that utilizes the specified
143     * algorithm from the specified provider. The {@code provider} supplied
144     * does not have to be registered.
145     *
146     * @param algorithm
147     *            the name of the algorithm to use.
148     * @param provider
149     *            the security provider.
150     * @return a new instance of {@code Signature} that utilizes the specified
151     *         algorithm from the specified provider.
152     * @throws NoSuchAlgorithmException
153     *             if the specified algorithm is not available.
154     * @throws NullPointerException
155     *             if {@code algorithm} is {@code null}.
156     * @throws IllegalArgumentException if {@code provider == null}
157     */
158    public static Signature getInstance(String algorithm, Provider provider)
159            throws NoSuchAlgorithmException {
160        if (algorithm == null) {
161            throw new NullPointerException("algorithm == null");
162        }
163        if (provider == null) {
164            throw new IllegalArgumentException("provider == null");
165        }
166        return getSignature(algorithm, provider);
167    }
168
169    private static Signature getSignature(String algorithm, Provider provider)
170            throws NoSuchAlgorithmException {
171        if (algorithm == null || algorithm.isEmpty()) {
172            throw new NoSuchAlgorithmException("Unknown algorithm: " + algorithm);
173        }
174
175        SpiAndProvider spiAndProvider = tryAlgorithm(null, provider, algorithm);
176        if (spiAndProvider == null) {
177            if (provider == null) {
178                throw new NoSuchAlgorithmException("No provider found for " + algorithm);
179            } else {
180                throw new NoSuchAlgorithmException("Provider " + provider.getName()
181                        + " does not provide " + algorithm);
182            }
183        }
184        if (spiAndProvider.spi instanceof Signature) {
185            return (Signature) spiAndProvider.spi;
186        }
187        return new SignatureImpl(algorithm, provider);
188    }
189
190    private static Engine.SpiAndProvider tryAlgorithm(Key key, Provider provider, String algorithm) {
191        if (provider != null) {
192            Provider.Service service = provider.getService(SERVICE, algorithm);
193            if (service == null) {
194                return null;
195            }
196            return tryAlgorithmWithProvider(key, service);
197        }
198        ArrayList<Provider.Service> services = ENGINE.getServices(algorithm);
199        if (services == null) {
200            return null;
201        }
202        for (Provider.Service service : services) {
203            Engine.SpiAndProvider sap = tryAlgorithmWithProvider(key, service);
204            if (sap != null) {
205                return sap;
206            }
207        }
208        return null;
209    }
210
211    private static Engine.SpiAndProvider tryAlgorithmWithProvider(Key key, Provider.Service service) {
212        try {
213            if (key != null && !service.supportsParameter(key)) {
214                return null;
215            }
216
217            Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
218            if (sap.spi == null || sap.provider == null) {
219                return null;
220            }
221            if (!(sap.spi instanceof SignatureSpi)) {
222                return null;
223            }
224            return sap;
225        } catch (NoSuchAlgorithmException ignored) {
226        }
227        return null;
228    }
229
230    /**
231     * Returns the provider associated with this {@code Signature}.
232     *
233     * @return the provider associated with this {@code Signature}.
234     */
235    public final Provider getProvider() {
236        ensureProviderChosen();
237        return provider;
238    }
239
240    /**
241     * This makes sure the provider is chosen since Signature is abstract and
242     * getProvider is final but we need to support late binding.
243     */
244    void ensureProviderChosen() {
245    }
246
247    /**
248     * Returns the name of the algorithm of this {@code Signature}.
249     *
250     * @return the name of the algorithm of this {@code Signature}.
251     */
252    public final String getAlgorithm() {
253        return algorithm;
254    }
255
256    /**
257     * Initializes this {@code Signature} instance for signature verification,
258     * using the public key of the identity whose signature is going to be
259     * verified.
260     *
261     * @param publicKey
262     *            the public key.
263     * @throws InvalidKeyException
264     *             if {@code publicKey} is not valid.
265     */
266    public final void initVerify(PublicKey publicKey)
267            throws InvalidKeyException {
268        engineInitVerify(publicKey);
269        state = VERIFY;
270    }
271
272    /**
273     * Initializes this {@code Signature} instance for signature verification,
274     * using the certificate of the identity whose signature is going to be
275     * verified.
276     * <p>
277     * If the given certificate is an instance of {@link X509Certificate} and
278     * has a key usage parameter that indicates, that this certificate is not to
279     * be used for signing, an {@code InvalidKeyException} is thrown.
280     *
281     * @param certificate
282     *            the certificate used to verify a signature.
283     * @throws InvalidKeyException
284     *             if the publicKey in the certificate is not valid or not to be
285     *             used for signing.
286     */
287    public final void initVerify(Certificate certificate)
288            throws InvalidKeyException {
289        if (certificate instanceof X509Certificate) {
290            Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
291            boolean critical = false;
292            if (ce != null && !ce.isEmpty()) {
293                for (Iterator<String> i = ce.iterator(); i.hasNext();) {
294                    if ("2.5.29.15".equals(i.next())) {
295                        //KeyUsage OID = 2.5.29.15
296                        critical = true;
297                        break;
298                    }
299                }
300                if (critical) {
301                    boolean[] keyUsage = ((X509Certificate) certificate)
302                            .getKeyUsage();
303                    // As specified in RFC 3280 -
304                    // Internet X.509 Public Key Infrastructure
305                    // Certificate and Certificate Revocation List (CRL) Profile.
306                    // (http://www.ietf.org/rfc/rfc3280.txt)
307                    //
308                    // KeyUsage ::= BIT STRING { digitalSignature (0), <skipped> }
309                    if ((keyUsage != null) && (!keyUsage[0])) { // digitalSignature
310                        throw new InvalidKeyException("The public key in the certificate cannot be used for digital signature purposes");
311                    }
312                }
313            }
314        }
315        engineInitVerify(certificate.getPublicKey());
316        state = VERIFY;
317    }
318
319    /**
320     * Initializes this {@code Signature} instance for signing, using the
321     * private key of the identity whose signature is going to be generated.
322     *
323     * @param privateKey
324     *            the private key.
325     * @throws InvalidKeyException
326     *             if {@code privateKey} is not valid.
327     */
328    public final void initSign(PrivateKey privateKey)
329            throws InvalidKeyException {
330        engineInitSign(privateKey);
331        state = SIGN;
332    }
333
334    /**
335     * Initializes this {@code Signature} instance for signing, using the
336     * private key of the identity whose signature is going to be generated and
337     * the specified source of randomness.
338     *
339     * @param privateKey
340     *            the private key.
341     * @param random
342     *            the {@code SecureRandom} to use.
343     * @throws InvalidKeyException
344     *             if {@code privateKey} is not valid.
345     */
346    public final void initSign(PrivateKey privateKey, SecureRandom random)
347            throws InvalidKeyException {
348        engineInitSign(privateKey, random);
349        state = SIGN;
350    }
351
352    /**
353     * Generates and returns the signature of all updated data.
354     * <p>
355     * This {@code Signature} instance is reset to the state of its last
356     * initialization for signing and thus can be used for another signature
357     * from the same identity.
358     *
359     * @return the signature of all updated data.
360     * @throws SignatureException
361     *             if this {@code Signature} instance is not initialized
362     *             properly.
363     */
364    public final byte[] sign() throws SignatureException {
365        if (state != SIGN) {
366            throw new SignatureException("Signature object is not initialized properly");
367        }
368        return engineSign();
369    }
370
371    /**
372     * Generates and stores the signature of all updated data in the provided
373     * {@code byte[]} at the specified position with the specified length.
374     * <p>
375     * This {@code Signature} instance is reset to the state of its last
376     * initialization for signing and thus can be used for another signature
377     * from the same identity.
378     *
379     * @param outbuf
380     *            the buffer to store the signature.
381     * @param offset
382     *            the index of the first byte in {@code outbuf} to store.
383     * @param len
384     *            the number of bytes allocated for the signature.
385     * @return the number of bytes stored in {@code outbuf}.
386     * @throws SignatureException
387     *             if this {@code Signature} instance is not initialized
388     *             properly.
389     * @throws IllegalArgumentException
390     *             if {@code offset} or {@code len} are not valid in respect to
391     *             {@code outbuf}.
392     */
393    public final int sign(byte[] outbuf, int offset, int len)
394            throws SignatureException {
395        if (outbuf == null || offset < 0 || len < 0 ||
396                offset + len > outbuf.length) {
397            throw new IllegalArgumentException();
398        }
399        if (state != SIGN) {
400            throw new SignatureException("Signature object is not initialized properly");
401        }
402        return engineSign(outbuf, offset, len);
403    }
404
405    /**
406     * Indicates whether the given {@code signature} can be verified using the
407     * public key or a certificate of the signer.
408     * <p>
409     * This {@code Signature} instance is reset to the state of its last
410     * initialization for verifying and thus can be used to verify another
411     * signature of the same signer.
412     *
413     * @param signature
414     *            the signature to verify.
415     * @return {@code true} if the signature was verified, {@code false}
416     *         otherwise.
417     * @throws SignatureException
418     *             if this {@code Signature} instance is not initialized
419     *             properly.
420     */
421    public final boolean verify(byte[] signature) throws SignatureException {
422        if (state != VERIFY) {
423            throw new SignatureException("Signature object is not initialized properly");
424        }
425        return engineVerify(signature);
426    }
427
428    /**
429     * Indicates whether the given {@code signature} starting at index {@code
430     * offset} with {@code length} bytes can be verified using the public key or
431     * a certificate of the signer.
432     * <p>
433     * This {@code Signature} instance is reset to the state of its last
434     * initialization for verifying and thus can be used to verify another
435     * signature of the same signer.
436     *
437     * @param signature
438     *            the {@code byte[]} containing the signature to verify.
439     * @param offset
440     *            the start index in {@code signature} of the signature.
441     * @param length
442     *            the number of bytes allocated for the signature.
443     * @return {@code true} if the signature was verified, {@code false}
444     *         otherwise.
445     * @throws SignatureException
446     *             if this {@code Signature} instance is not initialized
447     *             properly.
448     * @throws IllegalArgumentException
449     *             if {@code offset} or {@code length} are not valid in respect
450     *             to {@code signature}.
451     */
452    public final boolean verify(byte[] signature, int offset, int length)
453            throws SignatureException {
454        if (state != VERIFY) {
455            throw new SignatureException("Signature object is not initialized properly");
456        }
457        if (signature == null || offset < 0 || length < 0 ||
458                offset + length > signature.length) {
459            throw new IllegalArgumentException();
460        }
461        return engineVerify(signature, offset, length);
462    }
463
464    /**
465     * Updates the data to be verified or to be signed, using the specified
466     * {@code byte}.
467     *
468     * @param b
469     *            the byte to update with.
470     * @throws SignatureException
471     *             if this {@code Signature} instance is not initialized
472     *             properly.
473     */
474    public final void update(byte b) throws SignatureException {
475        if (state == UNINITIALIZED) {
476            throw new SignatureException("Signature object is not initialized properly");
477        }
478        engineUpdate(b);
479    }
480
481    /**
482     * Updates the data to be verified or to be signed, using the specified
483     * {@code byte[]}.
484     *
485     * @param data
486     *            the byte array to update with.
487     * @throws SignatureException
488     *             if this {@code Signature} instance is not initialized
489     *             properly.
490     */
491    public final void update(byte[] data) throws SignatureException {
492        if (state == UNINITIALIZED) {
493            throw new SignatureException("Signature object is not initialized properly");
494        }
495        engineUpdate(data, 0, data.length);
496    }
497
498    /**
499     * Updates the data to be verified or to be signed, using the given {@code
500     * byte[]}, starting form the specified index for the specified length.
501     *
502     * @param data
503     *            the byte array to update with.
504     * @param off
505     *            the start index in {@code data} of the data.
506     * @param len
507     *            the number of bytes to use.
508     * @throws SignatureException
509     *             if this {@code Signature} instance is not initialized
510     *             properly.
511     */
512    public final void update(byte[] data, int off, int len)
513            throws SignatureException {
514        if (state == UNINITIALIZED) {
515            throw new SignatureException("Signature object is not initialized properly");
516        }
517        if (data == null || off < 0 || len < 0 ||
518                off + len > data.length) {
519            throw new IllegalArgumentException();
520        }
521        engineUpdate(data, off, len);
522    }
523
524    /**
525     * Updates the data to be verified or to be signed, using the specified
526     * {@code ByteBuffer}.
527     *
528     * @param data
529     *            the {@code ByteBuffer} to update with.
530     * @throws SignatureException
531     *             if this {@code Signature} instance is not initialized
532     *             properly.
533     */
534    public final void update(ByteBuffer data) throws SignatureException {
535        if (state == UNINITIALIZED) {
536            throw new SignatureException("Signature object is not initialized properly");
537        }
538        engineUpdate(data);
539    }
540
541    /**
542     * Returns a string containing a concise, human-readable description of this
543     * {@code Signature} including its algorithm and its state.
544     *
545     * @return a printable representation for this {@code Signature}.
546     */
547    @Override
548    public String toString() {
549        return "SIGNATURE " + algorithm + " state: " + stateToString(state);
550    }
551
552    // Convert state to string
553    private String stateToString(int state) {
554        switch (state) {
555        case UNINITIALIZED:
556            return "UNINITIALIZED";
557        case SIGN:
558            return "SIGN";
559        case VERIFY:
560            return "VERIFY";
561        default:
562            return "";
563        }
564    }
565
566    /**
567     * Sets the specified parameter to the given value.
568     *
569     * @param param
570     *            the name of the parameter.
571     * @param value
572     *            the parameter value.
573     * @throws InvalidParameterException
574     *             if the parameter is invalid, already set or is not allowed to
575     *             be changed.
576     * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)} instead.
577     */
578    @Deprecated
579    public final void setParameter(String param, Object value)
580            throws InvalidParameterException {
581        engineSetParameter(param, value);
582    }
583
584    /**
585     * Sets the specified {@code AlgorithmParameterSpec}.
586     *
587     * @param params
588     *            the parameter to set.
589     * @throws InvalidAlgorithmParameterException
590     *             if the parameter is invalid, already set or is not allowed to
591     *             be changed.
592     */
593    public final void setParameter(AlgorithmParameterSpec params)
594            throws InvalidAlgorithmParameterException {
595        engineSetParameter(params);
596    }
597
598    /**
599     * Returns the {@code AlgorithmParameters} of this {@link Signature}
600     * instance.
601     *
602     * @return the {@code AlgorithmParameters} of this {@link Signature}
603     *         instance, maybe {@code null}.
604     */
605    public final AlgorithmParameters getParameters() {
606        return engineGetParameters();
607    }
608
609    /**
610     * Returns the value of the parameter with the specified name.
611     *
612     * @param param
613     *            the name of the requested parameter value
614     * @return the value of the parameter with the specified name, maybe {@code
615     *         null}.
616     * @throws InvalidParameterException
617     *             if {@code param} is not a valid parameter for this {@code
618     *             Signature} or an other error occurs.
619     * @deprecated There is no generally accepted parameter naming convention.
620     */
621    @Deprecated
622    public final Object getParameter(String param)
623            throws InvalidParameterException {
624        return engineGetParameter(param);
625    }
626
627    /**
628     * Internal Signature implementation
629     */
630    private static class SignatureImpl extends Signature {
631
632        /**
633         * Lock held while the SPI is initializing.
634         */
635        private final Object initLock = new Object();
636
637        // The provider specified when creating this instance.
638        private final Provider specifiedProvider;
639
640        private SignatureSpi spiImpl;
641
642        public SignatureImpl(String algorithm, Provider provider) {
643            super(algorithm);
644            this.specifiedProvider = provider;
645        }
646
647        private SignatureImpl(String algorithm, Provider provider, SignatureSpi spi) {
648            this(algorithm, provider);
649            spiImpl = spi;
650        }
651
652        @Override
653        void ensureProviderChosen() {
654            getSpi(null);
655        }
656
657        @Override
658        protected byte[] engineSign() throws SignatureException {
659            return getSpi().engineSign();
660        }
661
662        @Override
663        protected void engineUpdate(byte arg0) throws SignatureException {
664            getSpi().engineUpdate(arg0);
665        }
666
667        @Override
668        protected boolean engineVerify(byte[] arg0) throws SignatureException {
669            return getSpi().engineVerify(arg0);
670        }
671
672        @Override
673        protected void engineUpdate(byte[] arg0, int arg1, int arg2) throws SignatureException {
674            getSpi().engineUpdate(arg0, arg1, arg2);
675        }
676
677        @Override
678        protected void engineInitSign(PrivateKey arg0) throws InvalidKeyException {
679            getSpi(arg0).engineInitSign(arg0);
680        }
681
682        @Override
683        protected void engineInitVerify(PublicKey arg0) throws InvalidKeyException {
684            getSpi(arg0).engineInitVerify(arg0);
685        }
686
687        @Override
688        protected Object engineGetParameter(String arg0) throws InvalidParameterException {
689            return getSpi().engineGetParameter(arg0);
690        }
691
692        @Override
693        protected void engineSetParameter(String arg0, Object arg1)
694                throws InvalidParameterException {
695            getSpi().engineSetParameter(arg0, arg1);
696        }
697
698        @Override
699        protected void engineSetParameter(AlgorithmParameterSpec arg0)
700                throws InvalidAlgorithmParameterException {
701            getSpi().engineSetParameter(arg0);
702        }
703
704        @Override
705        public Object clone() throws CloneNotSupportedException {
706            SignatureSpi spi = spiImpl != null ? (SignatureSpi) spiImpl.clone() : null;
707            return new SignatureImpl(getAlgorithm(), getProvider(), spi);
708        }
709
710        /**
711         * Makes sure a CipherSpi that matches this type is selected.
712         */
713        private SignatureSpi getSpi(Key key) {
714            synchronized (initLock) {
715                if (spiImpl != null && key == null) {
716                    return spiImpl;
717                }
718
719                final Engine.SpiAndProvider sap = tryAlgorithm(key, specifiedProvider, algorithm);
720                if (sap == null) {
721                    throw new ProviderException("No provider for " + getAlgorithm());
722                }
723
724                spiImpl = (SignatureSpi) sap.spi;
725                provider = sap.provider;
726
727                return spiImpl;
728            }
729        }
730
731        /**
732         * Convenience call when the Key is not available.
733         */
734        private SignatureSpi getSpi() {
735            return getSpi(null);
736        }
737    }
738}
739