From cdeedf52ff5d545fa4d7a1061224e075a3aad1a1 Mon Sep 17 00:00:00 2001 From: Pramod Raghavendra Jayathirth Date: Wed, 3 Oct 2018 11:03:02 -0700 Subject: Adding multithreading support to the application change "thread_count" variable in the CaSignMultThread.java file to control the number of threads created Change-Id: I2296c01d476a7cf18e7fa221d5dd74044cd87293 Issue-ID: AAF-471 Signed-off-by: Pramod Raghavendra Jayathirth --- bin/caservicecontainer/CaSignMultiThread.java | 308 +++++++++++++++++++++++ bin/caservicecontainer/README | 14 +- bin/caservicecontainer/dockerfile | 9 + bin/caservicecontainer/gencsr.sh | 4 + bin/caservicecontainer/multithreadapplication.sh | 28 +++ bin/caservicecontainer/multithreadimport.sh | 93 +++++++ 6 files changed, 454 insertions(+), 2 deletions(-) create mode 100755 bin/caservicecontainer/CaSignMultiThread.java create mode 100755 bin/caservicecontainer/gencsr.sh create mode 100755 bin/caservicecontainer/multithreadapplication.sh create mode 100755 bin/caservicecontainer/multithreadimport.sh diff --git a/bin/caservicecontainer/CaSignMultiThread.java b/bin/caservicecontainer/CaSignMultiThread.java new file mode 100755 index 0000000..93be446 --- /dev/null +++ b/bin/caservicecontainer/CaSignMultiThread.java @@ -0,0 +1,308 @@ +/* + * Copyright 2018 Intel Corporation, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.security.*; +import sun.security.pkcs11.*; +import javax.crypto.spec.SecretKeySpec; +import java.util.*; +import sun.security.pkcs11.*; +import java.security.interfaces.*; +import javax.net.ssl.*; +import javax.crypto.spec.*; +import java.io.*; +import java.security.cert.*; +import java.security.spec.*; +import sun.security.x509.*; +import java.security.KeyStore.PrivateKeyEntry; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyManagementException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.SignatureException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Random; + +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.KeyPurposeId; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.CertIOException; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.bc.BcX509ExtensionUtils; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.util.io.pem.PemReader; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.asn1.pkcs.CertificationRequest; +import org.bouncycastle.asn1.x509.ExtendedKeyUsage; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; + +import javax.xml.bind.DatatypeConverter; +import java.security.cert.X509Certificate; +import java.io.StringWriter; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import static java.nio.file.StandardCopyOption.*; + +class ThreadDemo extends Thread { + private String threadName; + private PrivateKey key; + private X509Certificate caCert; + + ThreadDemo( String name, PrivateKey privateKey, X509Certificate cacert) { + threadName = name; + key = privateKey; + caCert = cacert; + } + + public static final KeyPurposeId[] ASN_WebUsage = new KeyPurposeId[] { + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth}; + + public void run() { + + System.out.println("Running " + threadName); + try { + String threadname = threadName+".csr"; + System.out.println(threadName); + File csrf = new File(threadname); + Reader pemcsr = new FileReader(csrf); + PemReader reader = new PemReader(pemcsr); + PemObject pem = reader.readPemObject(); + PKCS10CertificationRequest csr = new PKCS10CertificationRequest(pem.getContent()); + + X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE); + x500NameBld.addRDN(BCStyle.C, "US"); + x500NameBld.addRDN(BCStyle.ST, "CA"); + x500NameBld.addRDN(BCStyle.L, "local"); + x500NameBld.addRDN(BCStyle.O, "onap"); + x500NameBld.addRDN(BCStyle.CN, "test.onap.ca"); + X500Name issuer = x500NameBld.build(); + + GregorianCalendar gc = new GregorianCalendar(); + Date start = gc.getTime(); + gc.add(GregorianCalendar.DAY_OF_MONTH, 1000); + Date end = gc.getTime(); + + X509Certificate x509; + byte[] serialish = new byte[24]; + SecureRandom random = new SecureRandom(); + BigInteger bi; + bi = new BigInteger(serialish); + X509v3CertificateBuilder xcb = new X509v3CertificateBuilder(issuer, bi, + start, end, csr.getSubject(), csr.getSubjectPublicKeyInfo()); + + JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); + xcb.addExtension(Extension.basicConstraints, + false, new BasicConstraints(false)) + .addExtension(Extension.keyUsage, + true, new KeyUsage(KeyUsage.digitalSignature + | KeyUsage.keyEncipherment)) + .addExtension(Extension.extendedKeyUsage, + true, new ExtendedKeyUsage(ASN_WebUsage)) + + .addExtension(Extension.authorityKeyIdentifier, + false, extUtils.createAuthorityKeyIdentifier(caCert)) + .addExtension(Extension.subjectKeyIdentifier, + false, extUtils.createSubjectKeyIdentifier(caCert.getPublicKey())); + + ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSA").build(key); + + x509 = new JcaX509CertificateConverter().getCertificate(xcb.build(sigGen)); + StringWriter sw = new StringWriter(); + sw.write("-----BEGIN CERTIFICATE-----\n"); + sw.write(DatatypeConverter.printBase64Binary(x509.getEncoded()).replaceAll("(.{64})", "$1\n")); + sw.write("\n-----END CERTIFICATE-----\n"); + FileWriter fw = new FileWriter(threadName +".cert"); + fw.write(sw.toString()); + fw.close(); + + System.out.println("Done - Signed certificate is "+ threadName +".cert"); + System.out.println("Thread: " + threadName); + } + catch (Exception e) { + System.out.println("Thread " + threadName + " interrupted."); + e.printStackTrace(); + System.exit(-1); + } + System.out.println("Thread " + threadName + " exiting." + " upon Successful completion"); + } +} + +public class CaSignMultiThread { + + public static void main(String[] args) throws Exception { + + if ( args.length < 2 ) + System.out.println("Arguments mismatch, Usage: CaSign "); + for(int i = 0; i < args.length; i++) { + System.out.println(args[i]); + } + // Set up the Sun PKCS 11 provider + String configName = "pkcs11.cfg"; + Provider p = new SunPKCS11(configName); + //Provider p = Security.getProvider("SunPKCS11-pkcs11Test"); + if (p==null) { + throw new RuntimeException("could not get security provider for"); + } + Security.addProvider(p); + // Load the key store + char[] pin = args[0].toCharArray(); + KeyStore keyStore = KeyStore.getInstance("PKCS11", p); + keyStore.load(null, pin); + + Enumeration aliases = keyStore.aliases(); + while(aliases.hasMoreElements()){ + String alias = aliases.nextElement(); + System.out.println(alias + ": " + keyStore.getKey(alias,args[0].toCharArray())); + } + PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry(args[1], null); + PrivateKey privateKey = privateKeyEntry.getPrivateKey(); + + X509Certificate caCert = (X509Certificate) privateKeyEntry.getCertificate(); + RSAPublicKey publicKey = (RSAPublicKey) caCert.getPublicKey(); + + Security.addProvider(new BouncyCastleProvider()); + + // Set the number of thread that application need to create + int threadCount = 9; + ThreadDemo[] T = new ThreadDemo[threadCount]; + + for (int i = 0; i -f dockerfile . +$ docker build -t -f dockerfile . ```` ### Running the CA service container - Below command will run and log you into the container ```` -$ docker run -v /tmp/run/dbus:/var/run/dbus:rw -v /tmp/volume:/tmp/files:rw --name -i -t --entrypoint=/bin/bash +$ docker run -d -e DATA_FOLDER= -v /tmp/run/dbus:/var/run/dbus:rw -v /tmp/volume:/tmp/files:rw --name -i -t --entrypoint=/bin/bash +```` + +### Login to the container +```` +$ docker exec -it /bin/bash ```` ### Running the Import utility ```` $ import.sh ```` + +### Running the Import utility with stress test with multithreading +```` +$ ./testca/test/multithreadimport.sh +```` #### Make sure the TABRMD container is running on the same dbus mountpoint on the host as the CA service container ### Expected Input files for SoftHSM operations diff --git a/bin/caservicecontainer/dockerfile b/bin/caservicecontainer/dockerfile index 9fdbc30..89f7fef 100755 --- a/bin/caservicecontainer/dockerfile +++ b/bin/caservicecontainer/dockerfile @@ -15,9 +15,18 @@ RUN cp ./bctls-jdk15on-159.jar /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext # Create the directory for running things in this container RUN mkdir -p /testca/bin +RUN mkdir -p /testca/tests/multithread COPY import.sh /testca/bin COPY softhsmconfig.sh /testca/bin COPY application.sh /testca/bin COPY CaSign.java /testca/bin COPY test.csr /testca/bin + +# Files for Stress testing operations +COPY multithreadapplication.sh /testca/tests/multithread +COPY softhsmconfig.sh /testca/tests/multithread +COPY CaSignMultiThread.java /testca/tests/multithread +COPY multithreadapplication.sh /testca/tests/multithread +COPY multithreadimport.sh /testca/tests/multithread +COPY gencsr.sh /testca/tests/multithread diff --git a/bin/caservicecontainer/gencsr.sh b/bin/caservicecontainer/gencsr.sh new file mode 100755 index 0000000..0e09f7b --- /dev/null +++ b/bin/caservicecontainer/gencsr.sh @@ -0,0 +1,4 @@ +#!/bin/bash +thread_count=$1 +openssl req -nodes -sha1 -newkey rsa:2048 -keyout Thread$thread_count.key -out Thread$thread_count.csr -days 365 -subj "/C=US/ST=CA/L=SantaClara/O=ONAP/CN=" +chmod +x * diff --git a/bin/caservicecontainer/multithreadapplication.sh b/bin/caservicecontainer/multithreadapplication.sh new file mode 100755 index 0000000..3b3c5de --- /dev/null +++ b/bin/caservicecontainer/multithreadapplication.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# This script takes 4 arguments +key_label=$1 +SoftHSMv2SlotID=$2 +upin=$3 +cert_id=$4 + +# Location to fecth SoftHSM library required by application +applicationlibrary="/usr/local/lib/softhsm/libsofthsm2.so" + +# Setting up the java application and running the application +# 1. Create the configuration pkcs11.cfg for the application +# Remove any existing cfg file first from the CWD +rm -f pkcs11.cfg +touch pkcs11.cfg +chmod 755 pkcs11.cfg +echo "name = ${key_label}" >> pkcs11.cfg +echo "The location of applicationms library is ${applicationlibrary}" +echo "library = ${applicationlibrary}" >> pkcs11.cfg +echo "slot = ${SoftHSMv2SlotID}" >> pkcs11.cfg + +# 2. Compile the Application +# CaSign requires test.csr to be available in CWD +javac CaSignMultiThread.java + +# 3. Run the Application +java CaSignMultiThread ${upin} 0x${cert_id} diff --git a/bin/caservicecontainer/multithreadimport.sh b/bin/caservicecontainer/multithreadimport.sh new file mode 100755 index 0000000..9b092ff --- /dev/null +++ b/bin/caservicecontainer/multithreadimport.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# NOTE - This scripts expects the Init and the Duplicate tools to be already +# run and the output files(listed in README) to be present at the +# shared volume (input for Import tool) +# It also requires the following ENVIRONMENT variables to be set +# SECRETS_FOLDER - containing the srk_handl and prk_passwd files in base64 +# DATA_FOLDER - containing the files that are produced from the distcenter + +set -e + +#Primary Key Password used by TPM Plugin to load keys +export TPM_PRK_PASSWORD="$(cat ${SECRETS_FOLDER}/prk_passwd | base64 -d)" +#Handle to the aforementioned Primary Key +SRK_HANDLE="$(cat ${SECRETS_FOLDER}/srk_handle | base64 -d)" +#key_id is the parameter expected by SoftHSM +key_id="8738" +#Key_label is the parameter expected by SoftHSM +key_label="ABC" +#UserPin for the SoftHSM operations +upin="123456789" +#SoPin for the SoftHSM operations +sopin="123456789" +#Slot number for the SoftHSM operations. Initially it should be started with 0 +slot_no="0" +#Name for creating the slot used by SoftHSM +token_no="Token1" +#cert_id is the input for the application which is hexadecimal equivalent of key_id +cert_id=$(printf '%x' ${key_id}) +#Set working dir +WORKDIR=$PWD +#Process count for the Stress test +count="15" + +# 1.Initialize the token/ + softhsm2-util --init-token --slot ${slot_no} --label "${token_name}" \ + --pin ${upin} --so-pin ${sopin} + softhsm2-util --show-slots | grep 'Slot ' | cut -d\ -f2 | head -1 >> slotinfo.txt + SoftHSMv2SlotID="$(cat slotinfo.txt)" + echo "The slot ID used is ${SoftHSMv2SlotID}" + +# 2.Plugin directory for the SoftHSM to load plugin and for further operations +if [ -f ${DATA_FOLDER}/out_parent_public ]; then + + # 2.a Copy the required input files for the Import tool + cp ${DATA_FOLDER}/dup* /tpm-util/bin/ + + # 2.b Run the Import Utility + cd /tpm-util/bin + ./ossl_tpm_import -H $SRK_HANDLE -dupPub dupPub -dupPriv dupPriv \ + -dupSymSeed dupSymseed -dupEncKey dupEncKey -pub outPub -priv outPriv \ + -password $TPM_PRK_PASSWORD + + cd $WORKDIR + ./softhsmconfig.sh $SRK_HANDLE $key_id $key_label $upin $sopin $SoftHSMv2SlotID +else + +# 3 SoftHSM mode implementation + + echo "TPM hardware unavailable. Using SoftHSM implementation" + + cd ${DATA_FOLDER} + + # 3.a Extract the Private key using passphrase + cat passphrase | gpg --batch --yes --passphrase-fd 0 privkey.pem.gpg + + # 3.b Convert the Private key pem into der format + openssl rsa -in ./privkey.pem -outform DER -out privatekey.der + + # 3.c Load the Private key into SoftHSM + pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -l --pin ${upin} \ + --write-object ./privatekey.der --type privkey --id ${cert_id} --label ${key_label} + +fi + +# 3.a Application operation +cd ${DATA_FOLDER} + +# 3.b Convert the crt to der format +openssl x509 -in ca.cert -outform der -out ca.der +cp ca.cert /testca/tests/multithread/ + +# 3.c Add the ca certificate +pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -l --pin ${upin} \ +--write-object ./ca.der --type cert --id ${cert_id} + +# 4. Calling the functionalities of the sample application +cd $WORKDIR +./multithreadapplication.sh $key_label $SoftHSMv2SlotID $upin $cert_id + +# 5. Cleanup +cd $WORKDIR +rm -rf slotinfo.txt -- cgit 1.2.3-korg