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 }