View Javadoc
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   */
23  package com.sun.org.apache.xml.internal.security.algorithms.implementations;
24  
25  import java.security.InvalidAlgorithmParameterException;
26  import java.security.InvalidKeyException;
27  import java.security.Key;
28  import java.security.SecureRandom;
29  import java.security.spec.AlgorithmParameterSpec;
30  
31  import javax.crypto.Mac;
32  import javax.crypto.SecretKey;
33  
34  import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
35  import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
36  import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
37  import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
38  import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
39  import com.sun.org.apache.xml.internal.security.utils.Constants;
40  import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
41  import org.w3c.dom.Document;
42  import org.w3c.dom.Element;
43  import org.w3c.dom.Text;
44  
45  public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
46  
47      /** {@link org.apache.commons.logging} logging facility */
48      private static java.util.logging.Logger log =
49          java.util.logging.Logger.getLogger(IntegrityHmac.class.getName());
50  
51      /** Field macAlgorithm */
52      private Mac macAlgorithm = null;
53  
54      /** Field HMACOutputLength */
55      private int HMACOutputLength = 0;
56      private boolean HMACOutputLengthSet = false;
57  
58      /**
59       * Method engineGetURI
60       *
61       *@inheritDoc
62       */
63      public abstract String engineGetURI();
64  
65      /**
66       * Returns the output length of the hash/digest.
67       */
68      abstract int getDigestLength();
69  
70      /**
71       * Method IntegrityHmac
72       *
73       * @throws XMLSignatureException
74       */
75      public IntegrityHmac() throws XMLSignatureException {
76          String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
77          if (log.isLoggable(java.util.logging.Level.FINE)) {
78              log.log(java.util.logging.Level.FINE, "Created IntegrityHmacSHA1 using " + algorithmID);
79          }
80  
81          try {
82              this.macAlgorithm = Mac.getInstance(algorithmID);
83          } catch (java.security.NoSuchAlgorithmException ex) {
84              Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
85  
86              throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
87          }
88      }
89  
90      /**
91       * Proxy method for {@link java.security.Signature#setParameter(
92       * java.security.spec.AlgorithmParameterSpec)}
93       * which is executed on the internal {@link java.security.Signature} object.
94       *
95       * @param params
96       * @throws XMLSignatureException
97       */
98      protected void engineSetParameter(AlgorithmParameterSpec params) throws XMLSignatureException {
99          throw new XMLSignatureException("empty");
100     }
101 
102     public void reset() {
103         HMACOutputLength = 0;
104         HMACOutputLengthSet = false;
105         this.macAlgorithm.reset();
106     }
107 
108     /**
109      * Proxy method for {@link java.security.Signature#verify(byte[])}
110      * which is executed on the internal {@link java.security.Signature} object.
111      *
112      * @param signature
113      * @return true if the signature is correct
114      * @throws XMLSignatureException
115      */
116     protected boolean engineVerify(byte[] signature) throws XMLSignatureException {
117         try {
118             if (this.HMACOutputLengthSet && this.HMACOutputLength < getDigestLength()) {
119                 if (log.isLoggable(java.util.logging.Level.FINE)) {
120                     log.log(java.util.logging.Level.FINE, "HMACOutputLength must not be less than " + getDigestLength());
121                 }
122                 Object[] exArgs = { String.valueOf(getDigestLength()) };
123                 throw new XMLSignatureException("algorithms.HMACOutputLengthMin", exArgs);
124             } else {
125                 byte[] completeResult = this.macAlgorithm.doFinal();
126                 return MessageDigestAlgorithm.isEqual(completeResult, signature);
127             }
128         } catch (IllegalStateException ex) {
129             throw new XMLSignatureException("empty", ex);
130         }
131     }
132 
133     /**
134      * Proxy method for {@link java.security.Signature#initVerify(java.security.PublicKey)}
135      * which is executed on the internal {@link java.security.Signature} object.
136      *
137      * @param secretKey
138      * @throws XMLSignatureException
139      */
140     protected void engineInitVerify(Key secretKey) throws XMLSignatureException {
141         if (!(secretKey instanceof SecretKey)) {
142             String supplied = secretKey.getClass().getName();
143             String needed = SecretKey.class.getName();
144             Object exArgs[] = { supplied, needed };
145 
146             throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
147         }
148 
149         try {
150             this.macAlgorithm.init(secretKey);
151         } catch (InvalidKeyException ex) {
152             // reinstantiate Mac object to work around bug in JDK
153             // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
154             Mac mac = this.macAlgorithm;
155             try {
156                 this.macAlgorithm = Mac.getInstance(macAlgorithm.getAlgorithm());
157             } catch (Exception e) {
158                 // this shouldn't occur, but if it does, restore previous Mac
159                 if (log.isLoggable(java.util.logging.Level.FINE)) {
160                     log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Mac:" + e);
161                 }
162                 this.macAlgorithm = mac;
163             }
164             throw new XMLSignatureException("empty", ex);
165         }
166     }
167 
168     /**
169      * Proxy method for {@link java.security.Signature#sign()}
170      * which is executed on the internal {@link java.security.Signature} object.
171      *
172      * @return the result of the {@link java.security.Signature#sign()} method
173      * @throws XMLSignatureException
174      */
175     protected byte[] engineSign() throws XMLSignatureException {
176         try {
177             if (this.HMACOutputLengthSet && this.HMACOutputLength < getDigestLength()) {
178                 if (log.isLoggable(java.util.logging.Level.FINE)) {
179                     log.log(java.util.logging.Level.FINE, "HMACOutputLength must not be less than " + getDigestLength());
180                 }
181                 Object[] exArgs = { String.valueOf(getDigestLength()) };
182                 throw new XMLSignatureException("algorithms.HMACOutputLengthMin", exArgs);
183             } else {
184                 return this.macAlgorithm.doFinal();
185             }
186         } catch (IllegalStateException ex) {
187             throw new XMLSignatureException("empty", ex);
188         }
189     }
190 
191     /**
192      * Method engineInitSign
193      *
194      * @param secretKey
195      * @throws XMLSignatureException
196      */
197     protected void engineInitSign(Key secretKey) throws XMLSignatureException {
198         if (!(secretKey instanceof SecretKey)) {
199             String supplied = secretKey.getClass().getName();
200             String needed = SecretKey.class.getName();
201             Object exArgs[] = { supplied, needed };
202 
203             throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
204         }
205 
206         try {
207             this.macAlgorithm.init(secretKey);
208         } catch (InvalidKeyException ex) {
209             throw new XMLSignatureException("empty", ex);
210         }
211     }
212 
213     /**
214      * Method engineInitSign
215      *
216      * @param secretKey
217      * @param algorithmParameterSpec
218      * @throws XMLSignatureException
219      */
220     protected void engineInitSign(
221         Key secretKey, AlgorithmParameterSpec algorithmParameterSpec
222     ) throws XMLSignatureException {
223         if (!(secretKey instanceof SecretKey)) {
224             String supplied = secretKey.getClass().getName();
225             String needed = SecretKey.class.getName();
226             Object exArgs[] = { supplied, needed };
227 
228             throw new XMLSignatureException("algorithms.WrongKeyForThisOperation", exArgs);
229         }
230 
231         try {
232             this.macAlgorithm.init(secretKey, algorithmParameterSpec);
233         } catch (InvalidKeyException ex) {
234             throw new XMLSignatureException("empty", ex);
235         } catch (InvalidAlgorithmParameterException ex) {
236             throw new XMLSignatureException("empty", ex);
237         }
238     }
239 
240     /**
241      * Method engineInitSign
242      *
243      * @param secretKey
244      * @param secureRandom
245      * @throws XMLSignatureException
246      */
247     protected void engineInitSign(Key secretKey, SecureRandom secureRandom)
248         throws XMLSignatureException {
249         throw new XMLSignatureException("algorithms.CannotUseSecureRandomOnMAC");
250     }
251 
252     /**
253      * Proxy method for {@link java.security.Signature#update(byte[])}
254      * which is executed on the internal {@link java.security.Signature} object.
255      *
256      * @param input
257      * @throws XMLSignatureException
258      */
259     protected void engineUpdate(byte[] input) throws XMLSignatureException {
260         try {
261             this.macAlgorithm.update(input);
262         } catch (IllegalStateException ex) {
263             throw new XMLSignatureException("empty", ex);
264         }
265     }
266 
267     /**
268      * Proxy method for {@link java.security.Signature#update(byte)}
269      * which is executed on the internal {@link java.security.Signature} object.
270      *
271      * @param input
272      * @throws XMLSignatureException
273      */
274     protected void engineUpdate(byte input) throws XMLSignatureException {
275         try {
276             this.macAlgorithm.update(input);
277         } catch (IllegalStateException ex) {
278             throw new XMLSignatureException("empty", ex);
279         }
280     }
281 
282     /**
283      * Proxy method for {@link java.security.Signature#update(byte[], int, int)}
284      * which is executed on the internal {@link java.security.Signature} object.
285      *
286      * @param buf
287      * @param offset
288      * @param len
289      * @throws XMLSignatureException
290      */
291     protected void engineUpdate(byte buf[], int offset, int len) throws XMLSignatureException {
292         try {
293             this.macAlgorithm.update(buf, offset, len);
294         } catch (IllegalStateException ex) {
295             throw new XMLSignatureException("empty", ex);
296         }
297     }
298 
299     /**
300      * Method engineGetJCEAlgorithmString
301      * @inheritDoc
302      *
303      */
304     protected String engineGetJCEAlgorithmString() {
305         return this.macAlgorithm.getAlgorithm();
306     }
307 
308     /**
309      * Method engineGetJCEAlgorithmString
310      *
311      * @inheritDoc
312      */
313     protected String engineGetJCEProviderName() {
314         return this.macAlgorithm.getProvider().getName();
315     }
316 
317     /**
318      * Method engineSetHMACOutputLength
319      *
320      * @param HMACOutputLength
321      */
322     protected void engineSetHMACOutputLength(int HMACOutputLength) {
323         this.HMACOutputLength = HMACOutputLength;
324         this.HMACOutputLengthSet = true;
325     }
326 
327     /**
328      * Method engineGetContextFromElement
329      *
330      * @param element
331      */
332     protected void engineGetContextFromElement(Element element) {
333         super.engineGetContextFromElement(element);
334 
335         if (element == null) {
336             throw new IllegalArgumentException("element null");
337         }
338 
339         Text hmaclength =
340             XMLUtils.selectDsNodeText(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0);
341 
342         if (hmaclength != null) {
343             this.HMACOutputLength = Integer.parseInt(hmaclength.getData());
344             this.HMACOutputLengthSet = true;
345         }
346     }
347 
348     /**
349      * Method engineAddContextToElement
350      *
351      * @param element
352      */
353     public void engineAddContextToElement(Element element) {
354         if (element == null) {
355             throw new IllegalArgumentException("null element");
356         }
357 
358         if (this.HMACOutputLengthSet) {
359             Document doc = element.getOwnerDocument();
360             Element HMElem =
361                 XMLUtils.createElementInSignatureSpace(doc, Constants._TAG_HMACOUTPUTLENGTH);
362             Text HMText =
363                 doc.createTextNode(Integer.valueOf(this.HMACOutputLength).toString());
364 
365             HMElem.appendChild(HMText);
366             XMLUtils.addReturnToElement(element);
367             element.appendChild(HMElem);
368             XMLUtils.addReturnToElement(element);
369         }
370     }
371 
372     /**
373      * Class IntegrityHmacSHA1
374      */
375     public static class IntegrityHmacSHA1 extends IntegrityHmac {
376 
377         /**
378          * Constructor IntegrityHmacSHA1
379          *
380          * @throws XMLSignatureException
381          */
382         public IntegrityHmacSHA1() throws XMLSignatureException {
383             super();
384         }
385 
386         /**
387          * Method engineGetURI
388          * @inheritDoc
389          *
390          */
391         public String engineGetURI() {
392             return XMLSignature.ALGO_ID_MAC_HMAC_SHA1;
393         }
394 
395         int getDigestLength() {
396             return 160;
397         }
398     }
399 
400     /**
401      * Class IntegrityHmacSHA256
402      */
403     public static class IntegrityHmacSHA256 extends IntegrityHmac {
404 
405         /**
406          * Constructor IntegrityHmacSHA256
407          *
408          * @throws XMLSignatureException
409          */
410         public IntegrityHmacSHA256() throws XMLSignatureException {
411             super();
412         }
413 
414         /**
415          * Method engineGetURI
416          *
417          * @inheritDoc
418          */
419         public String engineGetURI() {
420             return XMLSignature.ALGO_ID_MAC_HMAC_SHA256;
421         }
422 
423         int getDigestLength() {
424             return 256;
425         }
426     }
427 
428     /**
429      * Class IntegrityHmacSHA384
430      */
431     public static class IntegrityHmacSHA384 extends IntegrityHmac {
432 
433         /**
434          * Constructor IntegrityHmacSHA384
435          *
436          * @throws XMLSignatureException
437          */
438         public IntegrityHmacSHA384() throws XMLSignatureException {
439             super();
440         }
441 
442         /**
443          * Method engineGetURI
444          * @inheritDoc
445          *
446          */
447         public String engineGetURI() {
448             return XMLSignature.ALGO_ID_MAC_HMAC_SHA384;
449         }
450 
451         int getDigestLength() {
452             return 384;
453         }
454     }
455 
456     /**
457      * Class IntegrityHmacSHA512
458      */
459     public static class IntegrityHmacSHA512 extends IntegrityHmac {
460 
461         /**
462          * Constructor IntegrityHmacSHA512
463          *
464          * @throws XMLSignatureException
465          */
466         public IntegrityHmacSHA512() throws XMLSignatureException {
467             super();
468         }
469 
470         /**
471          * Method engineGetURI
472          * @inheritDoc
473          *
474          */
475         public String engineGetURI() {
476             return XMLSignature.ALGO_ID_MAC_HMAC_SHA512;
477         }
478 
479         int getDigestLength() {
480             return 512;
481         }
482     }
483 
484     /**
485      * Class IntegrityHmacRIPEMD160
486      */
487     public static class IntegrityHmacRIPEMD160 extends IntegrityHmac {
488 
489         /**
490          * Constructor IntegrityHmacRIPEMD160
491          *
492          * @throws XMLSignatureException
493          */
494         public IntegrityHmacRIPEMD160() throws XMLSignatureException {
495             super();
496         }
497 
498         /**
499          * Method engineGetURI
500          *
501          * @inheritDoc
502          */
503         public String engineGetURI() {
504             return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
505         }
506 
507         int getDigestLength() {
508             return 160;
509         }
510     }
511 
512     /**
513      * Class IntegrityHmacMD5
514      */
515     public static class IntegrityHmacMD5 extends IntegrityHmac {
516 
517         /**
518          * Constructor IntegrityHmacMD5
519          *
520          * @throws XMLSignatureException
521          */
522         public IntegrityHmacMD5() throws XMLSignatureException {
523             super();
524         }
525 
526         /**
527          * Method engineGetURI
528          *
529          * @inheritDoc
530          */
531         public String engineGetURI() {
532             return XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5;
533         }
534 
535         int getDigestLength() {
536             return 128;
537         }
538     }
539 }