001    // Copyright (C) 2002 IAIK
002    // https://jce.iaik.tugraz.at
003    //
004    // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005    //                           Communication Technologies SIC
006    // https://sic.tech
007    //
008    // All rights reserved.
009    //
010    // Redistribution and use in source and binary forms, with or without
011    // modification, are permitted provided that the following conditions
012    // are met:
013    // 1. Redistributions of source code must retain the above copyright
014    //    notice, this list of conditions and the following disclaimer.
015    // 2. Redistributions in binary form must reproduce the above copyright
016    //    notice, this list of conditions and the following disclaimer in the
017    //    documentation and/or other materials provided with the distribution.
018    //
019    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029    // SUCH DAMAGE.
030    
031    // Copyright (C) 2002 IAIK
032    // https://sic.tech/
033    //
034    // Copyright (C) 2003 - 2025 Stiftung Secure Information and 
035    //                           Communication Technologies SIC
036    // https://sic.tech/
037    //
038    // All rights reserved.
039    //
040    // This source is provided for inspection purposes and recompilation only,
041    // unless specified differently in a contract with IAIK. This source has to
042    // be kept in strict confidence and must not be disclosed to any third party
043    // under any circumstances. Redistribution in source and binary forms, with
044    // or without modification, are <not> permitted in any case!
045    //
046    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056    // SUCH DAMAGE.
057    //
058    // $Header: /IAIK-CMS/current/src/demo/smime/ess/SecurityLabelDemo.java 17    12.02.25 17:59 Dbratko $
059    // $Revision: 17 $
060    //
061    
062    package demo.smime.ess;
063    
064    import iaik.asn1.structures.AlgorithmID;
065    import iaik.asn1.structures.Attribute;
066    import iaik.cms.Utils;
067    import iaik.smime.SMimeSignerInfo;
068    import iaik.smime.SignedContent;
069    import iaik.smime.ess.ESSSecurityLabel;
070    import iaik.smime.ess.SecurityLabelException;
071    import iaik.x509.X509Certificate;
072    
073    import java.io.ByteArrayInputStream;
074    import java.io.ByteArrayOutputStream;
075    import java.io.IOException;
076    import java.io.InputStream;
077    import java.security.PrivateKey;
078    import java.security.SignatureException;
079    import java.util.Date;
080    
081    import javax.mail.Message;
082    import javax.mail.MessagingException;
083    import javax.mail.Session;
084    import javax.mail.internet.InternetAddress;
085    import javax.mail.internet.MimeMessage;
086    
087    import demo.DemoSMimeUtil;
088    import demo.DemoUtil;
089    import demo.keystore.CMSKeyStore;
090    
091    /**
092     * Demonstrates the usage of the S/MIME-ESS SecurityLabel attribute.
093     * The {@link iaik.smime.ess.ESSSecurityLabel SecurityLabel} attribute may be 
094     * included as signed attribute in a {@link iaik.cms.SignerInfo SignerInfo} for
095     * providing some kind of "access control" mechanism for the contents of a message.
096     * <p> 
097     * This demo uses a simple {@link demo.smime.ess.MySecurityLabelHandler 
098     * SecurityLabelHandler} that only implements a simple security policy based on
099     * the default security classifications "unmarked", "unclassified", "restricted", 
100     * "confidential", "secret", "top-secret". Since the SignedData message created
101     * by this demo only contains an ESS {@link iaik.smime.ess.ESSSecurityLabel 
102     * SecurityLabel} attribute with classification "confidential", only this 
103     * classification is processed by the {@link demo.smime.ess.MySecurityLabelHandler 
104     * demo handler}. "unmarked" and "unclassified" are handled as "not critical"
105     * content (i.e. the content can be accessed by any one), "secret", "top-secret"
106     * lock the content (i.e. it is not displayed), and "restricted" and 
107     * "confidential" popup a confirmation dialog reminding the recipient about
108     * the confidentiality of the message content.
109     * <p>
110     * To run this demo the following packages are required:
111     * <ul>
112     *    <li>
113     *       <code>iaik_cms.jar</code>
114     *    </li>
115     *    <li>
116     *       <code>iaik_jce(_full).jar</code> (<a href="https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">IAIK-JCE Core Crypto Library</a>).
117     *    </li>
118     *    <li>
119     *       <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>).
120     *    </li>   
121     *    <li>
122     *       <code>activation.jar</code> (<a href="http://www.oracle.com/technetwork/java/javase/downloads/index-135046.html" target="_blank">Java Activation Framework</a>; required for JDK versions &lt; 1.6).
123     *    </li> 
124     * </ul>
125     *  
126     * @see demo.smime.ess.MySecurityLabelHandler
127     * @see iaik.smime.ess.ESSSecurityLabel
128     */
129    public class SecurityLabelDemo {
130        
131      // whether to print dump all generates test messages to System.out
132      final static boolean PRINT_MESSAGES = false;   
133    
134      String firstName = "John";
135      String lastName = "SMime";
136      String to = "smimetest@iaik.at";               // email recipient
137      String from = "smimetest@iaik.at";             // email sender
138      String host = "mailhost";                      // name of the mailhost
139    
140      X509Certificate[] signerCertificates;          // list of certificates to include in the S/MIME message
141      X509Certificate signerCertificate;             // certificate of the signer/sender
142      PrivateKey signerPrivateKey;                   // private key of the signer/sender
143      X509Certificate encryptionCertOfSigner;        // signer uses different certificate for encryption
144      
145      
146      /**
147       * Default constructor. Reads certificates and keys from the demo keystore.
148       */
149      public SecurityLabelDemo() {
150        
151        System.out.println();
152        System.out.println("******************************************************************************************");
153        System.out.println("*                               SecurityLabelDemo demo                                   *");
154        System.out.println("*                  (shows how to handle the ESS SecurityLabel attribute)                 *");
155        System.out.println("******************************************************************************************");
156        System.out.println();
157        
158        // get the certificates from the KeyStore
159        signerCertificates = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
160        signerPrivateKey = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
161        signerCertificate = signerCertificates[0];
162        encryptionCertOfSigner = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0];
163      }
164      
165      /**
166       * Starts the demo.
167       *
168       * @throws IOException if an I/O related error occurs
169       */
170      public void start() throws IOException {
171    
172            // get the default Session
173            Session session = DemoSMimeUtil.getSession();
174    
175            try {
176          Message msg;    // the message to send
177          ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream
178          ByteArrayInputStream bais;  // we read from a stream
179    
180          msg = createSignedMessage(session);
181          System.out.println("creating implicitly signed message...");
182              baos.reset();
183          // send, write
184              msg.saveChanges();
185              msg.writeTo(baos);
186          
187          // receive, parse
188              bais = new ByteArrayInputStream(baos.toByteArray());
189              msg = new MimeMessage(session, bais);
190              if (PRINT_MESSAGES) {
191            printMessage(msg);
192          }
193              parseMessage(msg);
194    
195        } catch (Exception ex) {
196              ex.printStackTrace();
197              throw new RuntimeException(ex.toString());
198            } 
199      }
200      
201      /**
202       * Creates a MIME message container with the given subject for the given session.
203       * 
204       * @param session the mail sesion
205       * @param subject the subject of the message
206       *
207       * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content)
208       *
209       * @throws MessagingException if the message cannot be created
210       */
211      public Message createMessage(Session session, String subject) throws MessagingException {
212        MimeMessage msg = new MimeMessage(session);
213        msg.setFrom(new InternetAddress(from));
214              msg.setRecipients(Message.RecipientType.TO,   InternetAddress.parse(to, false));
215              msg.setSentDate(new Date());
216        msg.setSubject(subject);
217        return msg;
218      }
219      
220      /**
221       * Creates a signed message containing an ESS SecurityLabel attribute.
222       *
223       * @param session the mail session
224       * @return the signed message
225       *
226       * @throws Exception if an error occurs when creating the message
227       */
228      public Message createSignedMessage(Session session) throws Exception {
229    
230        String subject = "IAIK-S/MIME: SecurityLabelDemo (Explicitly Signed)";
231        StringBuffer buf = new StringBuffer();
232        buf.append("This is an explicitly signed message\n");
233        buf.append("containing an ESSSecurityLabel attribute.\n");
234           
235        Message msg = createMessage(session, subject);
236    
237        SignedContent sc = new SignedContent(true);
238        // set the content
239        sc.setText(buf.toString());
240        
241        // set the signer certificates
242        sc.setCertificates(signerCertificates);
243        // set SignerInfo
244        SMimeSignerInfo signerInfo = new SMimeSignerInfo(signerCertificate, 
245                                                         (AlgorithmID)AlgorithmID.sha256.clone(),
246                                                         (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 
247                                                         signerPrivateKey, 
248                                                         encryptionCertOfSigner,
249                                                         true);
250        
251        // add SecurityLabel attribute
252        ESSSecurityLabel securityLabel = new ESSSecurityLabel(MySecurityLabelHandler.MY_SECURITY_POLICY_ID);
253        securityLabel.setSecurityClassification(ESSSecurityLabel.CONFIDENTIAL);
254        securityLabel.setPrivacyMarkString("HIGH CONFIDENTIAL DATA MATERIAL! RESTRICTED USER ACCESS");
255        signerInfo.addSignedAttribute(new Attribute(securityLabel));
256        sc.addSigner(signerInfo);
257        msg.setContent(sc, sc.getContentType());
258        // let the SignedContent update some message headers
259        sc.setHeaders(msg);
260        return msg;
261      }
262      
263      /**
264       * Parses the signed message, verifies the signature and processes the SecurityLabel
265       * attribute.
266       * 
267       * @param msg the message to be parsed
268       * 
269       * @throws IOException if an I/O related problem occurs
270       * @throws MessagingException if there is a problem with the message format
271       * @throws SignatureException if the signature verification failes
272       */
273      public void parseMessage(Message msg) throws IOException, MessagingException, SignatureException {
274        // we know that we have a signed message
275        SignedContent sc = (SignedContent)msg.getContent();
276        // set a SecurityLabelHandler
277        sc.setSecurityLabelHandler(new MySecurityLabelHandler());
278        // verify signature
279        X509Certificate signer = null;
280        try {
281          signer = sc.verify();
282              System.out.println("This message is signed from: "+signer.getSubjectDN());
283            } catch (SignatureException ex) {
284              throw new SignatureException("Signature verification error: " + ex.toString());
285        }
286        // try to access the content data
287        try {
288          Object content = sc.getContent();
289          System.out.println("Included content:");
290          // depending on JavaMail API version we may have a String or a InputStream
291          if (content instanceof String) {
292            System.out.println(content);
293          } else if (content instanceof InputStream) {
294            ByteArrayOutputStream baos = new ByteArrayOutputStream();
295            Utils.copyStream((InputStream)content, baos, null);
296            System.out.println(new String(baos.toByteArray()));
297          }  
298        } catch (SecurityLabelException ex) {
299          System.out.println(ex.getMessage());   
300        }    
301      }  
302      
303     
304      /** 
305       * Prints a dump of the given message to System.out.
306       *
307       * @param msg the message to be dumped to System.out
308       */
309      private static void printMessage(Message msg) throws IOException {
310        System.out.println("------------------------------------------------------------------");
311        System.out.println("Message dump: \n");
312        try {
313          msg.writeTo(System.out);
314        } catch (MessagingException ex) {
315          throw new IOException(ex.getMessage());   
316        }    
317        System.out.println("\n------------------------------------------------------------------");
318      }  
319    
320    
321      /**
322       * The main method.
323       */
324      public static void main(String[] argv) throws IOException {
325    
326        DemoSMimeUtil.initDemos();
327            try {
328              (new SecurityLabelDemo()).start();
329            } catch (Exception ex) {
330              ex.printStackTrace();  
331            }    
332    
333        System.out.println("\nReady!");
334        DemoUtil.waitKey();
335     
336      }
337    }