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
18/**
19* @author Boris V. Kuznetsov
20* @version $Revision$
21*/
22
23package org.apache.harmony.security.tests.java.security;
24
25import dalvik.annotation.KnownFailure;
26
27import java.security.InvalidParameterException;
28import java.security.NoSuchAlgorithmException;
29import java.security.Provider;
30import java.security.Security;
31import java.security.Signature;
32import java.security.InvalidAlgorithmParameterException;
33import java.security.InvalidKeyException;
34import java.security.Key;
35import java.security.PrivateKey;
36import java.security.PublicKey;
37import java.security.SecureRandom;
38import java.security.SignatureException;
39import java.security.SignatureSpi;
40import java.security.cert.Certificate;
41import java.security.spec.AlgorithmParameterSpec;
42
43import org.apache.harmony.security.tests.support.MySignature1;
44
45import junit.framework.TestCase;
46
47/**
48 * Tests for <code>Signature</code> constructor and methods
49 *
50 */
51public class SignatureTest extends TestCase {
52
53    /*
54     * Class under test for Signature(String)
55     */
56    public void testConstructor() {
57        String [] algorithms = { "SHA256WITHRSA", "NONEWITHDSA", "SHA384WITHRSA",
58            "MD5ANDSHA1WITHRSA", "SHA512WITHRSA",
59            "SHA1WITHRSA", "SHA1WITHDSA", "MD5WITHRSA" };
60        for (int i = 0; i < algorithms.length; i ++) {
61            MySignature1 s = new MySignature1(algorithms[i]);
62            assertEquals(algorithms[i],s.getAlgorithm());
63            assertNull(s.getProvider());
64            assertEquals(0, s.getState());
65        }
66
67        MySignature1 s1 = new MySignature1(null);
68        assertNull(s1.getAlgorithm());
69        assertNull(s1.getProvider());
70        assertEquals(0, s1.getState());
71
72        MySignature1 s2 = new MySignature1("ABCD@#&^%$)(*&");
73        assertEquals("ABCD@#&^%$)(*&", s2.getAlgorithm());
74        assertNull(s2.getProvider());
75        assertEquals(0, s2.getState());
76    }
77
78    /*
79     * Class under test for Object clone()
80     */
81    public void testClone() {
82        MySignature1 s = new MySignature1("ABC");
83        try {
84            s.clone();
85            fail("No expected CloneNotSupportedException");
86        } catch (CloneNotSupportedException e) {
87        }
88
89        MySignature sc = new MySignature();
90        try {
91            sc.clone();
92        } catch (CloneNotSupportedException e) {
93            fail("unexpected exception: " + e);
94        }
95
96    }
97
98    public void testGetProvider() {
99        MySignature1 s = new MySignature1("ABC");
100
101        assertEquals("state", MySignature1.UNINITIALIZED, s.getState());
102        assertNull("provider", s.getProvider());
103    }
104
105    public void testGetAlgorithm() {
106        MySignature1 s = new MySignature1("ABC");
107
108        assertEquals("state", MySignature1.UNINITIALIZED, s.getState());
109        assertEquals("algorithm", "ABC", s.getAlgorithm());
110    }
111
112    /*
113     * Class under test for void initVerify(PublicKey)
114     */
115    public void testInitVerifyPublicKey() throws InvalidKeyException {
116        MySignature1 s = new MySignature1("ABC");
117
118        s.initVerify(new MyPublicKey());
119        assertEquals("state", MySignature1.VERIFY, s.getState());
120        assertTrue("initVerify() failed", s.runEngineInitVerify);
121
122        try {
123            Signature sig = getTestSignature();
124            sig.initVerify((PublicKey)null);
125        } catch (InvalidKeyException e) {
126            // ok
127        } catch (NoSuchAlgorithmException e) {
128            fail("unexpected : " + e);
129        }
130    }
131
132    /*
133     * Class under test for void initVerify(Certificate)
134     */
135    public void testInitVerifyCertificate() throws InvalidKeyException {
136        MySignature1 s = new MySignature1("ABC");
137
138        s.initVerify(new MyCertificate());
139        assertEquals("state", MySignature1.VERIFY, s.getState());
140        assertTrue("initVerify() failed", s.runEngineInitVerify);
141
142        try {
143            Signature sig = getTestSignature();
144            sig.initVerify(new MyCertificate());
145            fail("expected InvalidKeyException");
146        } catch (InvalidKeyException e) {
147            // ok
148        } catch (NoSuchAlgorithmException e) {
149            fail("unexpected : " + e);
150        }
151    }
152
153    /*
154     * Class under test for void initSign(PrivateKey)
155     */
156    public void testInitSignPrivateKey() throws InvalidKeyException {
157        MySignature1 s = new MySignature1("ABC");
158
159        s.initSign(new MyPrivateKey());
160        assertEquals("state", MySignature1.SIGN, s.getState());
161        assertTrue("initSign() failed", s.runEngineInitSign);
162
163        try {
164            Signature signature = getTestSignature();
165            signature.initSign(null);
166            fail("expected InvalidKeyException");
167        } catch (InvalidKeyException e) {
168            // ok
169        } catch (NoSuchAlgorithmException e) {
170            fail("unexpected: " + e);
171        }
172    }
173
174    private Signature getTestSignature() throws NoSuchAlgorithmException {
175        Provider provider = new MyProvider("TestProvider", 1.0, "Test Provider", "Signature.ABC", MySignature.class.getName());
176        Security.insertProviderAt(provider, 1);
177
178        try {
179            return Signature.getInstance("ABC");
180        }
181        finally {
182           Security.removeProvider("TestProvider");
183        }
184
185    }
186
187    /*
188     * Class under test for void initSign(PrivateKey, SecureRandom)
189     */
190    public void testInitSignPrivateKeySecureRandom() throws InvalidKeyException {
191        MySignature1 s = new MySignature1("ABC");
192
193        s.initSign(new MyPrivateKey(), new SecureRandom());
194        assertEquals("state", MySignature1.SIGN, s.getState());
195        assertTrue("initSign() failed", s.runEngineInitSign);
196
197        try {
198            Signature sig = getTestSignature();
199            sig.initSign(null, null);
200            fail("expected InvalidKeyException");
201        } catch (InvalidKeyException e) {
202            // ok
203        } catch (NoSuchAlgorithmException e) {
204            fail("unexpected : " + e);
205        }
206    }
207
208    /*
209     * Class under test for byte[] sign()
210     */
211    public void testSign() throws Exception {
212        MySignature1 s = new MySignature1("ABC");
213        try {
214            s.sign();
215            fail("No expected SignatureException");
216        } catch (SignatureException e) {
217        }
218
219        s.initVerify(new MyPublicKey());
220
221        try {
222            s.sign();
223            fail("No expected SignatureException");
224        } catch (SignatureException e) {
225        }
226
227        s.initSign(new MyPrivateKey());
228        s.sign();
229        assertEquals("state", MySignature1.SIGN, s.getState());
230        assertTrue("sign() failed", s.runEngineSign);
231    }
232
233    /*
234     * Class under test for sign(byte[], offset, len)
235     */
236    public void testSignbyteintint() throws Exception {
237        MySignature1 s = new MySignature1("ABC");
238        byte[] outbuf = new byte [10];
239        try {
240            s.sign(outbuf, 0, outbuf.length);
241            fail("No expected SignatureException");
242        } catch (SignatureException e) {
243        }
244
245        s.initVerify(new MyPublicKey());
246
247        try {
248            s.sign(outbuf, 0, outbuf.length);
249            fail("No expected SignatureException");
250        } catch (SignatureException e) {
251        }
252
253        s.initSign(new MyPrivateKey());
254        assertEquals(s.getBufferLength(), s.sign(outbuf, 0, outbuf.length));
255        assertEquals("state", MySignature1.SIGN, s.getState());
256        assertTrue("sign() failed", s.runEngineSign);
257
258        try {
259            s.initSign(new MyPrivateKey());
260            s.sign(outbuf, outbuf.length, 0);
261            fail("expected SignatureException");
262        } catch (SignatureException e) {
263            // ok
264        }
265
266        try {
267            s.initSign(new MyPrivateKey());
268            s.sign(outbuf, outbuf.length, 3);
269            fail("expected IllegalArgumentException");
270        } catch (IllegalArgumentException e) {
271            // ok
272        }
273
274    }
275
276
277    /*
278     * Class under test for boolean verify(byte[])
279     */
280    public void testVerifybyteArray() throws Exception {
281        MySignature1 s = new MySignature1("ABC");
282        byte[] b = {1, 2, 3, 4};
283        try {
284            s.verify(b);
285            fail("No expected SignatureException");
286        } catch (SignatureException e) {
287        }
288
289        s.initSign(new MyPrivateKey());
290        try {
291            s.verify(b);
292            fail("No expected SignatureException");
293        } catch (SignatureException e) {
294        }
295
296        s.initVerify(new MyPublicKey());
297        s.verify(b);
298        assertEquals("state", MySignature1.VERIFY, s.getState());
299        assertTrue("verify() failed", s.runEngineVerify);
300    }
301
302    /*
303     * Class under test for boolean verify(byte[], int, int)
304     */
305    public void testVerifybyteArrayintint() throws Exception {
306        MySignature1 s = new MySignature1("ABC");
307        byte[] b = {1, 2, 3, 4};
308        try {
309            s.verify(b, 0, 3);
310            fail("No expected SignatureException");
311        } catch (SignatureException e) {
312        }
313
314        s.initSign(new MyPrivateKey());
315
316        try {
317            s.verify(b, 0, 3);
318            fail("No expected SignatureException");
319        } catch (SignatureException e) {
320        }
321
322        s.initVerify(new MyPublicKey());
323
324        try {
325            s.verify(b, 0, 5);
326            fail("No expected IllegalArgumentException");
327        } catch (IllegalArgumentException e) {
328        }
329
330        s.verify(b, 0, 3);
331        assertEquals("state", MySignature1.VERIFY, s.getState());
332        assertTrue("verify() failed", s.runEngineVerify);
333    }
334
335    /*
336     * Class under test for void update(byte)
337     */
338    public void testUpdatebyte() throws Exception {
339        MySignature1 s = new MySignature1("ABC");
340        try {
341            s.update((byte)1);
342            fail("No expected SignatureException");
343        } catch (SignatureException e) {
344        }
345
346        s.initVerify(new MyPublicKey());
347        s.update((byte) 1);
348        s.initSign(new MyPrivateKey());
349        s.update((byte) 1);
350
351        assertEquals("state", MySignature1.SIGN, s.getState());
352        assertTrue("update() failed", s.runEngineUpdate1);
353
354        try {
355            Signature sig = getTestSignature();
356            sig.update((byte) 42);
357            fail("expected SignatureException");
358        } catch (SignatureException e) {
359            // ok
360        }
361    }
362
363    /*
364     * Class under test for void update(byte[])
365     */
366    public void testUpdatebyteArray() throws Exception {
367        MySignature1 s = new MySignature1("ABC");
368        byte[] b = {1, 2, 3, 4};
369        try {
370            s.update(b);
371            fail("No expected SignatureException");
372        } catch (SignatureException e) {
373        }
374
375        s.initVerify(new MyPublicKey());
376        s.update(b);
377        s.initSign(new MyPrivateKey());
378        s.update(b);
379
380        assertEquals("state", MySignature1.SIGN, s.getState());
381        assertTrue("update() failed", s.runEngineUpdate2);
382
383        try {
384            Signature sig = getTestSignature();
385            sig.update(b);
386            fail("expected SignatureException");
387        } catch (SignatureException e) {
388            // ok
389        }
390
391        try {
392            Signature sig = getTestSignature();
393            sig.update((byte[])null);
394            fail("expected NullPointerException");
395        } catch (SignatureException e) {
396            // ok
397        } catch (NullPointerException e) {
398            // ok
399        }
400    }
401
402    /*
403     * Class under test for void update(byte[], int, int)
404     */
405    public void testUpdatebyteArrayintint() throws Exception {
406        MySignature1 s = new MySignature1("ABC");
407        byte[] b = {1, 2, 3, 4};
408        try {
409            s.update(b, 0, 3);
410            fail("No expected SignatureException");
411        } catch (SignatureException e) {
412        }
413
414        s.initVerify(new MyPublicKey());
415        s.update(b, 0, 3);
416        s.initSign(new MyPrivateKey());
417        s.update(b, 0, 3);
418
419        assertEquals("state", MySignature1.SIGN, s.getState());
420        assertTrue("update() failed", s.runEngineUpdate2);
421
422        try {
423            s.update(b, 3, 0);
424            fail("expected IllegalArgumentException");
425        } catch (IllegalArgumentException e) {
426            // ok
427        }
428
429        try {
430            s.update(b, 0, b.length + 1);
431            fail("expected IllegalArgumentException");
432        } catch (IllegalArgumentException e) {
433            // ok
434        }
435
436        try {
437            s.update(b, -1, b.length);
438            fail("expected IllegalArgumentException");
439        } catch (IllegalArgumentException e) {
440            // ok
441        }
442
443    }
444
445    /*
446     * Class under test for void update(byte[], int, int)
447     */
448    @KnownFailure("Android throws IllegalArgumentException, RI throws NullpointerException")
449    public void testUpdatebyteArrayintint2() throws Exception {
450        MySignature1 s = new MySignature1("ABC");
451        byte[] b = {1, 2, 3, 4};
452
453        s.initVerify(new MyPublicKey());
454        s.update(b, 0, 3);
455        s.initSign(new MyPrivateKey());
456        s.update(b, 0, 3);
457
458        assertEquals("state", MySignature1.SIGN, s.getState());
459        assertTrue("update() failed", s.runEngineUpdate2);
460
461        try {
462            s.update(null, 0, 3);
463            fail("NullPointerException wasn't thrown");
464        } catch (NullPointerException npe) {
465            // ok
466        }
467    }
468
469
470    /*
471     * Class under test for void setParameter(String, Object)
472     */
473    @SuppressWarnings("deprecation")
474    public void testSetParameterStringObject() {
475        MySignature1 s = new MySignature1("ABC");
476        s.setParameter("aaa", new Object());
477
478        try {
479            Signature sig = getTestSignature();
480            sig.setParameter("TestParam", new Integer(42));
481            fail("expected InvalidParameterException");
482        } catch (InvalidParameterException e) {
483            // expected
484        } catch (NoSuchAlgorithmException e) {
485            fail("unexpected: " + e);
486        }
487    }
488
489    /*
490     * Class under test for void setParameter(AlgorithmParameterSpec)
491     */
492    public void testSetParameterAlgorithmParameterSpec() throws InvalidAlgorithmParameterException {
493        MySignature1 s = new MySignature1("ABC");
494        try {
495            s.setParameter((java.security.spec.AlgorithmParameterSpec)null);
496            fail("No expected UnsupportedOperationException");
497        } catch (UnsupportedOperationException e){
498        }
499
500        try {
501            Signature sig = getTestSignature();
502            sig.setParameter(new AlgorithmParameterSpec() {});
503        } catch (InvalidAlgorithmParameterException e) {
504            fail("unexpected: " + e);
505        } catch (NoSuchAlgorithmException e) {
506            fail("unexpected: " + e);
507        }
508    }
509
510    @SuppressWarnings("deprecation")
511    public void testGetParameter() {
512        MySignature1 s = new MySignature1("ABC");
513        s.getParameter("aaa");
514
515        try {
516            MySignature se = new MySignature();
517            se.getParameter("test");
518        } catch (InvalidParameterException e) {
519            // ok
520        }
521
522    }
523
524    // https://android-review.googlesource.com/#/c/309105/
525    // http://b/33383388
526    // getCurrentSpi throws a NPE on a Signature that was obtained via a provider that has that
527    // algorithm registered for a SignatureSpi.
528    public void testSignature_getCurrentSpi_Success() throws Exception {
529        Provider provider = new MyProvider(
530                "TestProvider", 1.0, "Test Provider", "Signature.ABC",
531                MySignatureSpi.class.getName());
532        Signature signature = Signature.getInstance("ABC", provider);
533        assertNotNull(signature.getCurrentSpi());
534        assertEquals(MySignatureSpi.class, signature.getCurrentSpi().getClass());
535    }
536
537    private class MyKey implements Key {
538        public String getFormat() {
539            return "123";
540        }
541        public byte[] getEncoded() {
542            return null;
543        }
544        public String getAlgorithm() {
545            return "aaa";
546        }
547    }
548
549    private class MyPublicKey extends MyKey implements PublicKey {}
550
551    private class MyPrivateKey extends MyKey implements PrivateKey {}
552
553    private class MyCertificate extends java.security.cert.Certificate {
554        public  MyCertificate() {
555            super("MyCertificateType");
556        }
557
558        public PublicKey getPublicKey() {
559            return new MyPublicKey();
560        }
561
562        public byte[] getEncoded() {
563            return null;
564        }
565        public void verify(PublicKey key) {}
566
567        public void verify(PublicKey key, String sigProvider) {}
568
569        public String toString() {
570            return "MyCertificate";
571        }
572    }
573
574    @SuppressWarnings("unused")
575    // Needs to be public as this is checked by the provider class when providing an instance of
576    // a class
577    // There is a lot of code duplication, or better said, signature duplication with respect to
578    // MySignatureSpi. However, as for the test to check the desired functionality this class
579    // must extend from Signature and MySignatureSpi must extend from SignatureSpi. Then there is
580    // no way to avoid duplication other than delegation, but delegation would require to repeat
581    // all method signatures once more.
582    public static class MySignature extends Signature implements Cloneable {
583
584        public MySignature() {
585            super("TestSignature");
586        }
587
588        @Override
589        protected Object engineGetParameter(String param)
590                throws InvalidParameterException {
591            throw new InvalidParameterException();
592        }
593
594        @Override
595        protected void engineInitSign(PrivateKey privateKey)
596                throws InvalidKeyException {
597            throw new InvalidKeyException();
598        }
599
600        @Override
601        protected void engineInitVerify(PublicKey publicKey)
602                throws InvalidKeyException {
603            throw new InvalidKeyException();
604        }
605
606        @Override
607        protected void engineSetParameter(String param, Object value)
608                throws InvalidParameterException {
609            throw new InvalidParameterException();
610        }
611
612        @Override
613        protected byte[] engineSign() throws SignatureException {
614            return null;
615        }
616
617        @Override
618        protected void engineUpdate(byte b) throws SignatureException {
619            throw new SignatureException();
620        }
621
622        @Override
623        protected void engineUpdate(byte[] b, int off, int len)
624                throws SignatureException {
625
626        }
627
628        @Override
629        protected boolean engineVerify(byte[] sigBytes)
630                throws SignatureException {
631            return false;
632        }
633
634        @Override
635        protected void engineSetParameter(AlgorithmParameterSpec params)
636                throws InvalidAlgorithmParameterException {
637            if (params == null) {
638                throw new InvalidAlgorithmParameterException();
639            }
640        }
641    }
642
643    @SuppressWarnings("unused")
644    // Needs to be public as this is checked by the provider class when providing an instance of
645    // a class
646    public static class MySignatureSpi extends SignatureSpi implements Cloneable {
647
648        @Override
649        protected Object engineGetParameter(String param)
650                throws InvalidParameterException {
651            throw new InvalidParameterException();
652        }
653
654        @Override
655        protected void engineInitSign(PrivateKey privateKey)
656                throws InvalidKeyException {
657            throw new InvalidKeyException();
658        }
659
660        @Override
661        protected void engineInitVerify(PublicKey publicKey)
662                throws InvalidKeyException {
663            throw new InvalidKeyException();
664        }
665
666        @Override
667        protected void engineSetParameter(String param, Object value)
668                throws InvalidParameterException {
669            throw new InvalidParameterException();
670        }
671
672        @Override
673        protected byte[] engineSign() throws SignatureException {
674            return null;
675        }
676
677        @Override
678        protected void engineUpdate(byte b) throws SignatureException {
679            throw new SignatureException();
680        }
681
682        @Override
683        protected void engineUpdate(byte[] b, int off, int len)
684                throws SignatureException {
685
686        }
687
688        @Override
689        protected boolean engineVerify(byte[] sigBytes)
690                throws SignatureException {
691            return false;
692        }
693
694        @Override
695        protected void engineSetParameter(AlgorithmParameterSpec params)
696                throws InvalidAlgorithmParameterException {
697            if (params == null) {
698                throw new InvalidAlgorithmParameterException();
699            }
700        }
701    }
702
703    private class MyProvider extends Provider {
704
705        protected MyProvider(String name, double version, String info, String signame, String className) {
706            super(name, version, info);
707            put(signame, className);
708        }
709
710    }
711}
712