1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/**
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements. See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership. The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License. You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied. See the License for the
20 * specific language governing permissions and limitations
21 * under the License.
22 */
23package com.sun.org.apache.xml.internal.security.algorithms.implementations;
24
25import java.io.IOException;
26import java.security.InvalidAlgorithmParameterException;
27import java.security.InvalidKeyException;
28import java.security.Key;
29import java.security.PrivateKey;
30import java.security.PublicKey;
31import java.security.SecureRandom;
32import java.security.Signature;
33import java.security.SignatureException;
34import java.security.interfaces.DSAKey;
35import java.security.spec.AlgorithmParameterSpec;
36
37import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
38import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
39import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
40import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
41import com.sun.org.apache.xml.internal.security.utils.Base64;
42import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
43
44public class SignatureDSA extends SignatureAlgorithmSpi {
45
46    /** {@link org.apache.commons.logging} logging facility */
47    private static java.util.logging.Logger log =
48        java.util.logging.Logger.getLogger(SignatureDSA.class.getName());
49
50    /** Field algorithm */
51    private java.security.Signature signatureAlgorithm = null;
52
53    /** size of Q */
54    private int size;
55
56    /**
57     * Method engineGetURI
58     *
59     * @inheritDoc
60     */
61    protected String engineGetURI() {
62        return XMLSignature.ALGO_ID_SIGNATURE_DSA;
63    }
64
65    /**
66     * Constructor SignatureDSA
67     *
68     * @throws XMLSignatureException
69     */
70    public SignatureDSA() throws XMLSignatureException {
71        String algorithmID = JCEMapper.translateURItoJCEID(engineGetURI());
72        if (log.isLoggable(java.util.logging.Level.FINE)) {
73            log.log(java.util.logging.Level.FINE, "Created SignatureDSA using " + algorithmID);
74        }
75
76        String provider = JCEMapper.getProviderId();
77        try {
78            if (provider == null) {
79                this.signatureAlgorithm = Signature.getInstance(algorithmID);
80            } else {
81                this.signatureAlgorithm =
82                    Signature.getInstance(algorithmID, provider);
83            }
84        } catch (java.security.NoSuchAlgorithmException ex) {
85            Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
86            throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
87        } catch (java.security.NoSuchProviderException ex) {
88            Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
89            throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
90        }
91    }
92
93    /**
94     * @inheritDoc
95     */
96    protected void engineSetParameter(AlgorithmParameterSpec params)
97        throws XMLSignatureException {
98        try {
99            this.signatureAlgorithm.setParameter(params);
100        } catch (InvalidAlgorithmParameterException ex) {
101            throw new XMLSignatureException("empty", ex);
102        }
103    }
104
105    /**
106     * @inheritDoc
107     */
108    protected boolean engineVerify(byte[] signature)
109        throws XMLSignatureException {
110        try {
111            if (log.isLoggable(java.util.logging.Level.FINE)) {
112                log.log(java.util.logging.Level.FINE, "Called DSA.verify() on " + Base64.encode(signature));
113            }
114
115            byte[] jcebytes = JavaUtils.convertDsaXMLDSIGtoASN1(signature,
116                                                                size/8);
117
118            return this.signatureAlgorithm.verify(jcebytes);
119        } catch (SignatureException ex) {
120            throw new XMLSignatureException("empty", ex);
121        } catch (IOException ex) {
122            throw new XMLSignatureException("empty", ex);
123        }
124    }
125
126    /**
127     * @inheritDoc
128     */
129    protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
130        if (!(publicKey instanceof PublicKey)) {
131            String supplied = publicKey.getClass().getName();
132            String needed = PublicKey.class.getName();
133            Object exArgs[] = { supplied, needed };
134
135            throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
136        }
137
138        try {
139            this.signatureAlgorithm.initVerify((PublicKey) publicKey);
140        } catch (InvalidKeyException ex) {
141            // reinstantiate Signature object to work around bug in JDK
142            // see: http://bugs.java.com/view_bug.do?bug_id=4953555
143            Signature sig = this.signatureAlgorithm;
144            try {
145                this.signatureAlgorithm = Signature.getInstance(signatureAlgorithm.getAlgorithm());
146            } catch (Exception e) {
147                // this shouldn't occur, but if it does, restore previous
148                // Signature
149                if (log.isLoggable(java.util.logging.Level.FINE)) {
150                    log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Signature:" + e);
151                }
152                this.signatureAlgorithm = sig;
153            }
154            throw new XMLSignatureException("empty", ex);
155        }
156        size = ((DSAKey)publicKey).getParams().getQ().bitLength();
157    }
158
159    /**
160     * @inheritDoc
161     */
162    protected byte[] engineSign() throws XMLSignatureException {
163        try {
164            byte jcebytes[] = this.signatureAlgorithm.sign();
165
166            return JavaUtils.convertDsaASN1toXMLDSIG(jcebytes, size/8);
167        } catch (IOException ex) {
168            throw new XMLSignatureException("empty", ex);
169        } catch (SignatureException ex) {
170            throw new XMLSignatureException("empty", ex);
171        }
172    }
173
174    /**
175     * @inheritDoc
176     */
177    protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
178        throws XMLSignatureException {
179        if (!(privateKey instanceof PrivateKey)) {
180            String supplied = privateKey.getClass().getName();
181            String needed = PrivateKey.class.getName();
182            Object exArgs[] = { supplied, needed };
183
184            throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
185        }
186
187        try {
188            this.signatureAlgorithm.initSign((PrivateKey) privateKey, secureRandom);
189        } catch (InvalidKeyException ex) {
190            throw new XMLSignatureException("empty", ex);
191        }
192        size = ((DSAKey)privateKey).getParams().getQ().bitLength();
193    }
194
195    /**
196     * @inheritDoc
197     */
198    protected void engineInitSign(Key privateKey) throws XMLSignatureException {
199        if (!(privateKey instanceof PrivateKey)) {
200            String supplied = privateKey.getClass().getName();
201            String needed = PrivateKey.class.getName();
202            Object exArgs[] = { supplied, needed };
203
204            throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
205        }
206
207        try {
208            this.signatureAlgorithm.initSign((PrivateKey) privateKey);
209        } catch (InvalidKeyException ex) {
210            throw new XMLSignatureException("empty", ex);
211        }
212        size = ((DSAKey)privateKey).getParams().getQ().bitLength();
213    }
214
215    /**
216     * @inheritDoc
217     */
218    protected void engineUpdate(byte[] input) throws XMLSignatureException {
219        try {
220            this.signatureAlgorithm.update(input);
221        } catch (SignatureException ex) {
222            throw new XMLSignatureException("empty", ex);
223        }
224    }
225
226    /**
227     * @inheritDoc
228     */
229    protected void engineUpdate(byte input) throws XMLSignatureException {
230        try {
231            this.signatureAlgorithm.update(input);
232        } catch (SignatureException ex) {
233            throw new XMLSignatureException("empty", ex);
234        }
235    }
236
237    /**
238     * @inheritDoc
239     */
240    protected void engineUpdate(byte buf[], int offset, int len) throws XMLSignatureException {
241        try {
242            this.signatureAlgorithm.update(buf, offset, len);
243        } catch (SignatureException ex) {
244            throw new XMLSignatureException("empty", ex);
245        }
246    }
247
248    /**
249     * Method engineGetJCEAlgorithmString
250     *
251     * @inheritDoc
252     */
253    protected String engineGetJCEAlgorithmString() {
254        return this.signatureAlgorithm.getAlgorithm();
255    }
256
257    /**
258     * Method engineGetJCEProviderName
259     *
260     * @inheritDoc
261     */
262    protected String engineGetJCEProviderName() {
263        return this.signatureAlgorithm.getProvider().getName();
264    }
265
266    /**
267     * Method engineSetHMACOutputLength
268     *
269     * @param HMACOutputLength
270     * @throws XMLSignatureException
271     */
272    protected void engineSetHMACOutputLength(int HMACOutputLength) throws XMLSignatureException {
273        throw new XMLSignatureException("algorithms.HMACOutputLengthOnlyForHMAC");
274    }
275
276    /**
277     * Method engineInitSign
278     *
279     * @param signingKey
280     * @param algorithmParameterSpec
281     * @throws XMLSignatureException
282     */
283    protected void engineInitSign(
284        Key signingKey, AlgorithmParameterSpec algorithmParameterSpec
285    ) throws XMLSignatureException {
286        throw new XMLSignatureException("algorithms.CannotUseAlgorithmParameterSpecOnDSA");
287    }
288
289    public static class SHA256 extends SignatureDSA {
290
291        public SHA256() throws XMLSignatureException {
292            super();
293        }
294
295        public String engineGetURI() {
296            return XMLSignature.ALGO_ID_SIGNATURE_DSA_SHA256;
297        }
298    }
299}
300