Unit test development.
authorAndrii Androsov <a.androsov@samsung.com>
Tue, 20 Sep 2016 09:27:48 +0000 (12:27 +0300)
committerJee Hyeok Kim <jihyeok13.kim@samsung.com>
Tue, 20 Sep 2016 10:15:51 +0000 (10:15 +0000)
1. CSR update(update for new specification)
2. CSR unit test update for new specification.
3. Code refactoring.
4. Update CRL pubdatatype and express RCSN as Arralist of Strings
   as in specification.
5. Fix issues for CRL table, add new unit tests, add docs for
   CertificateConstants, CertificateManager, CertificateStorage.
6. Fix issue with subjectDN and issuerDN for CA certificate and for personal one.
   please remove cloud/account/keystore folder
7. Fix last update CRL issue.
8. Fix issuer name for CRL.
9. Fix issue with basic-constraints. Code refactoring.
10. Fix issue with CRL re-creation after account restart.
11. Fix issue with CRL subject name.
12. Replace Base64 to Der coding for CRL GET. Code refactoring.
13. Put CRL to db as BinaryData and remove CRL file.
14. Add new unit tests for CRL.
15. Add new unit tests for CSR and add documentation.

Change-Id: Iadef163d6cde2ca671b70a0cc05d9a73cbf9b8a3
Signed-off-by: Andrii Androsov <a.androsov@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/10977
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jee Hyeok Kim <jihyeok13.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/11973
Tested-by: Jee Hyeok Kim <jihyeok13.kim@samsung.com>
28 files changed:
cloud/account/README
cloud/account/properties/config.properties [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/CRLTable.java [moved from cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlInfo.java with 53% similarity]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/CertificateTable.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateManager.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateResource.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CSRParser.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateBuilder.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateIssuerConfig.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificatePrivateKeyPair.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/Utility.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlIssuer.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlStore.java [deleted file]
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java [new file with mode: 0644]
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/GenerateCSR.java [new file with mode: 0644]
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/OICConstants.java

index 37d1215..599913b 100644 (file)
@@ -31,3 +31,6 @@ Build and Run
        - Before you run a Accout server, You need to set up following steps.
           1) Install MongoDB
           2) Install Github certificates for github.com and *.github.com.
+5) Please download: file from http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html: Java Cryptography Extension
+         1.Extract files from zip. 
+         2.Place local_policy.jar and US_export_policy.jar files in/usr/lib/jvm/PATH_TO_JDK/jre/lib/security 
diff --git a/cloud/account/properties/config.properties b/cloud/account/properties/config.properties
new file mode 100644 (file)
index 0000000..73d9aaa
--- /dev/null
@@ -0,0 +1,17 @@
+#New Serial number
+#Wed Sep 07 17:08:34 EEST 2016
+keyGeneratorAlgorithm=ECDSA
+notAfterInterval=20
+securityProvider=BC
+ellipticCurve=secp256r1
+keyStoreLocation=keystore{0}certificateStorage.jks
+nextUpdateInterval=1
+signatureAlgorithm=SHA256withECDSA
+keystoreType=BKS
+rootOU=OCF Sub CA
+serialNumber=515
+rootO=Samsung
+caAlias=uuid\:31313131-3131-3131-3131-313131313131
+subjectName=uuid\:31313131-3131-3131-3131-313131313131
+password=PASSWORD
+rootC=KR
index 858e7ed..d7a8164 100644 (file)
@@ -30,7 +30,7 @@ import org.iotivity.cloud.accountserver.resources.account.tokenrefresh.TokenRefr
 import org.iotivity.cloud.accountserver.resources.acl.group.GroupResource;
 import org.iotivity.cloud.accountserver.resources.acl.id.AclResource;
 import org.iotivity.cloud.accountserver.resources.acl.invite.InviteResource;
-import org.iotivity.cloud.accountserver.resources.certificate.CertificateResource;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource;
 import org.iotivity.cloud.base.ServerSystem;
 import org.iotivity.cloud.base.server.CoapServer;
 import org.iotivity.cloud.util.Log;
index 5ddcd8b..1fc6d88 100644 (file)
  */
 package org.iotivity.cloud.accountserver;
 
