001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package  org.jpos.security.jceadapter;
020
021import org.jpos.core.ConfigurationException;
022import org.jpos.core.SimpleConfiguration;
023import org.jpos.iso.ISOUtil;
024import org.jpos.security.SMException;
025import org.jpos.security.SecureDESKey;
026import org.jpos.util.Logger;
027import org.jpos.util.SimpleLogListener;
028
029import java.io.PrintStream;
030import java.util.Properties;
031
032/**
033 * A simple application for sending critical commands to the JCE Security Module.
034 * The functionalities available from this console, are not available programmatically (via API's),
035 * for security reasons, because most of them involve clear (non encrypted) keys.
036 * Those commands are package protected in the JCE Security Module.
037 * @author Hani Samuel Kirollos
038 * @version $Revision$ $Date$
039 */
040/** Simple command-line console for testing the JCE security module. */
041public class Console {
042
043    /** Default constructor. */
044    public Console () {
045    }
046
047    /**
048     * Entry point for the JCE security console.
049     * @param args command-line arguments passed to {@link #exec}
050     */
051    public static void main (String[] args) {
052        new Console().exec(System.out,System.err,args);
053    }
054
055    /**
056     * Runs the JCE security module console with the given I/O streams.
057     * @param outPS output stream
058     * @param errPS error stream
059     * @param args command-line arguments
060     */
061    public void exec(PrintStream outPS,PrintStream errPS,String[] args)
062    {
063        JCESecurityModule sm = new JCESecurityModule();
064        Logger logger = new Logger();
065        logger.addListener(new SimpleLogListener(outPS));
066        sm.setLogger(logger, "jce-security-module");
067        Properties cfgProps = new Properties();
068        SimpleConfiguration cfg = new SimpleConfiguration(cfgProps);
069        String commandName = null;
070        String[] commandParams = new String[10];                 // 10 is Maximum number of paramters for a command
071        outPS.println("Welcome to JCE Security Module console commander!");
072        if (args.length == 0) {
073            outPS.println("Usage: Console [-options] command [commandparameters...]");
074            outPS.println("\nwhere options include:");
075            outPS.println("    -lmk <filename>");
076            outPS.println("                  to specify the Local Master Keys file");
077            outPS.println("    -rebuildlmk   to rebuild new Local Master Keys");
078            outPS.println("                  WARNING: old Local Master Keys gets overwritten");
079            outPS.println("    -jce <provider classname>");
080            outPS.println("                  to specify a JavaTM Cryptography Extension 1.2.1 provider");
081            outPS.println("\nWhere command include: ");
082            outPS.println("    GC <keyLength>");
083            outPS.println("                  to generate a clear key component.");
084            outPS.println("    FK <keyLength> <keyType> <component1> <component2> <component3>");
085            outPS.println("                  to form a key from three clear components.");
086            outPS.println("                  and returns the key encrypted under LMK");
087            outPS.println("                  Odd parity is be forced before encryption under LMK");
088            outPS.println("    CK <keyLength> <keyType> <KEYunderLMK>");
089            outPS.println("                  to generate a key check value for a key encrypted under LMK.");
090            outPS.println("    IK <keyLength> <keyType> <KEYunderKEK> ");
091            outPS.println("       <kekLength> <kekType> <KEKunderLMK> <KEKcheckValue>");
092            outPS.println("                  to import a key from encryption under KEK (eg. ZMK,TMK) to encryption under LMK");
093            outPS.println("                  Odd parity is be forced before encryption under LMK");
094            outPS.println("    KE <keyLength> <keyType> <KEYunderLMK> <KEYcheckValue> ");
095            outPS.println("       <kekLength> <kekType> <KEKunderLMK> <KEKcheckValue> ");
096            outPS.println("                  to translate (export) a key from encryption under LMK");
097            outPS.println("                  to encryption under KEK (eg. ZMK,TMK)");
098        }
099        else {
100            int argsCounter = 0;
101            for (int j = 0; j < 10; j++) {
102                if (argsCounter < args.length &&
103                        args[argsCounter].toLowerCase().compareTo("-lmk") == 0
104                ) {
105                    argsCounter++;
106                    cfgProps.setProperty("lmk", args[argsCounter++]);
107                }
108                if (argsCounter < args.length &&
109                        args[argsCounter].toLowerCase().compareTo("-jce") == 0
110                ) {
111                    argsCounter++;
112                    cfgProps.setProperty("provider", args[argsCounter++]);
113                }
114                if (argsCounter < args.length &&
115                        args[argsCounter].toLowerCase().compareTo("-rebuildlmk") == 0
116                ) {
117                    argsCounter++;
118                    cfgProps.setProperty("rebuildlmk", "true");
119                }
120            }
121            if (argsCounter < args.length) {
122                commandName = args[argsCounter++];
123                int i = 0;
124                while (argsCounter < args.length) {
125                    commandParams[i++] = args[argsCounter++];
126                }
127            }
128            // Configure JCE Security Module
129            try {
130                sm.setConfiguration(cfg);
131            } catch (ConfigurationException e) {
132                e.printStackTrace(errPS);
133                return;
134            }
135            // Execute Command
136            if (commandName != null) {
137                try {
138                    short keyLength = (short)Integer.parseInt(commandParams[0]);
139                    if (commandName.toUpperCase().compareTo("GC") == 0) {
140                        String clearKeyComponenetHexString = sm.generateClearKeyComponent(keyLength);
141                    }
142                    else if (commandName.toUpperCase().compareTo("FK") == 0) {
143                        SecureDESKey KEYunderLMK = sm.formKEYfromThreeClearComponents(keyLength,
144                                commandParams[1].toUpperCase(), commandParams[2], commandParams[3], commandParams[4]);
145                    }
146                    else if (commandName.toUpperCase().compareTo("CK") == 0) {
147                        byte[] keyCheckValue = sm.generateKeyCheckValue(
148                                new SecureDESKey(keyLength,commandParams[1].toUpperCase(), commandParams[2],""));
149                    }
150                    else if (commandName.toUpperCase().compareTo("IK") == 0) {
151                        SecureDESKey KEKunderLMK = new SecureDESKey((short)Integer.parseInt(commandParams[4]),
152                                commandParams[5].toUpperCase(), commandParams[6], commandParams[7]);
153                        sm.importKey(keyLength, commandParams[1].toUpperCase(),
154                                ISOUtil.hex2byte(commandParams[2]), KEKunderLMK, true);
155                    }
156                    else if (commandName.toUpperCase().compareTo("KE") == 0) {
157                        SecureDESKey KEKunderLMK = new SecureDESKey((short)Integer.parseInt(commandParams[4]),
158                                commandParams[5].toUpperCase(), commandParams[6], commandParams[7]);
159                        SecureDESKey KEYunderLMK = new SecureDESKey(keyLength, commandParams[1].toUpperCase(),
160                                commandParams[2], commandParams[3] );
161                        sm.exportKey(KEYunderLMK, KEKunderLMK);
162                    }
163                    else {
164                        System.err.println("Unknown command: " + commandName);
165                    }
166                } catch (SMException e) {
167                    e.printStackTrace(errPS);
168                } catch (java.lang.NumberFormatException e) {
169                    errPS.println("Invalid KeyLength");
170                }
171            }
172            else {
173                errPS.println("No command specified");
174            }
175        }
176    }
177}
178
179
180