1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.security.message;
21  
22  import javax.security.auth.callback.CallbackHandler;
23  
24  import org.apache.ws.security.WSConstants;
25  import org.apache.ws.security.WSDataRef;
26  import org.apache.ws.security.WSSConfig;
27  import org.apache.ws.security.WSSecurityEngine;
28  import org.apache.ws.security.WSSecurityEngineResult;
29  import org.apache.ws.security.common.KeystoreCallbackHandler;
30  import org.apache.ws.security.common.SOAPUtil;
31  import org.apache.ws.security.components.crypto.Crypto;
32  import org.apache.ws.security.components.crypto.CryptoFactory;
33  import org.w3c.dom.Document;
34  
35  /**
36   * A set of test-cases for encrypting and decrypting SOAP requests using GCM. See:
37   * https://issues.apache.org/jira/browse/WSS-325
38   */
39  public class EncryptionGCMTest extends org.junit.Assert {
40      private static final org.apache.commons.logging.Log LOG = 
41          org.apache.commons.logging.LogFactory.getLog(EncryptionGCMTest.class);
42      private static final javax.xml.namespace.QName SOAP_BODY =
43          new javax.xml.namespace.QName(
44              WSConstants.URI_SOAP11_ENV,
45              "Body"
46          );
47  
48      private WSSecurityEngine secEngine = new WSSecurityEngine();
49      private CallbackHandler keystoreCallbackHandler = new KeystoreCallbackHandler();
50      private Crypto crypto = null;
51      
52      public EncryptionGCMTest() throws Exception {
53          crypto = CryptoFactory.getInstance("wss40.properties");
54      }
55      
56      /**
57       * Setup method
58       * 
59       * @throws java.lang.Exception Thrown when there is a problem in setup
60       */
61      @org.junit.Before
62      public void setUp() throws Exception {
63          WSSConfig wssConfig = WSSConfig.getNewInstance();
64          wssConfig.setWsiBSPCompliant(true);
65          secEngine.setWssConfig(wssConfig);
66      }
67      
68      @org.junit.Test
69      public void testAES128GCM() throws Exception {
70          //
71          // This test fails with the IBM JDK 7
72          //
73          if ("IBM Corporation".equals(System.getProperty("java.vendor"))
74              && System.getProperty("java.version") != null
75              &&  System.getProperty("java.version").startsWith("1.7")) {
76              return;
77          }
78          WSSecEncrypt builder = new WSSecEncrypt();
79          builder.setUserInfo("wss40");
80          builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
81          builder.setSymmetricEncAlgorithm(WSConstants.AES_128_GCM);
82          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
83          WSSecHeader secHeader = new WSSecHeader();
84          secHeader.insertSecurityHeader(doc);
85          Document encryptedDoc = builder.build(doc, crypto, secHeader);
86  
87          String outputString = 
88              org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
89          if (LOG.isDebugEnabled()) {
90              LOG.debug("Encrypted message:");
91              LOG.debug(outputString);
92          }
93          assertTrue(outputString.indexOf("counter_port_type") == -1 ? true : false);
94          verify(encryptedDoc, keystoreCallbackHandler, SOAP_BODY);
95      }
96      
97      @org.junit.Test
98      public void testAES256GCM() throws Exception {
99          //
100         // This test fails with the IBM JDK 7
101         //
102         if ("IBM Corporation".equals(System.getProperty("java.vendor"))
103             && System.getProperty("java.version") != null
104             &&  System.getProperty("java.version").startsWith("1.7")) {
105             return;
106         }
107         WSSecEncrypt builder = new WSSecEncrypt();
108         builder.setUserInfo("wss40");
109         builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
110         builder.setSymmetricEncAlgorithm(WSConstants.AES_256_GCM);
111         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
112         WSSecHeader secHeader = new WSSecHeader();
113         secHeader.insertSecurityHeader(doc);
114         Document encryptedDoc = builder.build(doc, crypto, secHeader);
115 
116         String outputString = 
117             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
118         if (LOG.isDebugEnabled()) {
119             LOG.debug("Encrypted message:");
120             LOG.debug(outputString);
121         }
122         assertTrue(outputString.indexOf("counter_port_type") == -1 ? true : false);
123         verify(encryptedDoc, keystoreCallbackHandler, SOAP_BODY);
124     }
125 
126     /**
127      * Verifies the soap envelope
128      * <p/>
129      * 
130      * @param envelope 
131      * @throws Exception Thrown when there is a problem in verification
132      */
133     @SuppressWarnings("unchecked")
134     private void verify(
135         Document doc,
136         CallbackHandler handler,
137         javax.xml.namespace.QName expectedEncryptedElement
138     ) throws Exception {
139         final java.util.List<WSSecurityEngineResult> results = 
140             secEngine.processSecurityHeader(doc, null, handler, null, crypto);
141         String outputString = 
142             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
143         if (LOG.isDebugEnabled()) {
144             LOG.debug(outputString);
145         }
146         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
147         //
148         // walk through the results, and make sure there is an encryption
149         // action, together with a reference to the decrypted element 
150         // (as a QName)
151         //
152         boolean encrypted = false;
153         for (java.util.Iterator<WSSecurityEngineResult> ipos = results.iterator(); 
154             ipos.hasNext();) {
155             final WSSecurityEngineResult result = ipos.next();
156             final Integer action = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
157             assertNotNull(action);
158             if ((action.intValue() & WSConstants.ENCR) != 0) {
159                 final java.util.List<WSDataRef> refs =
160                     (java.util.List<WSDataRef>) result.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
161                 assertNotNull(refs);
162                 encrypted = true;
163                 for (java.util.Iterator<WSDataRef> jpos = refs.iterator(); jpos.hasNext();) {
164                     final WSDataRef ref = jpos.next();
165                     assertNotNull(ref);
166                     assertNotNull(ref.getName());
167                     assertEquals(
168                         expectedEncryptedElement,
169                         ref.getName()
170                     );
171                     assertNotNull(ref.getProtectedElement());
172                     if (LOG.isDebugEnabled()) {
173                         LOG.debug("WSDataRef element: ");
174                         LOG.debug(
175                             org.apache.ws.security.util.DOM2Writer.nodeToString(
176                                 ref.getProtectedElement()
177                             )
178                         );
179                     }
180                 }
181             }
182         }
183         assertTrue(encrypted);
184     }
185 
186 }