+import java.io.File;
+
 import org.iotivity.cloud.base.OICConstants;
 
 public class Constants extends OICConstants {
 
+    public static final String PROPERTIES_FILE_NAME  = "properties"
+            + File.separator + "config.properties";
+
     // Database name
 
     public static final String DB_NAME               = "ACCOUNTSERVER_DB";
 
     // Database table
 
+    public static final String CRL_TABLE             = "CRL_TABLE";
+
+    public static final String CERTIFICATE_TABLE     = "CERTIFICATE_TABLE";
+
     public static final String USER_TABLE            = "USER_TABLE";
 
     public static final String TOKEN_TABLE           = "TOKEN_TABLE";
@@ -47,6 +56,14 @@ public class Constants extends OICConstants {
 
     // Database table key
 
+    public static final String KEYFIELD_SN           = "serialNumber";
+
+    public static final String KEYFIELD_NA           = "notAfter";
+
+    public static final String KEYFIELD_NB           = "notBefore";
+
+    public static final String KEYFIELD_REVOKED      = "revoked";
+
     public static final String KEYFIELD_UUID         = "uuid";
 
     public static final String KEYFIELD_ACCESSTOKEN  = "accesstoken";
@@ -143,6 +160,16 @@ public class Constants extends OICConstants {
 
     public static final String REQ_MEMBER            = "mid";
 
+    public static final String REQ_LAST_UPDATE       = "lu";
+
+    public static final String REQ_THIS_UPDATE       = "tu";
+
+    public static final String REQ_NEXT_UPDATE       = "nu";
+
+    public static final String REQ_CRL               = "crl";
+
+    public static final String REQ_SERIAL_NUMBER     = "rcsn";
+
     public static final String REQ_MEMBER_LIST       = "midlist";
 
     public static final String REQ_GTYPE_PRIVATE     = "Private";
@@ -189,8 +216,15 @@ public class Constants extends OICConstants {
 
     public static final String RESP_ACL_ALLOWED      = "Allowed";
 
-    public static final String RESP_ACL_DENIED       = "Denied";
+    public static final String RESP_ACL_DENIED       = "Denied";    
+
+    public static final String ENCODING = "encoding";
+
+    public static final String DATA = "data";
+
+    public static final String CERT = "cert";
 
+    public static final String CERT_CHAIN = "certchain";
     // static token type
 
     public static final String TOKEN_TYPE_BEARER     = "bearer";
index 06f3e62..9d96a9b 100644 (file)
@@ -73,6 +73,8 @@ public class AccountDBManager {
         mongoDB.createTable(Constants.DEVICE_TABLE);
         mongoDB.createTable(Constants.ACL_TABLE);
         mongoDB.createTable(Constants.ACLTEMPLATE_TABLE);
+        mongoDB.createTable(Constants.CERTIFICATE_TABLE);
+        mongoDB.createTable(Constants.CRL_TABLE);
     }
 
     private void createIndexes() {
@@ -123,6 +125,16 @@ public class AccountDBManager {
         mongoDB.createIndex(Constants.ACLTEMPLATE_TABLE, keys);
         keyField.put(Constants.ACLTEMPLATE_TABLE, keys);
 
+        keys = new ArrayList<>();
+        keys.add(Constants.KEYFIELD_SN);
+        mongoDB.createIndex(Constants.CERTIFICATE_TABLE, keys);
+        keyField.put(Constants.CERTIFICATE_TABLE, keys);
+
+        keys = new ArrayList<>();
+        keys.add(Constants.REQ_THIS_UPDATE);
+        mongoDB.createIndex(Constants.CRL_TABLE, keys);
+        keyField.put(Constants.CRL_TABLE, keys);
+
     }
 
     public static AccountDBManager getInstance() {
  * //
  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  */
-package org.iotivity.cloud.accountserver.x509.crl;
+package org.iotivity.cloud.accountserver.db;
+
+import org.bson.types.Binary;
 
-import java.math.BigInteger;
 import java.util.Date;
 
-public class CrlInfo {
+public class CRLTable {
+
+    private Date thisUpdate;
+
+    private Binary binaryData;
+
+    public CRLTable() {
+    }
+
+    public CRLTable(Date thisUpdate, Binary binaryData) {
+        this.thisUpdate = thisUpdate;
+        this.binaryData = binaryData;
+    }
 
-    private BigInteger serialNumber;
-    private Date       revocationDate;
+    public Date getThisUpdate() {
+        return thisUpdate;
+    }
 
-    public void setSerialNumber(BigInteger serialNumber) {
-        this.serialNumber = serialNumber;
+    public void setThisUpdate(Date thisUpdate) {
+        this.thisUpdate = thisUpdate;
     }
 
-    public BigInteger getSerialNumber() {
-        return serialNumber;
+    public Binary getBinaryData() {
+        return binaryData;
     }
 
-    public void setRevocationDate(Date date) {
-        this.revocationDate = date;
+    public void setBinaryData(Binary binaryData) {
+        this.binaryData = binaryData;
     }
 
-    public Date getRevocationDate() {
-        return new Date(revocationDate.getTime());
+    @Override
+    public String toString() {
+        return "CRLTable{" +
+                "thisUpdate=" + thisUpdate +
+                ", binaryData=" + binaryData +
+                '}';
     }
 }
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/CertificateTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/CertificateTable.java
new file mode 100644 (file)
index 0000000..b4fc533
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+import java.util.Date;
+
+
+public class CertificateTable {
+
+    private String serialNumber;
+
+    private Date notAfter;
+
+    private Date notBefore;
+
+    private String did;
+
+    private String userid;
+
+    private boolean revoked;
+
+    public CertificateTable() {
+    }
+
+    public CertificateTable(String serialNumber, Date notAfter, Date notBefore, String did, String userid, boolean revoked) {
+        this.serialNumber = serialNumber;
+        this.notAfter = notAfter;
+        this.notBefore = notBefore;
+        this.did = did;
+        this.userid = userid;
+        this.revoked = revoked;
+    }
+
+    public String getSerialNumber() {
+        return serialNumber;
+    }
+
+    public void setSerialNumber(String serialNumber) {
+        this.serialNumber = serialNumber;
+    }
+
+    public Date getNotAfter() {
+        return notAfter;
+    }
+
+    public void setNotAfter(Date notAfter) {
+        this.notAfter = notAfter;
+    }
+
+    public Date getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(Date notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public String getDid() {
+        return did;
+    }
+
+    public void setDid(String did) {
+        this.did = did;
+    }
+
+    public String getUserid() {
+        return userid;
+    }
+
+    public void setUserid(String userid) {
+        this.userid = userid;
+    }
+
+    public boolean isRevoked() {
+        return revoked;
+    }
+
+    public void setRevoked(boolean revoked) {
+        this.revoked = revoked;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateManager.java
deleted file mode 100644 (file)
index 77373f0..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.iotivity.cloud.accountserver.resources.certificate;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.iotivity.cloud.accountserver.Constants;
-
-public class CertificateManager {
-    private Map<String, Object> mResponsePayload  = new HashMap<>();
-
-    public Map<String, Object> createPayload(byte[] cert, byte[] cacert) {
-        mResponsePayload.put(Constants.RESP_CERT, cert);
-        mResponsePayload.put(Constants.RESP_CACERT, cacert);
-        return mResponsePayload;
-    }
-
-
-    public void addDeviceId(String di) {
-        mResponsePayload.put(Constants.RESP_DEVICE_ID, di);
-    }
-
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/certificate/CertificateResource.java
deleted file mode 100644 (file)
index 8abbea2..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * //******************************************************************
- * //
- * // Copyright 2016 Samsung Electronics All Rights Reserved.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- * //
- * // 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.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- */
-package org.iotivity.cloud.accountserver.resources.certificate;
-
-import java.security.PublicKey;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.iotivity.cloud.accountserver.Constants;
-import org.iotivity.cloud.accountserver.x509.cert.CSRParser;
-import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
-import org.iotivity.cloud.accountserver.x509.cert.CertificateIssuerConfig;
-import org.iotivity.cloud.accountserver.x509.cert.CertificatePrivateKeyPair;
-import org.iotivity.cloud.base.device.Device;
-import org.iotivity.cloud.base.exception.ServerException;
-import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
-import org.iotivity.cloud.base.protocols.IRequest;
-import org.iotivity.cloud.base.protocols.IResponse;
-import org.iotivity.cloud.base.protocols.MessageBuilder;
-import org.iotivity.cloud.base.protocols.enums.ContentFormat;
-import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
-import org.iotivity.cloud.base.resource.Resource;
-import org.iotivity.cloud.util.Cbor;
-
-public class CertificateResource extends Resource {
-    /* resource uri for certificate issuer */
-    private Cbor<HashMap<String, Object>> mCbor               = new Cbor<>();
-    private CertificateManager            mCertificateManager = new CertificateManager();
-    private static String                 DEVICE_OU           = "OCF Device";
-
-    public CertificateResource() {
-        super(Arrays.asList(Constants.PREFIX_OIC, Constants.CREDPROV_URI,
-                Constants.CERT_URI));
-    }
-
-    @Override
-    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
-            throws ServerException {
-        IResponse response = null;
-
-        switch (request.getMethod()) {
-            case POST:
-                response = handlePutRequest(request);
-                break;
-
-            default:
-                throw new BadRequestException(
-                        request.getMethod() + " request type is not support");
-        }
-
-        srcDevice.sendResponse(response);
-    }
-
-    private IResponse handlePutRequest(IRequest request)
-            throws ServerException {
-
-        Map<String, Object> payloadData = mCbor
-                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
-
-        if (payloadData == null) {
-            throw new BadRequestException("CBOR parsing failed");
-        }
-
-        Map<String, Object> responsePayload = null;
-
-        if (payloadData.containsKey(Constants.REQ_CSR)) {
-
-            byte[] csrDer = (byte[]) payloadData.get(Constants.REQ_CSR);
-            CSRParser parser = null;
-            PublicKey pubKey = null;
-
-            try {
-                parser = new CSRParser(csrDer);
-                if (!parser.verify()) {
-                    throw new Exception();
-                }
-                pubKey = parser.getPublicKey();
-            } catch (Exception e) {
-                throw new BadRequestException("Bad CSR");
-            }
-
-            CertificateIssuerConfig ciConfig = CertificateIssuerConfig
-                    .getInstance();
-
-            Date notBefore = ciConfig.getNotBeforeDate();
-            Date notAfter = ciConfig.getNotAfterDate();
-
-            CertificateBuilder certBuilder = new CertificateBuilder(
-                    parser.getCommonName(), pubKey, notBefore, notAfter,
-                    ciConfig.getNextSerialNumber(),
-                    ciConfig.getRootCertificate());
-
-            certBuilder.setSubjectC(parser.getCountry());
-
-            certBuilder.setSubjectO(parser.getOrganizational());
-
-            certBuilder.setSubjectOU(DEVICE_OU);
-
-            CertificatePrivateKeyPair devCert = null;
-
-            try {
-                devCert = certBuilder.build();
-                // System.out.println("============================== DEV CERT
-                // ===========================");
-                // System.out.println();
-                // System.out.println(devCert.getCertificate().toString());
-                // System.out.println("===================================================================");
-
-                if (payloadData.containsKey(Constants.REQ_DEVICE_ID)) {
-                    mCertificateManager.addDeviceId(
-                            (String) payloadData.get(Constants.RESP_DEVICE_ID));
-                }
-
-                responsePayload = mCertificateManager.createPayload(
-                        devCert.getCertificate().getEncoded(),
-                        ciConfig.getRootCertificate().getCertificate()
-                                .getEncoded());
-
-            } catch (Exception e) {
-                throw new BadRequestException("Certificate generation error");
-            }
-
-        } else {
-            throw new BadRequestException("CSR is null");
-        }
-
-        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
-                ContentFormat.APPLICATION_CBOR,
-                mCbor.encodingPayloadToCbor(responsePayload));
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java
new file mode 100644 (file)
index 0000000..68d6fb3
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.cert;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.x509.cert.Utility;
+import org.iotivity.cloud.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.Properties;
+
+import static java.security.cert.CertificateFactory.getInstance;
+
+/**
+ * This utility class is used for getting all properties from properties file.
+ */
+public final class CertificateConstants {
+
+    public static final Properties PROPERTIES = new Properties();
+
+    /**
+     * Load properties from specified properties file.
+     */
+    static {
+        try {
+            PROPERTIES.load(new FileInputStream(Constants.PROPERTIES_FILE_NAME));
+        } catch (IOException e) {
+            Log.e(e.getMessage());
+        }
+    }
+
+    public static final String BASE_64 = "oic.sec.encoding.base64";
+
+    public static final String DER = "oic.sec.encoding.der";
+
+    public static final String SECURITY_PROVIDER = PROPERTIES.getProperty("securityProvider");
+
+    public static final String NOT_AFTER_INTERVAL = PROPERTIES.getProperty("notAfterInterval");
+
+    public static final String NEXT_UPDATE_INTERVAL = PROPERTIES.getProperty("nextUpdateInterval");
+
+    public static final String SIGNATURE_ALGORITHM = PROPERTIES.getProperty("signatureAlgorithm");
+
+    static final String KEYSTORE_TYPE = PROPERTIES.getProperty("keystoreType");
+
+    static final String CA_ALIAS = PROPERTIES.getProperty("caAlias");
+
+    static final String CURVE = PROPERTIES.getProperty("ellipticCurve");
+
+    static final String KEY_GENERATOR_ALGORITHM = PROPERTIES.getProperty("keyGeneratorAlgorithm");
+
+    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
+
+    public static final X500Name CA_ISSUER = Utility.getName(PROPERTIES.getProperty("subjectName"),
+            PROPERTIES.getProperty("rootC"), PROPERTIES.getProperty("rootO"), PROPERTIES.getProperty("rootOU"));
+
+    public static final AccountDBManager ACCOUNT_DB_MANAGER = AccountDBManager.getInstance();
+
+    public static CertificateFactory CERTIFICATE_FACTORY;
+
+    static {
+        try {
+            CERTIFICATE_FACTORY = getInstance("X509");
+        } catch (CertificateException e) {
+            Log.e(e.getMessage());
+        }
+    }
+
+    /**
+     * Path to keystore file
+     */
+    public static final File KEYSTORE_FILE = new File(MessageFormat.
+            format(PROPERTIES.getProperty("keyStoreLocation"), File.separator));
+
+    /**
+     * Set specified value for specified property.
+     * @param property specified property
+     * @param value specified property value.
+     */
+    public static void set(String property, String value) {
+        PROPERTIES.setProperty(property, value);
+        try {
+            PROPERTIES.store(new FileOutputStream(Constants.PROPERTIES_FILE_NAME), "New Serial number");
+        } catch (IOException e) {
+            Log.e(e.getMessage());
+        }
+    }
+
+    private CertificateConstants() {
+        throw new AssertionError();
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java
new file mode 100644 (file)
index 0000000..bb36946
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.cert;
+
+import org.iotivity.cloud.accountserver.db.CertificateTable;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.accountserver.x509.cert.Utility;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.iotivity.cloud.accountserver.Constants.CERTIFICATE_TABLE;
+import static org.iotivity.cloud.accountserver.Constants.KEYFIELD_DID;
+import static org.iotivity.cloud.accountserver.Constants.KEYFIELD_REVOKED;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.ACCOUNT_DB_MANAGER;
+
+
+/**
+ * This class is used as DB manager for CertificateTable.
+ * With help of this class we can save certificate info to DB,
+ * retrieve it from DB by specified in constructor device id,
+ * updateX509CRL certificate, also it helps us get user Id from Token
+ * Table by specified device id.
+ */
+final class CertificateManager {
+
+    /**
+     * Type casting manager for converting CertificateTable object tot map
+     */
+    private static final TypeCastingManager<CertificateTable> CERTIFICATE_TABLE_TYPE_CASTING_MANAGER =
+            new TypeCastingManager<>();
+
+    /**
+     * Class attribute as payload for response.
+     */
+    private final Map<String, Object> payLoad;
+
+    /**
+     * Class attribute to store device id.
+     */
+    private final String deviceId;
+
+    /**
+     * Constructs certificateMananger with specified device id.
+     * @param deviceId specified device identifier for this CertificateManager.
+     */
+    CertificateManager(String deviceId) {
+        payLoad = new HashMap<>();
+        this.deviceId = deviceId;
+    }
+
+    /**
+     * Returns payload for response.
+     */
+    Map<String, Object> getPayLoad() {
+        return payLoad;
+    }
+
+    /**
+     * Puts for specified key, specified value to
+     * object payload;
+     * @param key specified key value
+     * @param value specified value
+     */
+    public void put(String key, Object value) {
+        payLoad.put(key, value);
+    }
+
+    /**
+     * Saves new certificate to DB with specified columns.
+     *
+     * @param serialNumber specified certificate serial number
+     * @param notAfter validation date not after
+     * @param notBefore validation date not before
+     */
+    void save(BigInteger serialNumber, Date notAfter, Date notBefore) {
+        ACCOUNT_DB_MANAGER.insertRecord(CERTIFICATE_TABLE,
+                CERTIFICATE_TABLE_TYPE_CASTING_MANAGER.convertObjectToMap(
+                        new CertificateTable(serialNumber.toString(), notAfter,
+                        notBefore, deviceId, Utility.getUserID(deviceId), false)));
+    }
+
+    /**
+     * Updates certificate table with specified revoked column.
+     * @param certificateTable certificate to be updated.
+     * @param revoked specified value for revoke
+     */
+    void update(CertificateTable certificateTable, boolean revoked) {
+        certificateTable.setRevoked(revoked);
+        ACCOUNT_DB_MANAGER.updateRecord(CERTIFICATE_TABLE,
+                CERTIFICATE_TABLE_TYPE_CASTING_MANAGER.convertObjectToMap(certificateTable));
+    }
+
+    /**
+     * Returns certificate from database, according to specified
+     * device id
+     */
+    public CertificateTable getCertificate() {
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(KEYFIELD_DID, deviceId);
+        condition.put(KEYFIELD_REVOKED, false);
+        List<HashMap<String, Object>> listMap = ACCOUNT_DB_MANAGER.selectRecord(
+                CERTIFICATE_TABLE, condition);
+        if (!listMap.isEmpty()) {
+            return CERTIFICATE_TABLE_TYPE_CASTING_MANAGER
+                    .convertMaptoObject(
+                            listMap.get(0),
+                            new CertificateTable());
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java
new file mode 100644 (file)
index 0000000..e7113d5
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.cert;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.encoders.Base64;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.CertificateTable;
+import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlManager;
+import org.iotivity.cloud.accountserver.x509.cert.CSRParser;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateExtension;
+import org.iotivity.cloud.accountserver.x509.cert.Utility;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.enums.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Log;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.Security;
+import java.security.cert.CRLException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.iotivity.cloud.accountserver.Constants.*;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.BASE_64;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.KEYSTORE_FILE;
+
+/**
+ * This class provides access for certificate resource.
+ * Devices can send CSR requests in CBOR format to this resource
+ * and get responses in the same format. Response contains device identifier,
+ * personal certificate, issued by CA certificate and certificate chain.
+ */
+public class CertificateResource extends Resource {
+
+    /**
+     * This constant object is used for parsing cbor payload to Map object and to
+     * encoding map object to cbor format.
+     */
+    private static final Cbor<Map<String, Object>> MAP_CBOR = new Cbor<>();
+
+    /**
+     * Constructs certificate resourcewith specified prefixes
+     */
+    public CertificateResource() {
+        super(Arrays.asList(PREFIX_OIC, CREDPROV_URI, CERT_URI));
+    }
+
+    /**
+     * Insert BouncyCastleProvider into 0 position in security provider list.
+     * Init KeyStore, Generate CA certificate and save it to keyStore.
+     */
+    static {
+        Security.insertProviderAt(new BouncyCastleProvider(), 0);
+        try {
+            if (!KEYSTORE_FILE.exists()) {
+                CertificateStorage.init();
+            } else {
+                CertificateStorage.load();
+            }
+        } catch (GeneralSecurityException | IOException | OperatorCreationException e) {
+            Log.e(e.getMessage());
+        }
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        IResponse response;
+        switch (request.getMethod()) {
+            case POST:
+                response = handlePostRequest(request);
+                break;
+            default:
+                response = MessageBuilder.createResponse(request, ResponseStatus.METHOD_NOT_ALLOWED);
+        }
+        srcDevice.sendResponse(response);
+    }
+
+    /**
+     * Handles post requests to this resource
+     * @param request request with payload information.
+     * @throws ServerException
+     */
+    private IResponse handlePostRequest(IRequest request)
+            throws ServerException {
+        Map<String, Object> payloadData = MAP_CBOR
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+        IResponse response = MessageBuilder.createResponse(request, ResponseStatus.BAD_REQUEST);
+        Object csr = payloadData.get(Constants.REQ_CSR);
+        if (csr != null && csr instanceof Map) {
+            Object encoding =((Map<String, Object>)csr).get(ENCODING);
+            Object data = ((Map<String, Object>)csr).get(DATA);
+            if (encoding != null && encoding instanceof String && data != null && data instanceof byte[]) {
+                byte[] csrData = (byte[]) data;
+                if (encoding.equals(BASE_64)) {
+                    csrData = Base64.decode(csrData);
+                }
+                try {
+                    CSRParser parser = new CSRParser(csrData);
+                    String commonName = parser.getCommonName();
+                    String pattern = "^uuid:(.*)$";
+                    Pattern r = Pattern.compile(pattern);
+                    Matcher m = r.matcher(commonName);
+                    String deviceId = (String) payloadData.get(RESP_DEVICE_ID);
+                    if (m.find() && m.group(1).equals(deviceId) && parser.isSignatureValid()) {
+                        CertificateManager certificateManager = new CertificateManager(deviceId);
+                        CertificateTable certificateTable = certificateManager.getCertificate();
+                        if (certificateTable != null) {
+                            try {
+                                CrlManager.CRL_MANAGER.revoke(certificateTable.getSerialNumber());
+                            } catch (CRLException | OperatorCreationException e) {
+                                Log.e(e.getMessage() + e.getClass());
+                            }
+                            certificateManager.update(certificateTable, true);
+                        }
+                        CertificateExtension extension = new CertificateExtension(Extension.subjectAlternativeName,
+                                false, new DERSequence(new ASN1Encodable[]
+                                {new GeneralName(GeneralName.dNSName, Constants.KEYFIELD_USERID + ":" +
+                                        Utility.getUserID(deviceId))}));
+                        CertificateBuilder certBuilder = new CertificateBuilder(parser.getSubject(),
+                                parser.getPublicKey(), extension );
+                        try {
+                            X509Certificate personal = certBuilder.build();
+                            byte[] encodedCert = personal.getEncoded();
+                            byte[] encodedCa = CertificateStorage.ROOT_CERTIFICATE.getEncoded();
+                            if (encoding.equals(CertificateConstants.BASE_64)) {
+                                encodedCert = Base64.encode(encodedCert);
+                                encodedCa =  Base64.encode(encodedCa);
+                            }
+                            certificateManager.put(Constants.RESP_DEVICE_ID, deviceId);
+                            certificateManager.put(Constants.CERT, new CSR(encoding.toString(), encodedCert));
+                            certificateManager.put(Constants.CERT_CHAIN,  new CSR(encoding.toString(), encodedCa));
+                            certificateManager.save(personal.getSerialNumber(), personal.getNotBefore(),
+                                    personal.getNotAfter());
+                            response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED,
+                                    ContentFormat.APPLICATION_CBOR,
+                                    MAP_CBOR.encodingPayloadToCbor(certificateManager.getPayLoad()));
+                        } catch (GeneralSecurityException | OperatorCreationException | CertIOException e) {
+                            Log.e(e.getMessage());
+                        }
+                    }
+                } catch (IOException e) {
+                    Log.e(e.getMessage());
+                }
+            }
+        }
+        return response;
+    }
+
+    /**
+     * This class is used for response
+     */
+    private static final class CSR {
+
+        private final String encoding;
+
+        private final byte[] data;
+
+        CSR(String encoding, byte[] data) {
+            this.encoding = encoding;
+            this.data = data;
+        }
+
+        public String getEncoding() {
+            return encoding;
+        }
+
+        public byte[] getData() {
+            return data;
+        }
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java
new file mode 100644 (file)
index 0000000..f632a20
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.cert;
+
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateExtension;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.*;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
+
+public final class CertificateStorage {
+
+    /**
+     * This attribute is used to get password to kestore, that stores CA certificate info.
+     * Private key and certificate.
+     */
+    private static final String PASSWORD = PROPERTIES.getProperty("password");
+
+    /**
+     * Keystore object for save, get data from keystore.
+     */
+    private static KeyStore keyStore;
+
+    public static PrivateKey ROOT_PRIVATE_KEY;
+
+    public static X509Certificate ROOT_CERTIFICATE;
+
+    private CertificateStorage() {
+        throw new AssertionError();
+    }
+
+    /**
+     * Init KeyStore. If it does not exists, create it and push to KEYSTORE_FILE.
+     */
+    static void init() throws GeneralSecurityException, IOException, OperatorCreationException {
+        Files.createDirectories(Paths.get("keystore"));
+        keyStore = load(null, null);
+        store();
+        CertificateStorage.generateCACertificate();
+        CertificateStorage.saveCertificatePrivateKey();
+    }
+
+    /**
+     * Load KeyStore with default keystore file and password.
+     *
+     * @return KeyStore instance.
+     */
+    public static void load() throws GeneralSecurityException, IOException {
+        keyStore = load(new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
+        initRoot();
+    }
+
+    /**
+     * Loads KeyStore with defined inputStream object and password.
+     *
+     * @param is       specified inputStream which contains keystore bytes.
+     * @param password specified password for opening keystore.
+     * @return KeyStore instance.
+     */
+    private static KeyStore load(InputStream is, char[] password) throws IOException, GeneralSecurityException {
+        KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE, BouncyCastleProvider.PROVIDER_NAME);
+        keyStore.load(is, password);
+        return keyStore;
+    }
+
+
+    /**
+     * Stores keyStore to default file KEYSTORE_FILE with default password.
+     */
+    static void store() throws IOException, GeneralSecurityException {
+        store(keyStore, new FileOutputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
+    }
+
+    /**
+     * Stores KeyStore to file outputstream with specifie password.
+     *
+     * @param keyStore
+     */
+    private static void store(KeyStore keyStore, FileOutputStream out, char[] password) throws GeneralSecurityException,
+            IOException {
+        keyStore.store(out, password);
+        out.close();
+    }
+
+    /**
+     * Generates X509Certificate  with PublicKey and PrivateKey
+     *
+     * @return certificate and private key
+     */
+    private static void generateCACertificate() throws GeneralSecurityException,
+            OperatorCreationException, CertIOException {
+        if (ROOT_PRIVATE_KEY == null) {
+            KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, SECURITY_PROVIDER);
+            g.initialize(ECNamedCurveTable.getParameterSpec(CURVE), new SecureRandom());
+            KeyPair pair = g.generateKeyPair();
+            ROOT_PRIVATE_KEY = pair.getPrivate();
+            ROOT_CERTIFICATE = new CertificateBuilder(CA_ISSUER, pair.getPublic(),
+                    new CertificateExtension(Extension.basicConstraints, false,
+                            new BasicConstraints(true))).build();
+        }
+    }
+
+    /**
+     * Stores certificate and private key to keystore.
+     */
+    private static void saveCertificatePrivateKey() throws GeneralSecurityException, IOException {
+        keyStore.setCertificateEntry(CA_ALIAS, ROOT_CERTIFICATE);
+        keyStore.setKeyEntry(CA_ALIAS, ROOT_PRIVATE_KEY, PASSWORD.toCharArray(),
+                new Certificate[]{ROOT_CERTIFICATE});
+        store();
+    }
+
+    private static void initRoot() throws GeneralSecurityException {
+        ROOT_PRIVATE_KEY = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray());
+        ROOT_CERTIFICATE = (X509Certificate) keyStore.getCertificate(CA_ALIAS);
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java
new file mode 100644 (file)
index 0000000..d6d0f6a
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.crl;
+
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bson.types.Binary;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.CRLTable;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.cert.CRLException;
+import java.security.cert.X509CRL;
+import java.text.ParseException;
+import java.util.*;
+
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
+import static org.iotivity.cloud.accountserver.x509.crl.CrlIssuer.CRL_ISSUER;
+
+/**
+ * Class is used for managing CRLs(creation, revoke, update)
+ */
+public final class CrlManager {
+
+    /**
+     * Static manager for CRLs.
+     */
+    public static CrlManager CRL_MANAGER;
+    /**
+     * Casting manager for working with CRLTable in mongo db
+     */
+    private static TypeCastingManager<CRLTable> castingManager = new TypeCastingManager<>();
+
+    static {
+        try {
+            CRL_MANAGER = new CrlManager();
+            CRL_MANAGER.init();
+        } catch (CRLException | IOException | OperatorCreationException e) {
+            Log.e(e.getMessage());
+        }
+    }
+
+    /**
+     * X509 CRL presentation.
+     */
+    private X509CRL x509CRL;
+
+    private CrlManager() {
+    }
+
+    /**
+     * Revokes specified serial numbers.
+     *
+     * @param serialNumber specified var args serial numbers from 0.
+     */
+    public void revoke(String... serialNumber) throws CRLException, IOException, OperatorCreationException {
+        if (x509CRL != null) {
+            update(x509CRL.getThisUpdate(),
+                    CRL_ISSUER.generate(x509CRL.getThisUpdate(), x509CRL.getNextUpdate(),
+                            x509CRL.getRevokedCertificates(), serialNumber));
+        }
+    }
+
+    /**
+     * Check if last update is before CRL this update.
+     * @param lastUpdate specified last update;
+     * @return true if before and false - otherwise.
+     */
+    boolean checkLastUpdate(String lastUpdate) {
+        boolean checkCondition = false;
+        try {
+            if (x509CRL != null) {
+                checkCondition = DATE_FORMAT.parse(lastUpdate).before(x509CRL.getThisUpdate());
+            }
+        } catch (ParseException e) {
+            Log.e(e.getMessage());
+        }
+        return checkCondition;
+    }
+
+    /**
+     * Returns response payload, including this update, next update, and CRL in DER encoding.
+     */
+    Map<String, Object> getPayload() throws ServerException.PreconditionFailedException, CRLException {
+        if (x509CRL != null) {
+            Map<String, Object> responsePayload = new HashMap<>();
+            responsePayload.put(Constants.REQ_THIS_UPDATE, DATE_FORMAT.format(x509CRL.getThisUpdate()));
+            responsePayload.put(Constants.REQ_NEXT_UPDATE, DATE_FORMAT.format(x509CRL.getNextUpdate()));
+            responsePayload.put(Constants.REQ_CRL, new CRL(DER, x509CRL.getEncoded()));
+            return responsePayload;
+        }
+        return Collections.emptyMap();
+    }
+
+    /**
+     * Updates CRLTable with specified this update and binary CRL data.
+     */
+    void update(Date thisUpdate, byte[] data) throws CRLException {
+        CRLTable crlTable = castingManager.convertMaptoObject(
+                ACCOUNT_DB_MANAGER.selectRecord(Constants.CRL_TABLE, new HashMap<>()).get(0), new CRLTable());
+        crlTable.setThisUpdate(thisUpdate);
+        crlTable.setBinaryData(new Binary(data));
+        ACCOUNT_DB_MANAGER.updateRecord(Constants.CRL_TABLE, castingManager.convertObjectToMap(crlTable));
+        setX509CRL(data);
+    }
+
+    /**
+     * Create CRL with default options;
+     */
+    private void init() throws CRLException, IOException, OperatorCreationException {
+        Calendar calendar = Calendar.getInstance();
+        Date thisUpdate = calendar.getTime();
+        calendar.add(Calendar.DAY_OF_MONTH,
+                Integer.parseInt(NEXT_UPDATE_INTERVAL));
+        byte[] data = CRL_ISSUER.generate(thisUpdate, calendar.getTime(), Collections.emptyList());
+        ACCOUNT_DB_MANAGER.insertRecord(Constants.CRL_TABLE,
+                castingManager.convertObjectToMap(new CRLTable(thisUpdate, new Binary(data))));
+        setX509CRL(data);
+    }
+
+    /**
+     * Updates currect x509 CRL state by parsing specified data.
+     */
+    private void setX509CRL(byte[] data) throws CRLException {
+        x509CRL = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data));
+    }
+
+    /**
+     * Static inner class for CBOR Crl presentation.
+     */
+    private static final class CRL {
+
+        private final String encoding;
+
+        private final byte[] data;
+
+        public CRL(String encoding, byte[] data) {
+            this.encoding = encoding;
+            this.data = data;
+        }
+
+        public String getEncoding() {
+            return encoding;
+        }
+
+        public byte[] getData() {
+            return data;
+        }
+    }
+
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java
new file mode 100644 (file)
index 0000000..a274784
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.credprov.crl;
+
+
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.enums.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Log;
+
+import java.io.IOException;
+import java.security.cert.CRLException;
+import java.text.ParseException;
+import java.util.*;
+
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.BASE_64;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.DATE_FORMAT;
+import static org.iotivity.cloud.accountserver.resources.credprov.crl.CrlManager.CRL_MANAGER;
+
+/**
+ * Class is responsible for handling requests GET and POST for CRL data.
+ */
+public class CrlResource extends Resource {
+
+    /**
+     * CBOR container with help of map presentation.
+     */
+    private static final Cbor<Map<String, Object>> MAP_CBOR = new Cbor<>();
+
+    /**
+     * Creates resource for handling CRL requests(GET and POST)
+     */
+    public CrlResource() {
+        super(Arrays.asList(Constants.PREFIX_OIC,
+                Constants.CREDPROV_URI, Constants.REQ_CRL));
+
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        IResponse response;
+        switch (request.getMethod()) {
+            case POST:
+                response = handlePostRequest(request);
+                break;
+            case GET:
+                response = handleGetRequest(request);
+                break;
+            default:
+                response = MessageBuilder.createResponse(request, ResponseStatus.BAD_REQUEST);
+        }
+        srcDevice.sendResponse(response);
+    }
+
+    /**
+     * Handles GET request and sends response back to the client.
+     */
+    private IResponse handleGetRequest(IRequest request)
+            throws ServerException {
+        HashMap<String, List<String>> queryData = request.getUriQueryMap();
+        IResponse iResponse = MessageBuilder.createResponse(request, ResponseStatus.NOT_FOUND);
+        if (queryData != null) {
+            List<String> lastUpdateList = queryData.get(Constants.REQ_LAST_UPDATE);
+            if (lastUpdateList != null && !lastUpdateList.isEmpty() &&
+                    CRL_MANAGER.checkLastUpdate(lastUpdateList.get(0))) {
+                try {
+                    iResponse = MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                            ContentFormat.APPLICATION_CBOR, MAP_CBOR.encodingPayloadToCbor(CRL_MANAGER.getPayload()));
+                } catch (CRLException e) {
+                    Log.e(e.getMessage());
+                }
+            }
+        }
+        return iResponse;
+    }
+
+    /**
+     * Handles POST requests and sends back CRL data in response.
+     */
+    private IResponse handlePostRequest(IRequest request)
+            throws ServerException {
+        Map<String, Object> payloadData = MAP_CBOR
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+        Object thisUpdate = payloadData.get(Constants.REQ_THIS_UPDATE);
+        Object nextUpdate = payloadData.get(Constants.REQ_NEXT_UPDATE);
+        IResponse response = MessageBuilder.createResponse(request, ResponseStatus.PRECONDITION_FAILED);
+        if (thisUpdate != null && thisUpdate instanceof String && nextUpdate != null && nextUpdate instanceof String) {
+            Date thisUpdateDate;
+            try {
+                thisUpdateDate = DATE_FORMAT.parse(thisUpdate.toString());
+                DATE_FORMAT.parse(nextUpdate.toString());
+                Object reqSerialNumber = payloadData.get(Constants.REQ_SERIAL_NUMBER);
+                Object crl = payloadData.get(Constants.REQ_CRL);
+                if (reqSerialNumber != null && reqSerialNumber instanceof List) {
+                    CRL_MANAGER.revoke(((List<String>) reqSerialNumber).toArray(new String[]{}));
+                    response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED);
+                } else if (crl != null && crl instanceof Map) {
+                    Object encoding = ((Map<String, Object>) crl).get(Constants.ENCODING);
+                    Object crlData = ((Map<String, Object>) crl).get(Constants.DATA);
+                    if (encoding != null && encoding instanceof String && crlData != null && crlData instanceof byte[]) {
+                        try {
+                            if (encoding.equals(BASE_64)) {
+                                crlData = Base64.decode((byte[]) crlData);
+                            }
+                            CRL_MANAGER.update(thisUpdateDate, (byte[]) crlData);
+                            response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED);
+                        } catch (DecoderException e) {
+                            Log.e(e.getMessage() + e.getClass());
+                        }
+                    }
+                }
+            } catch (CRLException | IOException | OperatorCreationException | ParseException e) {
+                Log.e(e.getMessage() + e.getClass());
+            }
+        }
+        return response;
+    }
+}
index be287dc..0bf7401 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.cert;
 
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.security.PublicKey;
-import java.security.Security;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x500.RDN;
 import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openssl.PEMException;
-import org.bouncycastle.openssl.PEMParser;
 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
 import org.bouncycastle.pkcs.PKCS10CertificationRequest;
 import org.bouncycastle.pkcs.PKCSException;
+import org.iotivity.cloud.util.Log;
+
+import java.io.IOException;
+import java.security.PublicKey;
 
+import static org.bouncycastle.asn1.x500.style.BCStyle.CN;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.SECURITY_PROVIDER;
 
+/**
+ * Class is used for parsing CSR requests.
+ */
 public class CSRParser {
-    private PKCS10CertificationRequest mCsr;
-    private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-    private static final String COUNTRY = "2.5.4.6";
-    private static final String STATE = "2.5.4.8";
-    private static final String LOCALE = "2.5.4.7";
-    private static final String ORGANIZATION = "2.5.4.10";
-    private static final String ORGANIZATION_UNIT = "2.5.4.11";
-    private static final String COMMON_NAME = "2.5.4.3";
-
-    public CSRParser(String csrPem) throws IOException {
-        Security.addProvider(new BouncyCastleProvider());
-        mCsr = convertPemToPKCS10CertificationRequest(csrPem);
-    }
 
+    /**
+     * PKCS10CertificationRequest attribute.
+     */
+    private final PKCS10CertificationRequest mCsr;
+
+    /**
+     * Certificate subject.
+     */
+    private final X500Name subject;
+
+    /**
+     * Creates CSRParser instance with specified csrDer byte array.
+     *
+     * @param csrDer specified byte array.
+     */
     public CSRParser(byte[] csrDer) throws IOException {
-        Security.addProvider(new BouncyCastleProvider());
         mCsr = new PKCS10CertificationRequest(csrDer);
+        subject = mCsr.getSubject();
     }
 
-    public String getOrganizationalUnit() {
-        return getX500Field(ORGANIZATION_UNIT, mCsr.getSubject());
-    }
-
-    public String getOrganizational() {
-        return getX500Field(ORGANIZATION, mCsr.getSubject());
-    }
-
-    public String getCountry() {
-        return getX500Field(COUNTRY, mCsr.getSubject());
-    }
-
-    public String getState() {
-        return getX500Field(STATE, mCsr.getSubject());
-    }
-
-    public String getLocale() {
-        return getX500Field(LOCALE, mCsr.getSubject());
-    }
-
-    public String getCommonName() {
-        return getX500Field(COMMON_NAME, mCsr.getSubject());
-    }
-
-    public SubjectPublicKeyInfo getPublicKeyInfo() {
-        return mCsr.getSubjectPublicKeyInfo();
-    }
-
-    public PublicKey getPublicKey() throws PEMException {
-        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BC);
-        return converter.getPublicKey(getPublicKeyInfo());
+    /**
+     * Returns public key
+     */
+    public PublicKey getPublicKey() {
+        PublicKey publicKey = null;
+        try {
+            publicKey = new JcaPEMKeyConverter().setProvider(SECURITY_PROVIDER).
+                    getPublicKey(mCsr.getSubjectPublicKeyInfo());
+        } catch (PEMException e) {
+            Log.e(e.getMessage());
+        }
+        return publicKey;
     }
 
-    public boolean verify() {
-        SubjectPublicKeyInfo publicKeyInfo = mCsr.getSubjectPublicKeyInfo();
+    /**
+     * Verifies signature from this CSR request with help of
+     *
+     * @return true if signature is correct and false otherwise.
+     */
+    public boolean isSignatureValid() {
+        boolean condition = false;
         try {
-            return mCsr.isSignatureValid(new JcaContentVerifierProviderBuilder()
-                    .setProvider(BC).build(publicKeyInfo));
+            condition = mCsr.isSignatureValid(new JcaContentVerifierProviderBuilder()
+                    .setProvider(SECURITY_PROVIDER).build(mCsr.getSubjectPublicKeyInfo()));
         } catch (OperatorCreationException | PKCSException e) {
-            return false;
+            Log.e(e.getMessage());
         }
+        return condition;
     }
 
-    public boolean authenticate(String uuid) {
-        return uuid.equals(this.getCommonName());
-    }
-
-    private PKCS10CertificationRequest convertPemToPKCS10CertificationRequest(String pem)
-            throws IOException {
-        Security.addProvider(new BouncyCastleProvider());
-        ByteArrayInputStream pemStream = null;
-
-        pemStream = new ByteArrayInputStream(pem.getBytes("UTF-8"));
-
-        Reader pemReader = new BufferedReader(new InputStreamReader(pemStream));
-        PEMParser pemParser = new PEMParser(pemReader);
-
-        Object parsedObj = pemParser.readObject();
-
-        if (parsedObj instanceof PKCS10CertificationRequest) {
-            mCsr = (PKCS10CertificationRequest) parsedObj;
-        }
-
-        pemParser.close();
-        mCsr.getEncoded();
+    /**
+     * Returns common name from csr subject.
+     */
+    public String getCommonName() {
+        return subject.getRDNs(CN)[0].getFirst().getValue().toString();
 
-        return mCsr;
     }
 
-    private String getX500Field(String asn1ObjectIdentifier, X500Name x500Name) {
-        RDN[] rdnArray = x500Name.getRDNs(new ASN1ObjectIdentifier(asn1ObjectIdentifier));
-        String retVal = null;
-        for (RDN item : rdnArray) {
-            retVal = item.getFirst().getValue().toString();
-        }
-        return retVal;
+    /**
+     * Returns subject as X500Name.
+     */
+    public X500Name getSubject() {
+        return subject;
     }
-
 }
index 00f3038..041bea7 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.cert;
 
-import java.math.BigInteger;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.x500.RDN;
 import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameBuilder;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.bouncycastle.asn1.x500.style.IETFUtils;
-import org.bouncycastle.asn1.x509.Extension;
 import org.bouncycastle.cert.CertIOException;
 import org.bouncycastle.cert.X509v3CertificateBuilder;
 import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
 import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-import org.bouncycastle.operator.ContentSigner;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
 
-public class CertificateBuilder {
-    private String              mIssuer;
-    private String              mSubjectCN;
-    private String              mSubjectC;
-    private String              mSubjectO;
-    private String              mSubjectOU;
-    private String              mSubjectAltName;
-    private Date                mNotBefore;
-    private Date                mNotAfter;
-    private PrivateKey          mPrivKey;
-    private PublicKey           mPubKey;
-    private BigInteger          mSerial;
-    private static final String BC                      = BouncyCastleProvider.PROVIDER_NAME;
-    private static final String SIGNATURE_ALGORITHM     = "SHA256withECDSA";
-    private static final String CURVE                   = "secp256r1";
-    private static final String KEY_GENERATOR_ALGORITHM = "ECDSA";
-
-    public CertificateBuilder(String subject, Date notBefore, Date notAfter,
-            BigInteger serial) {
-        Security.addProvider(new BouncyCastleProvider());
-        init(subject, null, notBefore, notAfter, null, null, serial);
-    }
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
 
-    public CertificateBuilder(String subject, PublicKey pubKey, Date notBefore,
-            Date notAfter, BigInteger serial, CertificatePrivateKeyPair root) {
-        X500Name x500name = new X500Name(
-                root.getCertificate().getSubjectX500Principal().getName());
-        RDN cn = x500name.getRDNs(BCStyle.CN)[0];
-        init(subject, IETFUtils.valueToString(cn.getFirst().getValue()),
-                notBefore, notAfter, root.getKey(), pubKey, serial);
-    }
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
 
-    public CertificateBuilder(String subject, String issuer, Date notBefore,
-            Date notAfter, PrivateKey privKey, PublicKey pubKey,
-            BigInteger serial) {
-        Security.addProvider(new BouncyCastleProvider());
-        init(subject, issuer, notBefore, notAfter, privKey, pubKey, serial);
-    }
+/**
+ * Class is used for generating X509 certificate with specified in properties signature and ley algorithms.
+ */
+public class CertificateBuilder {
 
-    private void init(String subject, String issuer, Date notBefore,
-            Date notAfter, PrivateKey privKey, PublicKey pubKey,
-            BigInteger serial) {
-        this.mSubjectCN = subject;
-        this.mIssuer = issuer;
-        this.mNotBefore = notBefore;
-        this.mNotAfter = notAfter;
-        this.mPrivKey = privKey;
-        this.mPubKey = pubKey;
-        this.mSerial = serial;
+    /**
+     * SIGNER_BUILDER for building X509 certificates
+     */
+    public static final JcaContentSignerBuilder SIGNER_BUILDER = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM)
+            .setProvider(SECURITY_PROVIDER);
+
+    /**
+     * Serial number of last issued certificate.
+     */
+    private static BigInteger SERIAL_NUMBER = new BigInteger(PROPERTIES.getProperty("serialNumber"));
+
+    /**
+     * Attribute for X500Name subject.
+     */
+    private X500Name subject;
+
+    /**
+     * Attribute for public key.
+     */
+    private PublicKey publicKey;
+
+    /**
+     * Attribute for certificate extension.
+     */
+    private CertificateExtension extension;
+
+    /**
+     * Constructs certificate builder with specified subject
+     * public key and certificate extension.
+     */
+    public CertificateBuilder(X500Name subject,
+                              PublicKey publicKey, CertificateExtension extension) {
+        this.subject = subject;
+        this.publicKey = publicKey;
+        this.extension = extension;
     }
 
-    public void setSubjectC(String subjectC) {
-        this.mSubjectC = subjectC;
+    /**
+     * Builds X509Certificate with default root key.
+     */
+    public X509Certificate build() throws CertIOException, GeneralSecurityException, OperatorCreationException {
+        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
+                CA_ISSUER,
+                getNextSerialNumber(), getNotBeforeDate(), getNotAfterDate(), subject, publicKey);
+        certGen.addExtension(extension.getOid(), extension.isCritical(),
+                extension.getValue());
+        return new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER).
+                getCertificate(certGen.build(
+                        SIGNER_BUILDER.build(CertificateStorage.ROOT_PRIVATE_KEY)));
     }
 
-    public void setSubjectO(String subjectO) {
-        this.mSubjectO = subjectO;
+    /**
+     * Returns next serial number.
+     */
+    private static BigInteger getNextSerialNumber() {
+        SERIAL_NUMBER = SERIAL_NUMBER.add(BigInteger.ONE);
+        set("serialNumber", SERIAL_NUMBER.toString());
+        return SERIAL_NUMBER;
     }
 
-    public void setSubjectOU(String subjectOU) {
-        this.mSubjectOU = subjectOU;
+    /**
+     * Returns date not before.
+     */
+    private Date getNotBeforeDate() {
+        return Calendar.getInstance().getTime();
     }
 
-    public void setSubjectAltName(String subjectAltName) {
-        this.mSubjectAltName = subjectAltName;
+    /**
+     * Returns date not after.
+     */
+    private Date getNotAfterDate() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) +
+                Integer.parseInt(NOT_AFTER_INTERVAL));
+        return calendar.getTime();
     }
 
-    public CertificatePrivateKeyPair build() throws GeneralSecurityException,
-            OperatorCreationException, CertIOException {
-        if (null == mPrivKey && null == mPubKey) {
-            ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
-            KeyPairGenerator g = null;
-
-            g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, BC);
-            g.initialize(ecSpec, new SecureRandom());
-
-            KeyPair pair = g.generateKeyPair();
-            mPrivKey = pair.getPrivate();
-            mPubKey = pair.getPublic();
-            mIssuer = mSubjectCN;
-        }
-
-        X509Certificate cert = null;
-        X500NameBuilder subjectNameBld = new X500NameBuilder(BCStyle.INSTANCE);
-
-        subjectNameBld.addRDN(BCStyle.CN, mSubjectCN);
-
-        if (null != mSubjectOU) {
-            subjectNameBld.addRDN(BCStyle.OU, mSubjectOU);
-        }
-
-        if (null != mSubjectO) {
-            subjectNameBld.addRDN(BCStyle.O, mSubjectO);
-        }
-
-        if (null != mSubjectC) {
-            subjectNameBld.addRDN(BCStyle.C, mSubjectC);
-        }
-
-        X500NameBuilder issuerNameBld = new X500NameBuilder(BCStyle.INSTANCE);
-        issuerNameBld.addRDN(BCStyle.CN, mIssuer);
-
-        if (mPrivKey == null || mPubKey == null)
-            throw new CertIOException("mPrivKey or mPubKey is null!");
-
-        ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM)
-                .setProvider(BC).build(mPrivKey);
-
-        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
-                issuerNameBld.build(), mSerial, mNotBefore, mNotAfter,
-                subjectNameBld.build(), mPubKey);
-
-        if (null != mSubjectAltName) {
-            certGen.addExtension(Extension.subjectAlternativeName, false,
-                    new DEROctetString(mSubjectAltName.getBytes()));
-        }
-
-        cert = new JcaX509CertificateConverter().setProvider("BC")
-                .getCertificate(certGen.build(sigGen));
-
-        return new CertificatePrivateKeyPair(cert, mPrivKey);
-    }
 
 }
\ No newline at end of file
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java
new file mode 100644 (file)
index 0000000..8172a19
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.x509.cert;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * Class for representing certificate extension.
+ */
+public class CertificateExtension {
+
+    /**
+     * Attribute for ASN1 object identifier.
+     */
+    private final ASN1ObjectIdentifier oid;
+
+    /**
+     * Attribute checks critical or non critical type of extension.
+     */
+    private final boolean isCritical;
+
+    /**
+     * Attribute stores ASN1 Encodable value
+     */
+    private final ASN1Encodable value;
+
+    /**
+     * Constructs certificate extension with specified oid, isCritical, value parameters.
+     */
+    public CertificateExtension(ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value) {
+        this.oid = oid;
+        this.isCritical = isCritical;
+        this.value = value;
+    }
+
+    /**
+     * Returns attribute value for oid
+     */
+    ASN1ObjectIdentifier getOid() {
+        return oid;
+    }
+
+    /**
+     * Returns isCritical attribute value.
+     */
+    boolean isCritical() {
+        return isCritical;
+    }
+
+    /**
+     * Returns ASN1Encodable attribute value.
+     *
+     * @return
+     */
+    ASN1Encodable getValue() {
+        return value;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateIssuerConfig.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateIssuerConfig.java
deleted file mode 100644 (file)
index 2ecbba6..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * //******************************************************************
- * //
- * // Copyright 2016 Samsung Electronics All Rights Reserved.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- * //
- * // 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.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- */
-package org.iotivity.cloud.accountserver.x509.cert;
-
-import java.math.BigInteger;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-public class CertificateIssuerConfig {
-    private BigInteger mSerial;
-    private CertificatePrivateKeyPair mRootCertificate;
-    private static volatile CertificateIssuerConfig mInstance;
-
-    private CertificateIssuerConfig(){
-        readConfig();
-    }
-
-    public static CertificateIssuerConfig getInstance() {
-        if(mInstance == null) {
-            synchronized (CertificateIssuerConfig.class) {
-                if(mInstance == null) {
-                    mInstance = new CertificateIssuerConfig();
-                }
-            }
-        }
-        return mInstance;
-    }
-
-    private void readConfig() {
-        //TODO read from config db
-        mSerial =  BigInteger.valueOf(0);
-        String issuer = new String("uuid:31313131-3131-3131-3131-313131313131");
-        CertificateBuilder rootBuilder = new CertificateBuilder(issuer, getNotBeforeDate(),
-                getNotAfterDate(), getNextSerialNumber());
-        rootBuilder.setSubjectC("Uk");
-        rootBuilder.setSubjectO("Samsung");
-        rootBuilder.setSubjectOU("OCF Root CA");
-
-        try {
-            mRootCertificate =  rootBuilder.build();
-        } catch (Exception e) {
-        }
-    }
-
-    public BigInteger getNextSerialNumber() {
-        mSerial = mSerial.add(BigInteger.ONE);
-        return mSerial;
-    }
-
-    public Date getNotBeforeDate() {
-        return new Date(System.currentTimeMillis() - 50000);
-    }
-
-    public Date getNotAfterDate() {
-        String string = "January 2, 2017";
-        DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
-        Date notAfter = null;
-        try {
-            notAfter = format.parse(string);
-        } catch (ParseException e) {
-            e.printStackTrace();
-        }
-        return notAfter;
-    }
-
-    public CertificatePrivateKeyPair getRootCertificate() {
-        return mRootCertificate;
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificatePrivateKeyPair.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificatePrivateKeyPair.java
deleted file mode 100644 (file)
index 82ff1f1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * //******************************************************************
- * //
- * // Copyright 2016 Samsung Electronics All Rights Reserved.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- * //
- * // 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.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- */
-package org.iotivity.cloud.accountserver.x509.cert;
-
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-public class CertificatePrivateKeyPair {
-    private X509Certificate mCertificate = null;
-    private PrivateKey mKey = null;
-
-    public CertificatePrivateKeyPair(X509Certificate cert, PrivateKey k) {
-        mCertificate = cert;
-        mKey = k;
-    }
-
-    public X509Certificate getCertificate() {
-        return mCertificate;
-    }
-
-    public PrivateKey getKey() {
-        return mKey;
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/Utility.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/Utility.java
new file mode 100644 (file)
index 0000000..d2cce57
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.x509.cert;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameBuilder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import static org.bouncycastle.asn1.x500.style.BCStyle.*;
+import static org.iotivity.cloud.accountserver.Constants.*;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.ACCOUNT_DB_MANAGER;
+
+/**
+ * Utility class is for getting X500Name from common name, country, organization and organization unit name
+ */
+public final class Utility {
+
+    /**
+     * Forbid creation of new Utility object. This class is final
+     * and non-instantiable
+     */
+    private Utility() {
+        throw new AssertionError();
+    }
+
+    /**
+     * Returns X500Name contructed with help of specified parameters commonName, country, organizational
+     * and organizationUnit
+     */
+    public static X500Name getName(String commonName, String country, String organizational, String organizationUnit) {
+        X500NameBuilder nameBuilder = new X500NameBuilder(INSTANCE);
+        nameBuilder.addRDN(CN, commonName);
+        nameBuilder.addRDN(C, country);
+        nameBuilder.addRDN(O, organizational);
+        nameBuilder.addRDN(OU, organizationUnit);
+        return nameBuilder.build();
+    }
+
+    /**
+     * Retrieves user id from Token Table by specified deviceId.
+     */
+    public static String getUserID(String deviceId) {
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(KEYFIELD_DID, deviceId);
+        ArrayList<HashMap<String, Object>> recordList = ACCOUNT_DB_MANAGER.selectRecord(TOKEN_TABLE, condition);
+        Iterator<HashMap<String, Object>> iterator = recordList.iterator();
+        String result = null;
+        if (iterator.hasNext()) {
+            result = iterator.next().get(KEYFIELD_UUID).toString();
+        }
+        return result;
+    }
+
+
+}
index c02c85f..6e4df99 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.crl;
 
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.Date;
 
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.cert.X509CRLHolder;
 import org.bouncycastle.cert.X509v2CRLBuilder;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
 
-public final class CrlIssuer {
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509CRLEntry;
+import java.util.Collection;
+import java.util.Date;
 
-    private static final String BC                = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
-    private static final String SIGNING_ALGORITHM = "SHA256withECDSA";
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.CA_ISSUER;
 
+/**
+ * Class is used for generating CRL with specified parameters.
+ */
+public final class CrlIssuer {
+    /**
+     * Creates static final reference for CRL issuer.
+     */
+    public static final CrlIssuer CRL_ISSUER = new CrlIssuer();
+
+    /**
+     * Creates new instance of CRL issuer.
+     */
     private CrlIssuer() {
-        throw new AssertionError();// to get rid of security issue, connected
-                                   // with Java Reflection API
     }
 
-    static {
-        Security.insertProviderAt(new BouncyCastleProvider(), 1);
-    }
-
-    public static byte[] generateCrl(String issuerName, Date thisUpdate,
-            CrlInfo[] items, byte[] issuerPrivateKey) throws Exception {
-
-        X500Name issuerDN = new X500Name(issuerName);
-        X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(issuerDN,
+    /**
+     * Generates new CRL with specified this update, next update, certs and serial numbers list.
+     */
+    public byte[] generate(Date thisUpdate, Date nextUpdate, Collection<? extends X509CRLEntry> certs,
+                           String... serialNumbers) throws IOException, OperatorCreationException {
+        byte[] crl;
+        X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(CA_ISSUER,
                 thisUpdate);
-
-        for (CrlInfo item : items) {
-            crlBuilder.addCRLEntry(item.getSerialNumber(),
-                    item.getRevocationDate(), 0);
-        }
-
-        KeyFactory kf = KeyFactory.getInstance("ECDSA");
-        PrivateKey privateKey = kf
-                .generatePrivate(new PKCS8EncodedKeySpec(issuerPrivateKey));
-
-        // build and sign CRL with CA private key
-        ContentSigner signer = new JcaContentSignerBuilder(SIGNING_ALGORITHM)
-                .setProvider(BC).build(privateKey);
-        X509CRLHolder crl = crlBuilder.build(signer);
-
-        byte data[] = crl.getEncoded();
-        CrlStore.saveCrl(data);
-
-        return data;
-    }
-
-    public static byte[] getCrl() throws Exception {
-        return CrlStore.loadCrl();
-    }
-
-    public static void main(String[] args) {
-        System.out.println("Start!");
-
-        /* generate dummy crl items */
-        CrlInfo[] items = new CrlInfo[2];
-        int val = 1024;
-        for (int i = 0; i < items.length; i++) {
-            items[i] = new CrlInfo();
-            items[i].setSerialNumber(BigInteger.valueOf(val++));
-            items[i].setRevocationDate(new Date());
-        }
-
-        ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime192v1");
-        try {
-            KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
-            g.initialize(ecGenSpec, new SecureRandom());
-            KeyPair pair = g.generateKeyPair();
-
-            PrivateKey key = pair.getPrivate();
-            byte[] crl = generateCrl("C=DE,O=Samsung", new Date(), items,
-                    key.getEncoded());
-
-            System.out.println("Success!");
-            System.out.println("Stored CRL = " + getHex(crl));
-        } catch (java.lang.Exception e) {
-            e.printStackTrace();
-        }
-        System.out.println("End!");
-    }
-
-    static final String HEXES = "0123456789ABCDEF";
-
-    public static String getHex(byte[] raw) {
-        if (raw == null) {
-            return null;
+        crlBuilder.setNextUpdate(nextUpdate);
+        if (certs != null) {
+            for (X509CRLEntry entryHolder : certs) {
+                crlBuilder.addCRLEntry(entryHolder.getSerialNumber(), entryHolder.getRevocationDate(), 0);
+            }
         }
-        final StringBuilder hex = new StringBuilder(2 * raw.length);
-        for (final byte b : raw) {
-            hex.append(HEXES.charAt((b & 0xF0) >> 4))
-                    .append(HEXES.charAt((b & 0x0F)));
+        for (String serialNumber : serialNumbers) {
+            crlBuilder.addCRLEntry(new BigInteger(serialNumber), new Date(), 0);
         }
-        return hex.toString();
+        crl = crlBuilder.build(CertificateBuilder.SIGNER_BUILDER.
+                build(CertificateStorage.ROOT_PRIVATE_KEY)).getEncoded();
+        return crl;
     }
-}
+}
\ No newline at end of file
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlStore.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlStore.java
deleted file mode 100644 (file)
index 19b606a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * //******************************************************************
- * //
- * // Copyright 2016 Samsung Electronics All Rights Reserved.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- * //
- * // 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.
- * //
- * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- */
-package org.iotivity.cloud.accountserver.x509.crl;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public final class CrlStore {
-
-    private CrlStore() {
-        throw new AssertionError(); // to get rid of security issue, connected
-                                    // with Java Reflection API
-    }
-
-    private static final String CRL_FILE_NAME = "crl";
-
-    public static void saveCrl(byte[] crl) {
-
-        FileOutputStream out = null;
-        try {
-            out = new FileOutputStream(CRL_FILE_NAME);
-            out.write(crl);
-        } catch (java.io.IOException e) {
-            e.printStackTrace();
-        }
-
-        try {
-            if (out != null)
-                out.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    public static byte[] loadCrl() {
-
-        InputStream f = null;
-        try {
-            f = new FileInputStream(CRL_FILE_NAME);
-            int size = f.available();
-            byte data[] = new byte[size];
-
-            if (f.read(data) != data.length) {
-                System.err.println("couldn't read crl");
-            }
-            f.close();
-            return data;
-
-        } catch (java.io.IOException e) {
-            e.printStackTrace();
-        }
-
-        try {
-            if (f != null)
-                f.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-}
index d5382f7..3dedb79 100644 (file)
@@ -60,7 +60,7 @@ public class AccountResourceTest {
     private static final String            GROUP_URI                 = Constants.GROUP_FULL_URI;
     private static final String            DEVICE_ID                 = "B371C481-38E6-4D47-8320-7688D8A5B58C";
     private String                         mAuthProvider             = "Github";
-    private String                         mAuthCode                 = "c2820e39232088dca7d4";
+    private String                         mAuthCode                 = "00a93f698b47980b2d77";
     private CoapDevice                     mMockDevice               = mock(
             CoapDevice.class);
     private Cbor<HashMap<String, Object>>  mCbor                     = new Cbor<>();
diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java
new file mode 100644 (file)
index 0000000..62bdca5
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.account.credprov.cert;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.db.TokenTable;
+import org.iotivity.cloud.accountserver.resources.account.credprov.crl.CrlResourceTest;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
+import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlResource;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.accountserver.x509.cert.Utility;
+import org.iotivity.cloud.base.OICConstants;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.enums.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.RequestMethod;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.util.Cbor;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.cert.*;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+public class CertificateResourceTest {
+
+    private static final String COMMON_NAME = "OU=OCF Device CA, O=Samsung, C=KR, CN=uuid:B371C481-38E6-4D47-8320-7688D8A5B58C";
+
+    private static final String CERTIFICATE_URI = OICConstants.CREDPROV_CERT_FULL_URI;
+
+    private static final String DEVICE_ID = "B371C481-38E6-4D47-8320-7688D8A5B58C";
+
+    private CoapDevice mMockDevice = mock(CoapDevice.class);
+
+    private Cbor<HashMap<String, Object>> mCbor = new Cbor<>();
+
+    private IResponse mResponse = null;
+
+    private CountDownLatch mLatch = new CountDownLatch(
+            1);
+
+    private static CertificateResource certificateResource = new CertificateResource();
+
+    private byte[] csr;
+
+    private static TypeCastingManager<TokenTable> castingManager = new TypeCastingManager<>();
+
+    static void createToken() {
+        TokenTable certificateTable = new TokenTable();
+        certificateTable.setDid(DEVICE_ID);
+        certificateTable.setUuid("uuid:" + DEVICE_ID);
+        AccountDBManager.getInstance().insertRecord(Constants.TOKEN_TABLE,
+                castingManager.convertObjectToMap(certificateTable));
+    }
+
+    @AfterClass
+    public static void after() {
+        KEYSTORE_FILE.delete();
+    }
+
+    @BeforeClass
+    public static void setUpBefore() {
+        createToken();
+    }
+
+    /**
+     * DERSequence othernameSequence = new DERSequence(new ASN1Encodable[]{
+     * new ASN1ObjectIdentifier("1.3.6.1.5.5.7.8.5"), new DERTaggedObject(true, 0, new DERUTF8String(subjectAltName))});
+     * GeneralName othernameGN = new GeneralName(GeneralName.otherName, othernameSequence);
+     * ASN1Encodable[] subjectAlternativeNames = new ASN1Encodable[]
+     * {
+     * othernameGN
+     * <p>
+     * <p>
+     * };
+     * DERSequence subjectAlternativeNamesExtension = new DERSequence(othernameGN);
+     * return buildOne(Extension.subjectAlternativeName, true, subjectAlternativeNamesExtension, issuerNameBld.build());
+     */
+    @Test
+    public void testLoad() {
+        try {
+            Method m = CertificateStorage.class.getDeclaredMethod("load");
+            m.setAccessible(true);
+            m.invoke(null);
+        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        csr = GenerateCSR.generatePKCS10(COMMON_NAME, false);
+        MockitoAnnotations.initMocks(this);
+        // callback mock
+        Mockito.doAnswer(new Answer<Object>() {
+            @Override
+            public CoapResponse answer(InvocationOnMock invocation)
+                    throws Throwable {
+                Object[] args = invocation.getArguments();
+                CoapResponse resp = (CoapResponse) args[0];
+                mResponse = resp;
+
+
+                mLatch.countDown();
+                return null;
+            }
+        }).when(mMockDevice).sendResponse(Mockito.anyObject());
+    }
+
+    @Test(expected = AssertionError.class)
+    public void testErrorConstruction() {
+        Constructor<CertificateStorage> constructor;
+        try {
+            constructor = CertificateStorage.class.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            constructor.newInstance();
+        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            throw new AssertionError();
+        }
+
+    }
+
+    @Test(expected = AssertionError.class)
+    public void testErrorConstructionUtility() {
+        Constructor<Utility> constructor;
+        try {
+            constructor = Utility.class.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            constructor.newInstance();
+        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            throw new AssertionError();
+        }
+    }
+
+    @Test(expected = AssertionError.class)
+    public void testErrorConstructionCertificateConstants() {
+        Constructor<CertificateConstants> constructor;
+        try {
+            constructor = CertificateConstants.class.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            constructor.newInstance();
+        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            throw new AssertionError();
+        }
+
+    }
+
+    /**
+     * DERUTF8String derDomainName = new DERUTF8String("hello.world");
+     * DERTaggedObject derTaggedDomainName = new DERTaggedObject(0, derDomainName);
+     * DLSequence otherName = new DLSequence(new ASN1Encodable[]{new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.3"), derTaggedDomainName});
+     * GeneralNames generalNames = new GeneralNames(new GeneralName(GeneralName.otherName, otherName));
+     *
+     * @throws Exception
+     */
+
+    @Test
+    public void testCSRIssueDER() throws Exception {
+        getTestMethodName();
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        Map<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
+        assertTrue(hashmapCheck(mResponse, Constants.REQ_DEVICE_ID));
+        assertTrue(hashmapCheck(mResponse, Constants.CERT));
+        assertTrue(hashmapCheck(mResponse, Constants.CERT_CHAIN));
+        Map<String, Object> certMap = (Map<String, Object>) payloadData.get(Constants.CERT);
+        InputStream in = new ByteArrayInputStream((byte[]) certMap.get(Constants.DATA));
+        X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in);
+        personaleCert.verify(CertificateStorage.ROOT_CERTIFICATE.getPublicKey());
+        assertEquals(COMMON_NAME, personaleCert.getSubjectDN().getName());
+        String encoding = certMap.get(Constants.ENCODING).toString();
+        assertEquals(CertificateConstants.DER, encoding);
+        assertEquals(personaleCert.getPublicKey(), GenerateCSR.getPublicKey());
+        certMap = (Map<String, Object>) payloadData.get(Constants.CERT_CHAIN);
+        encoding = certMap.get(Constants.ENCODING).toString();
+        assertEquals(CertificateConstants.DER, encoding);
+        in = new ByteArrayInputStream((byte[]) certMap.get(Constants.DATA));
+        X509Certificate caCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in);
+        assertEquals(caCert, CertificateStorage.ROOT_CERTIFICATE);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+    }
+
+    @Test
+    public void testCSRIssueDERFailed() throws Exception {
+        getTestMethodName();
+        IRequest request = csrRequestFailed(DEVICE_ID, RequestMethod.POST);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST));
+    }
+
+    @Test
+    public void testCSRIssueDERFailedSignature() throws Exception {
+        byte[] csr = GenerateCSR.generatePKCS10(COMMON_NAME, true);
+        getTestMethodName();
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST));
+    }
+
+    Map<String, Object> payloadData;
+
+    Map<String, Object> crlMap;
+
+    byte[] data;
+
+    X509CRL crlX509;
+
+    @Test
+    public void testReIssueBase64() throws CRLException, CertificateException {
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+
+        Map<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
+        List<BigInteger> serialNumbers = new ArrayList<>();
+        Map<String, Object> certMap = (Map<String, Object>) payloadData.get(Constants.CERT);
+        InputStream in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA)));
+        X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in);
+        serialNumbers.add(personaleCert.getSerialNumber());
+        serialNumbers.add(personaleCert.getSerialNumber().subtract(BigInteger.ONE));
+
+        request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        payloadData = mCbor
+                .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
+        certMap = (Map<String, Object>) payloadData.get(Constants.CERT);
+        in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA)));
+        personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in);
+        serialNumbers.add(personaleCert.getSerialNumber());
+
+
+        request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        getTestMethodName();
+        request = CrlResourceTest.crlRequest(RequestMethod.GET, CrlResourceTest.CRL_URI, CrlResourceTest.CRL_URI_QUERY);
+        CrlResource crlResource = new CrlResource();
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        hashmapCheck(mResponse, Constants.ENCODING);
+        hashmapCheck(mResponse, Constants.DATA);
+        if (mResponse.getPayload() != null) {
+            payloadData = mCbor
+                    .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
+            crlMap = (Map<String, Object>) payloadData.get(Constants.REQ_CRL);
+            data = (byte[]) crlMap.get(Constants.DATA);
+            crlX509 = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data));
+        }
+
+        assertEquals(DER, crlMap.get(Constants.ENCODING));
+        assertNotNull(data);
+        Set<? extends X509CRLEntry> entries = crlX509.getRevokedCertificates();
+        Iterator<? extends X509CRLEntry> iterator = entries.iterator();
+        while (iterator.hasNext()) {
+            assertTrue(serialNumbers.contains(iterator.next().getSerialNumber()));
+        }
+    }
+
+    @Test
+    public void testMethodNotAllowed() {
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.GET, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.METHOD_NOT_ALLOWED));
+    }
+
+    @Test
+    public void testBadRequest() {
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, false);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST));
+    }
+
+
+    @Test
+    public void testBadData() {
+        IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, null, RequestMethod.POST, true);
+        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST));
+    }
+
+
+    private void getTestMethodName() {
+        StackTraceElement[] stacks = new Throwable().getStackTrace();
+        StackTraceElement currentStack = stacks[1];
+        System.out.println("\t---Test Name : " + currentStack.getMethodName());
+    }
+
+    private IRequest csrRequestFailed(String deviceId, RequestMethod method) {
+        IRequest request;
+        HashMap<String, Object> payloadData = new HashMap<>();
+        payloadData.put(Constants.REQ_DEVICE_ID, deviceId);
+        payloadData.put("csr", "csr");
+        request = MessageBuilder.createRequest(method, CERTIFICATE_URI,
+                null, ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+        return request;
+    }
+
+    private IRequest csrRequest(String deviceId, String encoding, byte[] data, RequestMethod method, boolean isEncoded) {
+        IRequest request;
+        HashMap<String, Object> payloadData = new HashMap<>();
+        payloadData.put(Constants.REQ_DEVICE_ID, deviceId);
+        CSR csr = new CSR();
+        if (isEncoded) {
+            csr.setEncoding(encoding);
+            csr.setData(data);
+            payloadData.put("csr", csr);
+        }
+        request = MessageBuilder.createRequest(method, CERTIFICATE_URI,
+                null, ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+        return request;
+    }
+
+    private static class CSR {
+        String encoding;
+
+        byte[] data;
+
+        public String getEncoding() {
+            return encoding;
+        }
+
+        public void setEncoding(String encoding) {
+            this.encoding = encoding;
+        }
+
+        public byte[] getData() {
+            return data;
+        }
+
+        public void setData(byte[] data) {
+            this.data = data;
+        }
+
+        @Override
+        public String toString() {
+            return "CSR{" +
+                    "encoding='" + encoding + '\'' +
+                    ", data=" + Arrays.toString(data) +
+                    '}';
+        }
+    }
+
+    private boolean methodCheck(IResponse response,
+                                ResponseStatus responseStatus) {
+        if (responseStatus == response.getStatus())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean hashmapCheck(IResponse response, String propertyName) {
+        HashMap<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(response.getPayload(), HashMap.class);
+        if (payloadData.containsKey(propertyName))
+            return true;
+        else
+            return false;
+    }
+
+}
diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/GenerateCSR.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/GenerateCSR.java
new file mode 100644 (file)
index 0000000..600bbc6
--- /dev/null
@@ -0,0 +1,63 @@
+package org.iotivity.cloud.accountserver.resources.account.credprov.cert;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants;
+
+import javax.security.auth.x500.X500Principal;
+import java.security.*;
+
+public class GenerateCSR {
+
+    public static final String SIGNATURE_ALGORITHM = CertificateConstants.PROPERTIES.getProperty("signatureAlgorithm");
+
+    private static final String CURVE = CertificateConstants.PROPERTIES.getProperty("ellipticCurve");
+
+    private static final String KEY_GENERATOR_ALGORITHM = CertificateConstants.PROPERTIES.getProperty("keyGeneratorAlgorithm");
+
+    private static PublicKey publicKey = null;
+    private static PrivateKey privateKey = null;
+    private static PublicKey publicKey1 = null;
+    private static PrivateKey privateKey1= null;
+    private static KeyPairGenerator keyGen = null;
+    private static GenerateCSR gcsr = null;
+
+    /**
+     * @return
+     * @throws Exception
+     */
+    public static byte[] generatePKCS10(String commonName, boolean falseKey) throws Exception {
+        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
+        KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, CertificateConstants.SECURITY_PROVIDER);
+        g.initialize(ecSpec, new SecureRandom());
+        KeyPair pair = g.generateKeyPair();
+        privateKey = pair.getPrivate();
+        publicKey = pair.getPublic();
+        pair = g.generateKeyPair();
+        privateKey1 = pair.getPrivate();
+        publicKey1 = pair.getPublic();
+        PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
+                new X500Principal(commonName), publicKey);
+        JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM);
+        ContentSigner signer;
+        if (falseKey) {
+            signer = csBuilder.build(privateKey1);
+        } else {
+            signer = csBuilder.build(privateKey);
+        }
+
+        PKCS10CertificationRequest csr = p10Builder.build(signer);
+        return csr.getEncoded();
+    }
+    public static PublicKey getPublicKey() {
+        return publicKey;
+    }
+
+}
\ No newline at end of file
diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java
new file mode 100644 (file)
index 0000000..1afb0ef
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // 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.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources.account.credprov.crl;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.encoders.Base64;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.db.CRLTable;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
+import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlManager;
+import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlResource;
+import org.iotivity.cloud.accountserver.util.TypeCastingManager;
+import org.iotivity.cloud.accountserver.x509.crl.CrlIssuer;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.enums.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.RequestMethod;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.util.Cbor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLEntry;
+import java.text.ParseException;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+
+public class CrlResourceTest {
+
+    private CoapDevice mMockDevice = mock(CoapDevice.class);
+    private Cbor<Map<String, Object>> mCbor = new Cbor<>();
+    private IResponse mResponse = null;
+    private CountDownLatch mLatch = new CountDownLatch(
+            1);
+    public static final String[] FOR_SERIAL_NUMBER = {Constants.REQ_THIS_UPDATE, Constants.REQ_NEXT_UPDATE, Constants.REQ_SERIAL_NUMBER};
+    public static final String CRL_URI = Constants.PREFIX_OIC + "/" + Constants.CREDPROV_URI + "/" +
+            Constants.REQ_CRL;
+    public static final String CRL_URI_QUERY = "lu=20160726210000";
+    public static final String CRL_URI_QUERY_CONDITION_FALSE = "lu=21160726210000";
+    public static final String CRL_URI_QUERY_PARSE_ERROR = "lu=1231212asdzfg4123123123123123";
+    public static final String[] FOR_FULL_CRL = {Constants.REQ_THIS_UPDATE, Constants.REQ_NEXT_UPDATE, Constants.REQ_CRL};
+    public static final PublicKey key = CertificateStorage.ROOT_CERTIFICATE.getPublicKey();
+
+    private static TypeCastingManager<CRLTable> castingManager = new TypeCastingManager<>();
+
+    static {
+        Security.insertProviderAt(new BouncyCastleProvider(), 0);
+        new CertificateResource();
+    }
+
+    /**
+     * Serial number of last issued certificate.
+     */
+    private static BigInteger SERIAL_NUMBER = new BigInteger(PROPERTIES.getProperty("serialNumber"));
+
+    Map<String, Object> payloadData;
+
+    Map<String, Object> crlMap;
+
+    byte[] data;
+
+    X509CRL crlX509;
+
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doAnswer(new Answer<Object>() {
+            @Override
+            public CoapResponse answer(InvocationOnMock invocation)
+                    throws Throwable {
+                Object[] args = invocation.getArguments();
+                CoapResponse resp = (CoapResponse) args[0];
+                mResponse = resp;
+                if (mResponse.getPayload() != null) {
+                    payloadData = mCbor
+                            .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
+                    crlMap = (Map<String, Object>) payloadData.get(Constants.REQ_CRL);
+                    data = (byte[]) crlMap.get(Constants.DATA);
+                    CertificateFactory factory = CertificateFactory.getInstance("X509");
+                    crlX509 = (X509CRL) factory.generateCRL(new ByteArrayInputStream(data));
+                }
+
+                mLatch.countDown();
+                return null;
+            }
+        }).when(mMockDevice).sendResponse(Mockito.anyObject());
+    }
+
+
+    CRLTable getCRLTime() {
+
+        List<HashMap<String, Object>> listMap = AccountDBManager.getInstance().selectRecord(
+                Constants.CRL_TABLE, new HashMap<>());
+        if (!listMap.isEmpty()) {
+            return castingManager
+                    .convertMaptoObject(
+                            listMap.get(0),
+                            new CRLTable());
+        } else {
+            return null;
+        }
+    }
+
+    private CrlResource crlResource = new CrlResource();
+
+    /**
+     * Returns next serial number.
+     */
+    private static BigInteger getNextSerialNumber() {
+        SERIAL_NUMBER = SERIAL_NUMBER.add(BigInteger.ONE);
+        set("serialNumber", SERIAL_NUMBER.toString());
+        return SERIAL_NUMBER;
+    }
+
+    @Test
+    public void testCrlGetContent() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        hashmapCheck(mResponse, Constants.ENCODING);
+        hashmapCheck(mResponse, Constants.DATA);
+        assertEquals(DER, crlMap.get(Constants.ENCODING));
+        assertNotNull(data);
+        crlX509.verify(key);
+    }
+
+    @Test
+    public void testCrlGetNotFoundLastUpdateConditionFalse() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY_CONDITION_FALSE);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND));
+    }
+
+    @Test
+    public void testCrlGetNotFoundNullPointer() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, null);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND));
+    }
+
+    @Test
+    public void testCrlGetNotFoundParseError() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY_PARSE_ERROR);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND));
+    }
+
+    @Test(expected = InvocationTargetException.class)
+    public void testNullX509CRL() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        Method m = null;
+        m = CrlManager.class.getDeclaredMethod("setX509CRL", byte[].class);
+        m.setAccessible(true);
+        System.out.println(m);
+        m.invoke(CrlManager.CRL_MANAGER, "Hello".getBytes());
+    }
+
+    @Test
+    public void testX509CRL() {
+        Field field;
+        Method m;
+        try {
+            IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+            crlResource.onDefaultRequestReceived(mMockDevice, request);
+            assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+            field = CrlManager.class.getDeclaredField("x509CRL");
+            field.setAccessible(true);
+            Object value = field.get(CrlManager.CRL_MANAGER);
+            field.set(CrlManager.CRL_MANAGER, null);
+            request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+            crlResource.onDefaultRequestReceived(mMockDevice, request);
+            assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND));
+            m = CrlManager.class.getDeclaredMethod("getPayload");
+            m.setAccessible(true);
+            field.set(CrlManager.CRL_MANAGER, null);
+            Object o = m.invoke(CrlManager.CRL_MANAGER);
+            assertEquals(Collections.EMPTY_MAP, o);
+            field.set(CrlManager.CRL_MANAGER, value);
+        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testCrlPreconditionFailedException() throws ParseException, IOException, OperatorCreationException {
+        getTestMethodName();
+        getTestMethodName();
+        String thisUpdate = "20160823000000";
+        String nextUpdate = "20161123000000";
+        byte[] crl = CrlIssuer.CRL_ISSUER.generate(DATE_FORMAT.parse(thisUpdate),
+                DATE_FORMAT.parse(nextUpdate), Collections.emptyList());
+        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, Base64.encode(Arrays.copyOf(crl, crl.length - 2)), BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+        crl = new byte[8];
+        request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, Base64.encode(crl), BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+        crl = new byte[8];
+        request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, crl, BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostSerialNumberFailedData() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        String thisUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getThisUpdate());
+        String nextUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getNextUpdate());
+        String next = getNextSerialNumber().subtract(BigInteger.valueOf(3l)).toString();
+        String[] serialNUmber = new String[]{"123456", "1234", "12312", next};
+        request = crlRequestFailedCRL(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostSerialNumber() throws Exception {
+        getTestMethodName();
+        testCrlPostEncodingBase64();
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        String thisUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getThisUpdate());
+        String nextUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getNextUpdate());
+        String next = getNextSerialNumber().subtract(BigInteger.valueOf(3l)).toString();
+        String nextNext = getNextSerialNumber().subtract(BigInteger.valueOf(3l)).toString();
+
+        String[] serialNUmber = new String[]{"123456", "1234", "12312", next, nextNext};
+        request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        serialNUmber = new String[]{"12345612312", "12341231", "12312231"};
+        request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        serialNUmber = new String[]{"12345612312", "12341231", "12312231", "123456", "1234", "12312", next, nextNext};
+        request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        assertEquals(DER, crlMap.get(Constants.ENCODING));
+        Set<? extends X509CRLEntry> entries = crlX509.getRevokedCertificates();
+        Iterator<? extends X509CRLEntry> iterator = entries.iterator();
+
+        while (iterator.hasNext()) {
+            assertTrue(Arrays.asList(serialNUmber).contains(iterator.next().getSerialNumber().toString()));
+        }
+        CRLTable table = getCRLTime();
+        assertEquals(DATE_FORMAT.format(table.getThisUpdate()), thisUpdate);
+
+    }
+
+    @Test
+    public void testSerialNumberNull() {
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        String thisUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getThisUpdate());
+        String nextUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getNextUpdate());
+        String[] serialNUmber = null;
+        request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlUnParseableDate() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "l;dkfjg;ls";
+        String nextUpdate = "sdfgsdfg";
+        String[] serialNUmber = new String[]{"123456"};
+        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostNullDate() throws Exception {
+        getTestMethodName();
+        String thisUpdate = null;
+        String nextUpdate = null;
+        String[] serialNUmber = new String[]{"123456"};
+        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+    }
+
+
+    @Test
+    public void testCrlPostEncodingBase64() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "20160831000000";
+        String nextUpdate = "20161123000000";
+        byte[] crl = CrlIssuer.CRL_ISSUER.generate(DATE_FORMAT.parse(thisUpdate),
+                DATE_FORMAT.parse(nextUpdate), Collections.emptyList());
+        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, Base64.encode(crl), BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        assertEquals(DER, crlMap.get(Constants.ENCODING));
+    }
+
+    @Test
+    public void testCrlPostEncodingBase64FailedCRL() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "20160831000000";
+        String nextUpdate = "20161123000000";
+        IRequest request = crlRequestFailedCRL(RequestMethod.POST, thisUpdate, nextUpdate, BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostEncodingBase64FailedDate() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "20160831000000";
+        String nextUpdate = "20161123000000";
+        byte[] crl = CrlIssuer.CRL_ISSUER.generate(DATE_FORMAT.parse(thisUpdate),
+                DATE_FORMAT.parse(nextUpdate), Collections.emptyList());
+        IRequest request = crlRequestFailedDate(RequestMethod.POST, thisUpdate, nextUpdate, BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostEncodingBase64FailedPayload() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "20160831000000";
+        String nextUpdate = "20161123000000";
+        byte[] crl = CrlIssuer.CRL_ISSUER.generate(DATE_FORMAT.parse(thisUpdate),
+                DATE_FORMAT.parse(nextUpdate), Collections.emptyList());
+        IRequest request = crlRequestFailedPayload(RequestMethod.POST, BASE_64);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
+    }
+
+    @Test
+    public void testCrlPostEncodingDER() throws Exception {
+        getTestMethodName();
+        String thisUpdate = "20160831000000";
+        String nextUpdate = "20161123000000";
+        byte[] crl = CrlIssuer.CRL_ISSUER.generate(DATE_FORMAT.parse(thisUpdate),
+                DATE_FORMAT.parse(nextUpdate), Collections.emptyList());
+        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, crl, DER);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED));
+        request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT));
+        assertEquals(DER, crlMap.get(Constants.ENCODING));
+        assertTrue(Arrays.equals(crl, data));
+        assertTrue(Arrays.equals(crl, crlX509.getEncoded()));
+    }
+
+    @Test
+    public void testCrlBadRequest() throws Exception {
+        getTestMethodName();
+        IRequest request = crlRequest(RequestMethod.PUT, CRL_URI, null);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(mResponse.getStatus().equals(ResponseStatus.BAD_REQUEST));
+    }
+
+    public static IRequest crlRequest(RequestMethod method, String uri, String query) {
+        IRequest request = MessageBuilder.createRequest(method, uri, query);
+        return request;
+    }
+
+    private IRequest crlRequestSN(RequestMethod method, String[] keys, Object[] values) {
+        HashMap<String, Object> payloadData = new HashMap<>();
+        for (int i = 0; i < keys.length; i++) {
+            payloadData.put(keys[i], values[i]);
+        }
+        IRequest request = MessageBuilder.createRequest(method, CRL_URI,
+                null, ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+        return request;
+    }
+
+    private IRequest crlRequestFull(RequestMethod method, String[] keys, Object[] values, String encoding) {
+        HashMap<String, Object> payloadData = new HashMap<>();
+        if (keys.length != 0 && values.length != 0) {
+            for (int i = 0; i < keys.length - 1; i++) {
+                payloadData.put(keys[i], values[i]);
+            }
+            Object value = values[values.length - 1];
+            if (value instanceof byte[]) {
+                payloadData.put(keys[keys.length - 1], new CRL(encoding, (byte[]) value));
+            } else {
+                payloadData.put(keys[keys.length - 1], value);
+            }
+
+        }
+        IRequest request = MessageBuilder.createRequest(method, CRL_URI,
+                null, ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+        return request;
+    }
+
+
+    private IRequest crlRequest(RequestMethod method, String thisUpdate, String nextUpdate, String[] rcsn) {
+        return crlRequestSN(method, FOR_SERIAL_NUMBER, new Object[]{thisUpdate, nextUpdate, rcsn});
+    }
+
+    private IRequest crlRequestFailedCRL(RequestMethod method, String thisUpdate, String nextUpdate, String[] rcsn) {
+        return crlRequestSN(method, FOR_SERIAL_NUMBER, new Object[]{thisUpdate, nextUpdate, rcsn.length});
+    }
+
+    private IRequest crlRequest(RequestMethod method, String thisUpdate, String nextUpdate, byte[] crl, String encoding) {
+        return crlRequestFull(method, FOR_FULL_CRL, new Object[]{thisUpdate, nextUpdate, crl}, encoding);
+    }
+
+    private IRequest crlRequestFailedCRL(RequestMethod method, String thisUpdate, String nextUpdate,
+                                         String encoding) {
+        return crlRequestFull(method, FOR_FULL_CRL, new Object[]{thisUpdate, nextUpdate, thisUpdate}, encoding);
+    }
+
+    private IRequest crlRequestFailedDate(RequestMethod method, String thisUpdate, String nextUpdate,
+                                          String encoding) {
+        return crlRequestFull(method, FOR_FULL_CRL, new Object[]{thisUpdate.getBytes(), nextUpdate, thisUpdate}, encoding);
+    }
+
+    private IRequest crlRequestFailedPayload(RequestMethod method, String encoding) {
+        return crlRequestFull(method, new String[]{}, new Object[]{}, encoding);
+    }
+
+    private static final class CRL {
+
+        private final String encoding;
+
+        private final byte[] data;
+
+        public CRL(String encoding, byte[] data) {
+            this.encoding = encoding;
+            this.data = data;
+        }
+
+        @Override
+        public String toString() {
+            return "CRL{" +
+                    "encoding='" + encoding + '\'' +
+                    ", data=" + Arrays.toString(data) +
+                    '}';
+        }
+
+        public String getEncoding() {
+            return encoding;
+        }
+
+        public byte[] getData() {
+            return data;
+        }
+    }
+
+
+    private void getTestMethodName() {
+        StackTraceElement[] stacks = new Throwable().getStackTrace();
+        StackTraceElement currentStack = stacks[1];
+        System.out.println("\t---Test Name : " + currentStack.getMethodName());
+    }
+
+    private boolean methodCheck(IResponse response,
+                                ResponseStatus responseStatus) {
+        if (responseStatus == response.getStatus())
+            return true;
+        else
+            return false;
+    }
+
+    private boolean hashmapCheck(IResponse response, String propertyName) {
+        Map<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(response.getPayload(), HashMap.class);
+        if (payloadData.containsKey(propertyName))
+            return true;
+        else
+            return false;
+    }
+}
index 59b8938..a76151d 100755 (executable)
@@ -120,4 +120,7 @@ public class OICConstants {
 
     public static final String DEVICE_PRESENCE_FULL_URI      = "/"
             + OICConstants.PREFIX_OIC + "/" + OICConstants.DEVICE_PRESENCE_URI;
+
+    public static final String CREDPROV_CERT_FULL_URI        = "/" + PREFIX_OIC
+            + "/" + CREDPROV_URI + "/" + CERT_URI;
 }