Unit test development.
authorAndrii Androsov <a.androsov@samsung.com>
Wed, 7 Sep 2016 14:21:34 +0000 (17:21 +0300)
committerJee Hyeok Kim <jihyeok13.kim@samsung.com>
Thu, 8 Sep 2016 00:31:10 +0000 (00:31 +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>
23 files changed:
cloud/account/properties/config.properties
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
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/MongoDB.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java
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/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/CrlParser.java [deleted file]
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
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/GenerateCSR.java
cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java

index 0c5a722..73d9aaa 100644 (file)
@@ -1,19 +1,17 @@
 #New Serial number
-#Thu Aug 25 11:19:40 EEST 2016
+#Wed Sep 07 17:08:34 EEST 2016
 keyGeneratorAlgorithm=ECDSA
 notAfterInterval=20
 securityProvider=BC
 ellipticCurve=secp256r1
-crlLocation=keystore{0}crl
 keyStoreLocation=keystore{0}certificateStorage.jks
-keystoreType=BKS
 nextUpdateInterval=1
 signatureAlgorithm=SHA256withECDSA
-crlCN=C\=DE,O\=Samsung
-serialNumber=223
-deviceO=Samsung
-subjectName=uuid\:31313131-3131-3131-3131-313131313131
+keystoreType=BKS
+rootOU=OCF Sub CA
+serialNumber=515
+rootO=Samsung
 caAlias=uuid\:31313131-3131-3131-3131-313131313131
-deviceOU=OCF Root CA
+subjectName=uuid\:31313131-3131-3131-3131-313131313131
 password=PASSWORD
-deviceC=UK
+rootC=KR
index 8793e43..84d4caa 100755 (executable)
  */
 package org.iotivity.cloud.accountserver;
 
-import java.io.File;
-
 import org.iotivity.cloud.base.OICConstants;
 
+import java.io.File;
+
 public class Constants extends OICConstants {
 
     public static final String PROPERTIES_FILE_NAME  = "properties"
@@ -180,21 +180,13 @@ public class Constants extends OICConstants {
 
     public static final String RESP_INVITED          = "invited";
 
-    public static final String CSR_ENCODING          = "csr.encoding";
-
-    public static final String CSR_DATA              = "csr.data";
-
-    public static final String CERT_ENCODING         = "cert.encoding";
-
-    public static final String CERT_DATA             = "cert.data";
-
-    public static final String CERTCHAIN_ENCODING    = "certchain.encoding";
+    public static final String ENCODING = "encoding";
 
-    public static final String CERTCHAIN_DATA        = "certchain.data";
+    public static final String DATA = "data";
 
-    public static final String CRL_ENCODING          = "crl.encoding";
+    public static final String CERT = "cert";
 
-    public static final String CRL_DATA              = "crl.data";
+    public static final String CERT_CHAIN = "certchain";
 
     // static token type
 
index 8e4932d..275d1bb 100644 (file)
@@ -130,6 +130,11 @@ public class AccountDBManager {
         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() {
@@ -214,7 +219,7 @@ public class AccountDBManager {
 
         if (!_updateRecord(tableName, replace))
             throw new InternalServerErrorException(
-                    "Database record update failed");
+                    "Database record updateX509CRL failed");
 
     }
 
index 049905f..aed0f8f 100644 (file)
  */
 package org.iotivity.cloud.accountserver.db;
 
+import org.bson.types.Binary;
+
 import java.util.Date;
 
 public class CRLTable {
 
     private Date thisUpdate;
 
-    public CRLTable(Date thisUpdate) {
+    private Binary binaryData;
+
+    public CRLTable() {
+    }
+
+    public CRLTable(Date thisUpdate, Binary binaryData) {
         this.thisUpdate = thisUpdate;
+        this.binaryData = binaryData;
     }
 
     public Date getThisUpdate() {
@@ -38,4 +46,20 @@ public class CRLTable {
     public void setThisUpdate(Date thisUpdate) {
         this.thisUpdate = thisUpdate;
     }
+
+    public Binary getBinaryData() {
+        return binaryData;
+    }
+
+    public void setBinaryData(Binary binaryData) {
+        this.binaryData = binaryData;
+    }
+
+    @Override
+    public String toString() {
+        return "CRLTable{" +
+                "thisUpdate=" + thisUpdate +
+                ", binaryData=" + binaryData +
+                '}';
+    }
 }
index bf18a16..a6bb542 100644 (file)
@@ -182,7 +182,7 @@ public class MongoDB {
 
         if (collection.findOneAndReplace(filter, record) == null) {
 
-            Log.w("DB update failed due to no matched record!");
+            Log.w("DB updateX509CRL failed due to no matched record!");
             return false;
         }
 
index 67b4f8f..68d6fb3 100644 (file)
+/*
+ * //******************************************************************
+ * //
+ * // 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;
+
 /**
- * Created by octavian on 22.08.16.
+ * This utility class is used for getting all properties from properties file.
  */
-public interface CertificateConstants {
+public final class CertificateConstants {
 
-    public static final String BASE_64 = "oic.sec.encoding.base64";
+    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();
+    }
 }
index e77d684..bb36946 100644 (file)
  */
 package org.iotivity.cloud.accountserver.resources.credprov.cert;
 
-import org.iotivity.cloud.accountserver.Constants;
-import org.iotivity.cloud.accountserver.db.AccountDBManager;
 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 {
 
-import java.util.*;
+    /**
+     * Type casting manager for converting CertificateTable object tot map
+     */
+    private static final TypeCastingManager<CertificateTable> CERTIFICATE_TABLE_TYPE_CASTING_MANAGER =
+            new TypeCastingManager<>();
 
-public final class CertificateManager {
+    /**
+     * Class attribute as payload for response.
+     */
     private final Map<String, Object> payLoad;
 
-    private TypeCastingManager<CertificateTable> castingManager = new TypeCastingManager<>();
-
-    public Map<String, Object> getPayLoad() {
-        return payLoad;
-    }
-
-    public void putCert(String encoding, byte[] cert) {
-        if (encoding.equals(CertificateConstants.BASE_64)){
-            cert = org.bouncycastle.util.encoders.Base64.encode(cert);
-        }
-        payLoad.put(Constants.CERT_ENCODING, encoding);
-        payLoad.put(Constants.CERT_DATA, cert);
-
-    }
+    /**
+     * Class attribute to store device id.
+     */
+    private final String deviceId;
 
-    public void putCACert(String encoding, byte[] cacert) {
-        if (encoding.equals(CertificateConstants.BASE_64)){
-            cacert = org.bouncycastle.util.encoders.Base64.encode(cacert);
-        }
-        payLoad.put(Constants.CERTCHAIN_ENCODING, encoding);
-        payLoad.put(Constants.CERTCHAIN_DATA, cacert);
+    /**
+     * Constructs certificateMananger with specified device id.
+     * @param deviceId specified device identifier for this CertificateManager.
+     */
+    CertificateManager(String deviceId) {
+        payLoad = new HashMap<>();
+        this.deviceId = deviceId;
     }
 
-    public void putDeviceId(String di) {
-        payLoad.put(Constants.RESP_DEVICE_ID, di);
+    /**
+     * Returns payload for response.
+     */
+    Map<String, Object> getPayLoad() {
+        return payLoad;
     }
 
-    public CertificateManager() {
-        payLoad = new HashMap<>();
+    /**
+     * 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);
     }
 
-    public void createCertificate(String serialNumber, Date notAfter, Date notBefore,
-                                  String deviceId, String uid) {
-        CertificateTable certificateTable = new CertificateTable(serialNumber,
-                notAfter, notBefore, deviceId, uid, false);
-        AccountDBManager.getInstance().insertRecord(Constants.CERTIFICATE_TABLE,
-                castingManager.convertObjectToMap(certificateTable));
-
+    /**
+     * 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)));
     }
 
-    public void updateCertificate(String serialNumber, boolean revoked) {
-        CertificateTable certificateTable = getCertificateTable(serialNumber);
+    /**
+     * 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);
-        AccountDBManager.getInstance().updateRecord(Constants.CERTIFICATE_TABLE,
-                castingManager.convertObjectToMap(certificateTable));
-
+        ACCOUNT_DB_MANAGER.updateRecord(CERTIFICATE_TABLE,
+                CERTIFICATE_TABLE_TYPE_CASTING_MANAGER.convertObjectToMap(certificateTable));
     }
 
-
-    private CertificateTable getCertificateTable(String serialNumber) {
-        CertificateTable certificateTable = new CertificateTable();
-        HashMap<String, Object> condition = new HashMap<>();
-        condition.put(Constants.KEYFIELD_SN, serialNumber);
-        certificateTable = castingManager
-                .convertMaptoObject(
-                        AccountDBManager.getInstance().selectRecord(
-                                Constants.CERTIFICATE_TABLE, condition).get(0),
-                        certificateTable);
-        return certificateTable;
-    }
-
-
-    public String getUserID(String deviceId) {
+    /**
+     * Returns certificate from database, according to specified
+     * device id
+     */
+    public CertificateTable getCertificate() {
         HashMap<String, Object> condition = new HashMap<>();
-        condition.put(Constants.KEYFIELD_DID, deviceId);
-        ArrayList<HashMap<String, Object>> recordList = AccountDBManager
-                .getInstance().selectRecord(Constants.TOKEN_TABLE, condition);
-        Iterator<HashMap<String, Object>> iterator = recordList.iterator();
-        String result = null;
-        if (iterator.hasNext()) {
-            result = iterator.next().get(Constants.KEYFIELD_UUID).toString();
+        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;
         }
-        return result;
     }
 }
index b06aac5..e7113d5 100644 (file)
  */
 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.CertificatePrivateKeyPair;
-import org.iotivity.cloud.accountserver.x509.crl.CrlIssuer;
+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;
@@ -42,31 +48,56 @@ import org.iotivity.cloud.util.Cbor;
 import org.iotivity.cloud.util.Log;
 
 import java.io.IOException;
-import java.math.BigInteger;
 import java.security.GeneralSecurityException;
-import java.security.PrivateKey;
 import java.security.Security;
-import java.security.cert.Certificate;
+import java.security.cert.CRLException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
-import java.util.Date;
 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.CertificateStorage.*;
-
+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
@@ -83,49 +114,62 @@ public class CertificateResource extends Resource {
         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);
-        if (payloadData.containsKey(CSR_ENCODING)) {
-            String encoding = (String) payloadData.get(CSR_ENCODING);
-            byte[] data = (byte[]) payloadData.get(CSR_DATA);
-            if (data != null) {
-                if (encoding.equals(CertificateConstants.BASE_64)) {
-                    data = Base64.decode(data);
+        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(data);
+                    CSRParser parser = new CSRParser(csrData);
                     String commonName = parser.getCommonName();
-                    String[] split = commonName.split(":");
+                    String pattern = "^uuid:(.*)$";
+                    Pattern r = Pattern.compile(pattern);
+                    Matcher m = r.matcher(commonName);
                     String deviceId = (String) payloadData.get(RESP_DEVICE_ID);
-                    if (split[0].equals(KEYFIELD_UUID) && split[1].equals(deviceId) && parser.verify()) {
-                        CertificatePrivateKeyPair privateKeyPair = getRootCertificatePrivateKeyPair();
-                        X509Certificate x509Certificate = getCertificate(deviceId);
-                        CertificateManager certificateManager = new CertificateManager();
-                        BigInteger serialNumber = getNextSerialNumber();
-                        if (x509Certificate != null) {
-                            PrivateKey privateKey = privateKeyPair.getPrivateKey();
-                            CrlIssuer.revokeCertificate(x509Certificate.getSerialNumber(), privateKey);
-                            certificateManager.updateCertificate(x509Certificate.getSerialNumber().toString(), true);
+                    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);
                         }
-                        Date notBefore = getNotBeforeDate();
-                        Date notAfter = getNotAfterDate();
-                        CertificateBuilder certBuilder = new CertificateBuilder(
-                                commonName, parser.getPublicKey(),
-                                notBefore, notAfter,
-                                serialNumber, privateKeyPair);
-                        checkSubjectName(parser, certBuilder);
+                        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 {
-                            certificateManager.putDeviceId((String) payloadData.get(RESP_DEVICE_ID));
-                            String uid = certificateManager.getUserID(deviceId);
-                            certBuilder.setSubjectAltName(Constants.KEYFIELD_USERID + ":" + uid);
-                            Certificate certificate = certBuilder.build().getX509Certificate();
-                            CertificateStorage.saveCertificate(certificate, deviceId);
-                            certificateManager.putCert(encoding, certificate.getEncoded());
-                            certificateManager.putCACert(encoding, privateKeyPair.getX509Certificate().getEncoded());
-                            certificateManager.createCertificate(serialNumber.toString(), notBefore, notAfter, deviceId, uid);
+                            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()));
@@ -137,23 +181,30 @@ public class CertificateResource extends Resource {
                     Log.e(e.getMessage());
                 }
             }
-
         }
         return response;
     }
 
-    private void checkSubjectName(CSRParser parser, CertificateBuilder certBuilder) {
-        String country = parser.getCountry();
-        if (country != null) {
-            certBuilder.setSubjectC(country);
+    /**
+     * 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;
         }
-        String organization = parser.getOrganizational();
-        if (organization != null) {
-            certBuilder.setSubjectO(organization);
+
+        public String getEncoding() {
+            return encoding;
         }
-        String organizationUnit = parser.getOrganizationalUnit();
-        if (organizationUnit != null) {
-            certBuilder.setSubjectOU(organizationUnit);
+
+        public byte[] getData() {
+            return data;
         }
     }
 }
index fca663f..f632a20 100644 (file)
  */
 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.Constants;
 import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
-import org.iotivity.cloud.accountserver.x509.cert.CertificatePrivateKeyPair;
-import org.iotivity.cloud.util.Log;
+import org.iotivity.cloud.accountserver.x509.cert.CertificateExtension;
 
-import java.io.*;
-import java.math.BigInteger;
+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 java.text.MessageFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Properties;
 
-public class CertificateStorage {
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
 
-    public static final Properties PROPERTIES = new Properties();
-
-    static {
-        try {
-            PROPERTIES.load(new FileInputStream(Constants.PROPERTIES_FILE_NAME));
-        } catch (IOException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-    public static final String BC = PROPERTIES.getProperty("securityProvider");
+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");
 
-    public static final String DEVICE_OU = PROPERTIES.getProperty("deviceOU");
-
-    public static final String DEVICE_O = PROPERTIES.getProperty("deviceO");
-
-    public static final String DEVICE_C = PROPERTIES.getProperty("deviceC");
-
-    public static final String KEYSTORE_TYPE = PROPERTIES.getProperty("keystoreType");
-
-    public static final String CA_ALIAS = PROPERTIES.getProperty("caAlias");
-
-    public static final String SUBJECT_NAME = PROPERTIES.getProperty("subjectName");
-
-    private static final File KEYSTORE_FILE = new File(MessageFormat.format(PROPERTIES.getProperty("keyStoreLocation"), File.separator));
+    /**
+     * Keystore object for save, get data from keystore.
+     */
+    private static KeyStore keyStore;
 
-    private static BigInteger SERIAL_NUMBER = new BigInteger(PROPERTIES.getProperty("serialNumber"));
+    public static PrivateKey ROOT_PRIVATE_KEY;
 
-    private static KeyStore keyStore;
+    public static X509Certificate ROOT_CERTIFICATE;
 
-    /**
-     * Insert BouncyCastleProvider into 0 position in security provider list.
-     * Init KeyStore, Generate CA certificate and save it to keyStore.
-     */
-    static {
-        if (!KEYSTORE_FILE.exists()) {
-            try {
-                Files.createDirectories(Paths.get("keystore"));
-            } catch (IOException e) {
-                Log.e(e.getMessage());
-            }
-        }
-        CertificateStorage.init();
-        CertificateStorage.load();
-        CertificatePrivateKeyPair certificatePrivateKeyPair =
-                CertificateStorage.generateCACertificate(DEVICE_C, DEVICE_O, SUBJECT_NAME, DEVICE_OU);
-        CertificateStorage.saveCertificatePrivateKey(certificatePrivateKeyPair);
+    private CertificateStorage() {
+        throw new AssertionError();
     }
 
     /**
      * Init KeyStore. If it does not exists, create it and push to KEYSTORE_FILE.
      */
-    private static void init() {
+    static void init() throws GeneralSecurityException, IOException, OperatorCreationException {
+        Files.createDirectories(Paths.get("keystore"));
         keyStore = load(null, null);
         store();
+        CertificateStorage.generateCACertificate();
+        CertificateStorage.saveCertificatePrivateKey();
     }
 
     /**
@@ -106,12 +79,9 @@ public class CertificateStorage {
      *
      * @return KeyStore instance.
      */
-    public static void load() {
-        try {
-            keyStore = load(new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
-        } catch (FileNotFoundException e) {
-            Log.e(e.getMessage());
-        }
+    public static void load() throws GeneralSecurityException, IOException {
+        keyStore = load(new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
+        initRoot();
     }
 
     /**
@@ -121,14 +91,9 @@ public class CertificateStorage {
      * @param password specified password for opening keystore.
      * @return KeyStore instance.
      */
-    private static KeyStore load(InputStream is, char[] password) {
-        KeyStore keyStore = null;
-        try {
-            keyStore = KeyStore.getInstance(KEYSTORE_TYPE, BouncyCastleProvider.PROVIDER_NAME);
-            keyStore.load(is, password);
-        } catch (GeneralSecurityException | IOException e) {
-            Log.e(e.getMessage());
-        }
+    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;
     }
 
@@ -136,137 +101,51 @@ public class CertificateStorage {
     /**
      * Stores keyStore to default file KEYSTORE_FILE with default password.
      */
-    public static void store() {
-        try {
-            store(keyStore, new FileOutputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
-        } catch (IOException e) {
-            Log.e(e.getMessage());
-        }
+    static void store() throws IOException, GeneralSecurityException {
+        store(keyStore, new FileOutputStream(KEYSTORE_FILE), PASSWORD.toCharArray());
     }
 
     /**
-     * Stores KeyStore to s
+     * Stores KeyStore to file outputstream with specifie password.
      *
      * @param keyStore
      */
-    private static void store(KeyStore keyStore, FileOutputStream out, char[] password) {
-        try {
-            keyStore.store(out, password);
-            out.close();
-        } catch (GeneralSecurityException | IOException e) {
-            Log.e(e.getMessage());
-        }
+    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
      *
-     * @param country          specified country name
-     * @param organization     specified organization name
-     * @param subjectName      specified subject name.
-     * @param organizationUnit specified organization unit.
-     * @return certificate and private key as fields of CertificatePrivateKeyPair instance.
+     * @return certificate and private key
      */
-    private static CertificatePrivateKeyPair generateCACertificate(String country, String organization,
-                                                                   String subjectName, String organizationUnit) {
-        CertificateBuilder rootBuilder = new CertificateBuilder(subjectName, getNotBeforeDate(),
-                getNotAfterDate(), getNextSerialNumber());
-        rootBuilder.setSubjectC(country);
-        rootBuilder.setSubjectO(organization);
-        rootBuilder.setSubjectOU(organizationUnit);
-        CertificatePrivateKeyPair certificatePrivateKeyPair = null;
-        try {
-            certificatePrivateKeyPair = rootBuilder.build();
-        } catch (GeneralSecurityException | OperatorCreationException | CertIOException e) {
-            Log.e(e.getMessage());
+    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();
         }
-        return certificatePrivateKeyPair;
     }
 
     /**
      * Stores certificate and private key to keystore.
-     *
-     * @param certificatePrivateKeyPair specified certificate private key pair.
-     */
-    public static void saveCertificatePrivateKey(CertificatePrivateKeyPair certificatePrivateKeyPair) {
-        try {
-            X509Certificate certificate = certificatePrivateKeyPair.getX509Certificate();
-            keyStore.setCertificateEntry(CA_ALIAS, certificate);
-            keyStore.setKeyEntry(CA_ALIAS, certificatePrivateKeyPair.getPrivateKey(), PASSWORD.toCharArray(),
-                    new java.security.cert.Certificate[]{certificate});
-            store();
-        } catch (GeneralSecurityException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-    public static void saveCertificate(java.security.cert.Certificate certificate, String subjectName) {
-        try {
-            keyStore.setCertificateEntry(subjectName, certificate);
-            store();
-        } catch (KeyStoreException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-
-    /**
-     * Returns next serial number.
-     */
-    public static BigInteger getNextSerialNumber() {
-        SERIAL_NUMBER = SERIAL_NUMBER.add(BigInteger.ONE);
-        PROPERTIES.setProperty("serialNumber", SERIAL_NUMBER.toString());
-        try {
-            PROPERTIES.store(new FileOutputStream(Constants.PROPERTIES_FILE_NAME), "New Serial number");
-        } catch (IOException e) {
-            Log.e(e.getMessage());
-        }
-        return SERIAL_NUMBER;
-    }
-
-    /**
-     * Returns date not before.
-     */
-    public static Date getNotBeforeDate() {
-        return new Date(System.currentTimeMillis());
-    }
-
-    /**
-     * Returns date not after.
-     */
-    public static Date getNotAfterDate() {
-        Calendar calendar = Calendar.getInstance();
-        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) +
-                Integer.parseInt(PROPERTIES.getProperty("notAfterInterval")));
-        return calendar.getTime();
-    }
-
-    /**
-     * Returns CertificatePrivateKeyPair for signing user personal certificates.
      */
-    public static CertificatePrivateKeyPair getRootCertificatePrivateKeyPair() {
-
-        X509Certificate certificate = null;
-        PrivateKey privateKey = null;
-        try {
-            certificate = (X509Certificate) keyStore.getCertificate(CA_ALIAS);
-            privateKey = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray());
-        } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
-            Log.e(e.getMessage());
-        }
-        return new CertificatePrivateKeyPair(certificate, privateKey);
+    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();
     }
 
-    /**
-     * Returns CertificatePrivateKeyPair for signing user personal certificates.
-     */
-    public static X509Certificate getCertificate(String alias) {
-        X509Certificate certificate = null;
-        try {
-            certificate = (X509Certificate) keyStore.getCertificate(alias);
-        } catch (KeyStoreException e) {
-            Log.e(e.getMessage());
-        }
-        return certificate;
+    private static void initRoot() throws GeneralSecurityException {
+        ROOT_PRIVATE_KEY = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray());
+        ROOT_CERTIFICATE = (X509Certificate) keyStore.getCertificate(CA_ALIAS);
     }
 }
index a843d53..d6d0f6a 100644 (file)
  */
 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.AccountDBManager;
 import org.iotivity.cloud.accountserver.db.CRLTable;
-import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants;
 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
-import org.iotivity.cloud.accountserver.x509.crl.CrlParser;
-import org.iotivity.cloud.accountserver.x509.crl.CrlStore;
+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.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
-import static java.util.Collections.EMPTY_MAP;
-import static org.iotivity.cloud.accountserver.x509.crl.CrlParser.DATE_FORMAT;
+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() {
-        throw new AssertionError();
     }
 
-    public static boolean checkLastUpdate(String lastUpdate) {
+    /**
+     * 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 {
-            checkCondition = CrlStore.checkLastUpdate(DATE_FORMAT.parse(lastUpdate));
+            if (x509CRL != null) {
+                checkCondition = DATE_FORMAT.parse(lastUpdate).before(x509CRL.getThisUpdate());
+            }
         } catch (ParseException e) {
             Log.e(e.getMessage());
         }
         return checkCondition;
     }
 
-    public static Map<String, Object> getCrlInfo() {
-        byte[] crl = CrlStore.load();
-        if (crl == null) {
-            return EMPTY_MAP;
+    /**
+     * 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;
         }
-        CrlParser parser = new CrlParser(crl);
-        Map<String, Object> responsePayload = new HashMap<>();
-        responsePayload.put(Constants.REQ_THIS_UPDATE, DATE_FORMAT.format(parser.getThisUpdate()));
-        responsePayload.put(Constants.REQ_NEXT_UPDATE, DATE_FORMAT.format(parser.getNextUpdate()));
-        responsePayload.put(Constants.CRL_ENCODING, CertificateConstants.DER);
-        responsePayload.put(Constants.CRL_DATA, crl);
-        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);
     }
 
-    public static void createCRL(Date thisUpdate) {
-        CRLTable crlTable = new CRLTable(thisUpdate);
-        AccountDBManager.getInstance().insertRecord(Constants.CRL_TABLE,
-                castingManager.convertObjectToMap(crlTable));
+    /**
+     * 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;
+        }
     }
 
 }
index acf7c41..a274784 100644 (file)
 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.accountserver.resources.credprov.cert.CertificateConstants;
-import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
-import org.iotivity.cloud.accountserver.x509.crl.CrlIssuer;
 import org.iotivity.cloud.base.device.Device;
 import org.iotivity.cloud.base.exception.ServerException;
 import org.iotivity.cloud.base.protocols.IRequest;
@@ -37,28 +37,28 @@ 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.CertificateStorage.PROPERTIES;
-import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage.getRootCertificatePrivateKeyPair;
-import static org.iotivity.cloud.accountserver.x509.crl.CrlParser.DATE_FORMAT;
+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 {
 
-    private static final Cbor<HashMap<String, Object>> MAP_CBOR = new Cbor<>();
-
-    static {
-        Calendar calendar = Calendar.getInstance();
-        Date thisUpdate = calendar.getTime();
-        calendar.add(Calendar.DAY_OF_MONTH,
-                Integer.parseInt(PROPERTIES.getProperty("nextUpdateInterval")));
-        Date nextUpdate = calendar.getTime();
-        CrlIssuer.generate(PROPERTIES.getProperty("crlCN"), thisUpdate,
-                nextUpdate, getRootCertificatePrivateKeyPair().getPrivateKey());
-        CrlManager.createCRL(thisUpdate);
-    }
+    /**
+     * 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));
@@ -82,55 +82,65 @@ public class CrlResource extends Resource {
         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() && CrlManager.checkLastUpdate(lastUpdateList.get(0))) {
-                System.out.println("LAST DATE = " + lastUpdateList.get(0));
-                iResponse = MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
-                        ContentFormat.APPLICATION_CBOR, MAP_CBOR.encodingPayloadToCbor(CrlManager.getCrlInfo()));
+            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 {
-        HashMap<String, Object> payloadData = MAP_CBOR
+        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 || nextUpdate != null) {
-            String encoding = (String) payloadData.get(Constants.CRL_ENCODING);
-            byte[] crl = (byte[]) payloadData.get(Constants.CRL_DATA);
-            if(encoding != null && crl != null && encoding.equals(CertificateConstants.BASE_64)) {
-                if (encoding.equals(CertificateConstants.BASE_64)) {
-                    crl = org.bouncycastle.util.encoders.Base64.decode(crl);
-                }
-                CrlIssuer.update(crl);
-                response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED);
-            }
-            Object reqSerialNumber = payloadData.get(Constants.REQ_SERIAL_NUMBER);
-            if (reqSerialNumber != null) {
-                Date thisUpdateDate = null;
-                Date nextUpdateDate = null;
-                boolean parseable = true;
-                try {
-                    thisUpdateDate = DATE_FORMAT.parse(thisUpdate.toString());
-                    nextUpdateDate = DATE_FORMAT.parse(nextUpdate.toString());
-                } catch (ParseException e) {
-                    Log.e(e.getMessage());
-                    parseable = false;
-                }
-                if(parseable) {
-                    CrlIssuer.update(thisUpdateDate, nextUpdateDate, reqSerialNumber.toString(), CertificateStorage.getRootCertificatePrivateKeyPair().getPrivateKey());
+        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 ae6dbb1..0bf7401 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.cert;
 
-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.openssl.PEMException;
 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.accountserver.resources.credprov.cert.CertificateStorage;
 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 static final String COUNTRY = "2.5.4.6";
-
-    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";
-
+    /**
+     * 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 {
         mCsr = new PKCS10CertificationRequest(csrDer);
+        subject = mCsr.getSubject();
     }
 
     /**
      * Returns public key
      */
-    public PublicKey getPublicKey() throws PEMException {
-        return new JcaPEMKeyConverter().setProvider(CertificateStorage.BC).getPublicKey(getPublicKeyInfo());
+    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;
     }
 
     /**
@@ -71,11 +80,11 @@ public class CSRParser {
      *
      * @return true if signature is correct and false otherwise.
      */
-    public boolean verify() {
+    public boolean isSignatureValid() {
         boolean condition = false;
         try {
             condition = mCsr.isSignatureValid(new JcaContentVerifierProviderBuilder()
-                    .setProvider(CertificateStorage.BC).build(getPublicKeyInfo()));
+                    .setProvider(SECURITY_PROVIDER).build(mCsr.getSubjectPublicKeyInfo()));
         } catch (OperatorCreationException | PKCSException e) {
             Log.e(e.getMessage());
         }
@@ -83,53 +92,17 @@ public class CSRParser {
     }
 
     /**
-     * Returns Organization Unit from csr subject.
-     */
-    public String getOrganizationalUnit() {
-        return getX500Field(ORGANIZATION_UNIT, mCsr.getSubject());
-    }
-
-    /**
-     * Returns organization from csr subject.
-     */
-    public String getOrganizational() {
-        return getX500Field(ORGANIZATION, mCsr.getSubject());
-    }
-
-    /**
-     * Returns country from csr subject.
-     */
-    public String getCountry() {
-        return getX500Field(COUNTRY, mCsr.getSubject());
-    }
-
-    /**
      * Returns common name from csr subject.
      */
     public String getCommonName() {
-        return getX500Field(COMMON_NAME, mCsr.getSubject());
-    }
+        return subject.getRDNs(CN)[0].getFirst().getValue().toString();
 
-    /**
-     * Returns public key information for this csr.
-     */
-    public SubjectPublicKeyInfo getPublicKeyInfo() {
-        return mCsr.getSubjectPublicKeyInfo();
     }
 
     /**
-     * Converts asn1.0 identifier ti string DATE_FORMAT.
-     *
-     * @param asn1ObjectIdentifier
-     * @param x500Name
-     * @return
+     * Returns subject as X500Name.
      */
-    private String getX500Field(String asn1ObjectIdentifier, X500Name x500Name) {
-        String result = null;
-        RDN[] arRdns = x500Name.getRDNs(new ASN1ObjectIdentifier(asn1ObjectIdentifier));
-        if (arRdns.length != 0) {
-            result = arRdns[0].getFirst().getValue().toString();
-        }
-        return result;
+    public X500Name getSubject() {
+        return subject;
     }
 }
index c0d0cf8..041bea7 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.cert;
 
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.RDN;
 import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameBuilder;
-import org.bouncycastle.asn1.x500.style.IETFUtils;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.GeneralName;
 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.spec.ECParameterSpec;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
 
 import java.math.BigInteger;
-import java.security.*;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
+import java.util.Calendar;
 import java.util.Date;
 
-import static org.bouncycastle.asn1.x500.style.BCStyle.*;
+import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
 
+/**
+ * Class is used for generating X509 certificate with specified in properties signature and ley algorithms.
+ */
 public class CertificateBuilder {
 
-    private String issuerName;
-
-    private String subjectCN;
-
-    private String subjectC;
-
-    private String subjectO;
-
-    private String subjectOU;
-
-    private String subjectAltName;
-
-    private Date notBefore;
-
-    private Date notAfter;
-
-    private PrivateKey privateKey;
-
+    /**
+     * 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;
 
-    private BigInteger serial;
-
-    public static final String SIGNATURE_ALGORITHM = CertificateStorage.PROPERTIES.getProperty("signatureAlgorithm");
-
-    private static final String CURVE = CertificateStorage.PROPERTIES.getProperty("ellipticCurve");
-
-    private static final String KEY_GENERATOR_ALGORITHM = CertificateStorage.PROPERTIES.getProperty("keyGeneratorAlgorithm");
-
-    private final X500NameBuilder subjectNameBld = new X500NameBuilder(INSTANCE);
-
-    public CertificateBuilder(String subject, Date notBefore, Date notAfter, BigInteger serial) {
-        init(subject, null, notBefore, notAfter, null, null, serial);
-    }
-
-    public CertificateBuilder(String subject, PublicKey pubKey, Date notBefore, Date notAfter,
-                              BigInteger serial, CertificatePrivateKeyPair root) {
-        X500Name x500name = new X500Name(root.getX509Certificate().getSubjectX500Principal().getName());
-        RDN cn = x500name.getRDNs(CN)[0];
-        init(subject, IETFUtils.valueToString(cn.getFirst().getValue()), notBefore, notAfter, root.getPrivateKey(), pubKey, serial);
-    }
-
-    private void init(String subject, String issuer, Date notBefore, Date notAfter,
-                      PrivateKey privKey, PublicKey pubKey, BigInteger serial) {
-        this.subjectCN = subject;
-        this.issuerName = issuer;
-        this.notBefore = notBefore;
-        this.notAfter = notAfter;
-        this.privateKey = privKey;
-        this.publicKey = pubKey;
-        this.serial = serial;
-        subjectNameBld.addRDN(CN, subjectCN);
+    /**
+     * 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.subjectC = subjectC;
-        subjectNameBld.addRDN(C, 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.subjectO = subjectO;
-        subjectNameBld.addRDN(O, 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.subjectOU = subjectOU;
-        subjectNameBld.addRDN(OU, subjectOU);
+    /**
+     * Returns date not before.
+     */
+    private Date getNotBeforeDate() {
+        return Calendar.getInstance().getTime();
     }
 
-    public void setSubjectAltName(String subjectAltName) {
-        this.subjectAltName = 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 (privateKey == null && publicKey == null) {
-            ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
-            KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, CertificateStorage.BC);
-            g.initialize(ecSpec, new SecureRandom());
-            KeyPair pair = g.generateKeyPair();
-            privateKey = pair.getPrivate();
-            publicKey = pair.getPublic();
-            issuerName = subjectCN;
-        }
-        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
-                new X500NameBuilder(INSTANCE).addRDN(CN, issuerName).build(),
-                serial, notBefore, notAfter, subjectNameBld.build(), publicKey);
-
-        if (subjectAltName != null) {
-            ASN1Encodable[] subjectAlternativeNames = new ASN1Encodable[]
-                    {
-                            new GeneralName(GeneralName.dNSName, subjectAltName)
-                    };
-            DERSequence subjectAlternativeNamesExtension = new DERSequence(subjectAlternativeNames);
-            certGen.addExtension(Extension.subjectAlternativeName, false,
-                    subjectAlternativeNamesExtension);
-        }
-        X509Certificate cert = new JcaX509CertificateConverter().setProvider(CertificateStorage.BC).
-                getCertificate(certGen.build(
-                        new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(CertificateStorage.BC).build(privateKey)));
-
-        return new CertificatePrivateKeyPair(cert, privateKey);
-    }
 
 }
\ 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/CertificatePrivateKeyPair.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificatePrivateKeyPair.java
deleted file mode 100644 (file)
index 7d5d70d..0000000
+++ /dev/null
@@ -1,57 +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 final X509Certificate x509Certificate;
-
-    private final PrivateKey privateKey;
-
-    /**
-     * Constructs new CertificatePrivateKeyPair with help of X509Certificate and PrivateKey instances.
-     * @param x509Certificate specified certificate
-     * @param privateKey specified private key.
-     */
-    public CertificatePrivateKeyPair(X509Certificate x509Certificate, PrivateKey privateKey) {
-        this.x509Certificate = x509Certificate;
-        this.privateKey = privateKey;
-    }
-
-    /**
-     * Returns private key.
-     */
-    public PrivateKey getPrivateKey() {
-        return privateKey;
-    }
-
-    /**
-     * Returns certificate.
-     */
-    public X509Certificate getX509Certificate() {
-        return x509Certificate;
-    }
-}
-
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 7542248..6e4df99 100644 (file)
  */
 package org.iotivity.cloud.accountserver.x509.crl;
 
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.cert.X509CRLEntryHolder;
+
 import org.bouncycastle.cert.X509v2CRLBuilder;
-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;
 import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
-import org.iotivity.cloud.util.Log;
 
 import java.io.IOException;
 import java.math.BigInteger;
-import java.security.PrivateKey;
-import java.text.ParseException;
+import java.security.cert.X509CRLEntry;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Date;
 
-import static org.iotivity.cloud.accountserver.x509.crl.CrlParser.DATE_FORMAT;
+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();
     }
 
-    public static byte[] generate(Date thisUpdate, Date nextUpdate,
-                                  PrivateKey key, BigInteger[] serialNumbers, Collection<X509CRLEntryHolder> certs, String issuer) {
-        X500Name issuerDN = new X500Name(issuer);
-        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);
-        if (nextUpdate != null) {
-            crlBuilder.setNextUpdate(nextUpdate);
-        }
-        for (X509CRLEntryHolder crlItem : certs) {
-            crlBuilder.addCRLEntry(crlItem.getSerialNumber(), crlItem.getRevocationDate(), 0);
+        crlBuilder.setNextUpdate(nextUpdate);
+        if (certs != null) {
+            for (X509CRLEntry entryHolder : certs) {
+                crlBuilder.addCRLEntry(entryHolder.getSerialNumber(), entryHolder.getRevocationDate(), 0);
+            }
         }
-        for (BigInteger serialNumber : serialNumbers) {
-            crlBuilder.addCRLEntry(serialNumber, new Date(), 0);
+        for (String serialNumber : serialNumbers) {
+            crlBuilder.addCRLEntry(new BigInteger(serialNumber), new Date(), 0);
         }
-        byte[] data = null;
-        try {
-            ContentSigner signer = new JcaContentSignerBuilder(CertificateBuilder.SIGNATURE_ALGORITHM)
-                    .setProvider(CertificateStorage.BC).build(key);
-            data = crlBuilder.build(signer).getEncoded();
-            CrlStore.save(data);
-        } catch (OperatorCreationException | IOException e) {
-            Log.e(e.getMessage());
-        }
-        return data;
-    }
-
-    public static byte[] generate(String issuerName, Date thisUpdate, Date nextUpdate,
-                                  PrivateKey key) {
-        return generate(thisUpdate, nextUpdate, key, new BigInteger[]{}, Collections.EMPTY_LIST, issuerName);
-
-    }
-
-    public static void update(byte[] crl) {
-        CrlStore.save(crl);
+        crl = crlBuilder.build(CertificateBuilder.SIGNER_BUILDER.
+                build(CertificateStorage.ROOT_PRIVATE_KEY)).getEncoded();
+        return crl;
     }
-
-    public static void revokeCertificate(BigInteger serialNumber, PrivateKey key) {
-        byte[] data = CrlStore.load();
-        CrlParser parser = new CrlParser(data);
-        Collection<X509CRLEntryHolder> certificates = parser.getCerts();
-        X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(new X500Name(parser.getIssuer()),
-                parser.getThisUpdate());
-        crlBuilder.setNextUpdate(parser.getNextUpdate());
-        for (X509CRLEntryHolder entryHolder : certificates) {
-            crlBuilder.addCRLEntry(entryHolder.getSerialNumber(), entryHolder.getRevocationDate(), 0);
-        }
-        crlBuilder.addCRLEntry(serialNumber, new Date(), 0);
-        try {
-            ContentSigner signer = new JcaContentSignerBuilder(CertificateBuilder.SIGNATURE_ALGORITHM)
-                    .setProvider(CertificateStorage.BC).build(key);
-            CrlStore.save(crlBuilder.build(signer).getEncoded());
-        } catch (OperatorCreationException | IOException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-    public static void update(Date thisUpdate, Date nextUpdate,
-                              String serialNumber, PrivateKey key) {
-        String[] serials = serialNumber.split(",");
-        BigInteger[] serialNumbers = new BigInteger[serials.length];
-        for (int i = 0; i < serials.length; i++) {
-            serialNumbers[i] = new BigInteger(serials[i]);
-        }
-        CrlParser crlParser = new CrlParser(CrlStore.load());
-        generate(thisUpdate, nextUpdate, key, serialNumbers, crlParser.getCerts(), crlParser.getIssuer());
-    }
-}
-
+}
\ No newline at end of file
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlParser.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlParser.java
deleted file mode 100644 (file)
index 097463d..0000000
+++ /dev/null
@@ -1,65 +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 org.bouncycastle.cert.X509CRLEntryHolder;
-import org.bouncycastle.cert.X509CRLHolder;
-import org.iotivity.cloud.util.Log;
-
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Date;
-
-public class CrlParser {
-
-    private X509CRLHolder mCrl;
-
-    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
-
-
-    public CrlParser(byte[] crl) {
-        try {
-            mCrl = new X509CRLHolder(crl);
-        } catch (IOException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-    public Date getThisUpdate() {
-        return mCrl.toASN1Structure().getThisUpdate().getDate();
-    }
-
-    public Date getNextUpdate() {
-        return mCrl.toASN1Structure().getNextUpdate().getDate();
-    }
-
-    public String getIssuer() {
-        return mCrl.getIssuer().toString();
-    }
-
-    @SuppressWarnings("unchecked")
-    public Collection<X509CRLEntryHolder> getCerts() {
-        return mCrl.getRevokedCertificates();
-    }
-}
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 1c9a96e..0000000
+++ /dev/null
@@ -1,78 +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 org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage;
-import org.iotivity.cloud.util.Log;
-
-import java.io.*;
-import java.text.MessageFormat;
-import java.util.Date;
-
-public final class CrlStore {
-
-    private CrlStore() {
-        throw new AssertionError();
-    }
-
-    private static final File CRL_FILE = new File(MessageFormat.format(CertificateStorage.PROPERTIES.getProperty("crlLocation"), File.separator));
-
-    public static void save(byte[] crl) {
-        try {
-            FileOutputStream out = new FileOutputStream(CRL_FILE);
-            out.write(crl);
-            out.close();
-        } catch (IOException e) {
-            Log.e(e.getMessage());
-        }
-    }
-
-    public static byte[] load() {
-        try {
-            InputStream f = new FileInputStream(CRL_FILE);
-            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) {
-            Log.e(e.getMessage());
-        }
-        return null;
-    }
-
-    public static boolean checkLastUpdate(Date lastUpdate) {
-        boolean result = false;
-        try {
-            if (CRL_FILE.isFile()) {
-                Date current = new Date(CRL_FILE.lastModified());
-                result = current.after(lastUpdate);
-            }
-        } catch (Exception e) {
-            Log.e(e.getMessage());
-        }
-        return result;
-    }
-}
\ No newline at end of file
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<>();
index 241c560..62bdca5 100644 (file)
@@ -23,10 +23,15 @@ 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.resources.account.AccountResource;
+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;
@@ -37,7 +42,9 @@ 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;
@@ -46,29 +53,83 @@ import org.mockito.stubbing.Answer;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
+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.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+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 Root CA, O=Samsung, C=US, CN=uuid:B371C481-38E6-4D47-8320-7688D8A5B58C";
+    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 CertificateResource certificateResource = new CertificateResource();
+
+    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);
@@ -80,11 +141,6 @@ public class CertificateResourceTest {
                     throws Throwable {
                 Object[] args = invocation.getArguments();
                 CoapResponse resp = (CoapResponse) args[0];
-                System.out
-                        .println("\t----payload : " + resp.getPayloadString());
-
-                System.out
-                        .println("\t----responsestatus : " + resp.getStatus());
                 mResponse = resp;
 
 
@@ -94,6 +150,59 @@ public class CertificateResourceTest {
         }).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();
@@ -102,22 +211,31 @@ public class CertificateResourceTest {
         Map<String, Object> payloadData = mCbor
                 .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class);
         assertTrue(hashmapCheck(mResponse, Constants.REQ_DEVICE_ID));
-        assertTrue(hashmapCheck(mResponse, Constants.CERT_ENCODING));
-        assertTrue(hashmapCheck(mResponse, Constants.CERT_DATA));
-        assertTrue(hashmapCheck(mResponse, Constants.CERTCHAIN_ENCODING));
-        assertTrue(hashmapCheck(mResponse, Constants.CERTCHAIN_DATA));
-
-        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-        InputStream in = new ByteArrayInputStream((byte[]) payloadData.get(Constants.CERT_DATA));
-        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);
-
-
-        assertEquals(COMMON_NAME, cert.getSubjectDN().getName());
-        assertEquals(cert.getPublicKey(), GenerateCSR.getPublicKey());
-        assertEquals("CN="+CertificateStorage.SUBJECT_NAME, cert.getIssuerDN().getName());
-        System.out.println(cert);
+        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
@@ -127,18 +245,68 @@ public class CertificateResourceTest {
         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() {
+    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() {
@@ -147,8 +315,6 @@ public class CertificateResourceTest {
         assertTrue(methodCheck(mResponse, ResponseStatus.METHOD_NOT_ALLOWED));
     }
 
-
-
     @Test
     public void testBadRequest() {
         IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, false);
@@ -171,20 +337,63 @@ public class CertificateResourceTest {
         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) {
-            payloadData.put(Constants.CSR_ENCODING, encoding);
+            csr.setEncoding(encoding);
+            csr.setData(data);
+            payloadData.put("csr", csr);
         }
-        payloadData.put(Constants.CSR_DATA, data);
         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())
@@ -193,7 +402,6 @@ public class CertificateResourceTest {
             return false;
     }
 
-
     private boolean hashmapCheck(IResponse response, String propertyName) {
         HashMap<String, Object> payloadData = mCbor
                 .parsePayloadFromCbor(response.getPayload(), HashMap.class);
index c6b8a7e..600bbc6 100644 (file)
@@ -1,6 +1,5 @@
 package org.iotivity.cloud.accountserver.resources.account.credprov.cert;
 
-import org.bouncycastle.asn1.x500.X500NameBuilder;
 import org.bouncycastle.jce.ECNamedCurveTable;
 import org.bouncycastle.jce.spec.ECParameterSpec;
 import org.bouncycastle.operator.ContentSigner;
@@ -8,28 +7,19 @@ 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.CertificateStorage;
+import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants;
 
 import javax.security.auth.x500.X500Principal;
 import java.security.*;
 
-import static org.bouncycastle.asn1.x500.style.BCStyle.INSTANCE;
-
-/**
- * This class generates PKCS10 certificate signing request
- *
- * @author Pankaj@JournalDev.com
- * @version 1.0
- */
 public class GenerateCSR {
 
-    public static final String SIGNATURE_ALGORITHM = CertificateStorage.PROPERTIES.getProperty("signatureAlgorithm");
+    public static final String SIGNATURE_ALGORITHM = CertificateConstants.PROPERTIES.getProperty("signatureAlgorithm");
 
-    private static final String CURVE = CertificateStorage.PROPERTIES.getProperty("ellipticCurve");
+    private static final String CURVE = CertificateConstants.PROPERTIES.getProperty("ellipticCurve");
 
-    private static final String KEY_GENERATOR_ALGORITHM = CertificateStorage.PROPERTIES.getProperty("keyGeneratorAlgorithm");
+    private static final String KEY_GENERATOR_ALGORITHM = CertificateConstants.PROPERTIES.getProperty("keyGeneratorAlgorithm");
 
-    private final X500NameBuilder subjectNameBld = new X500NameBuilder(INSTANCE);
     private static PublicKey publicKey = null;
     private static PrivateKey privateKey = null;
     private static PublicKey publicKey1 = null;
@@ -43,13 +33,11 @@ public class GenerateCSR {
      */
     public static byte[] generatePKCS10(String commonName, boolean falseKey) throws Exception {
         ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
-        KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, CertificateStorage.BC);
+        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();
@@ -71,8 +59,5 @@ public class GenerateCSR {
         return publicKey;
     }
  
-    public static PrivateKey getPrivateKey() {
-        return privateKey;
-    }
+
 }
\ No newline at end of file
index 49ae340..1afb0ef 100644 (file)
 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;
@@ -40,46 +50,81 @@ 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.util.HashMap;
+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.junit.Assert.assertTrue;
+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<HashMap<String, Object>> mCbor = new Cbor<>();
+    private Cbor<Map<String, Object>> mCbor = new Cbor<>();
     private IResponse mResponse = null;
     private CountDownLatch mLatch = new CountDownLatch(
             1);
-    private CrlResource certificateResource = new CrlResource();
-    private static final String CRL_URI = "/oic/credprov/crl";
-    private static final String CRL_URI_QUERY = "lu=20160726210000";
+    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);
-        // callback mock
         Mockito.doAnswer(new Answer<Object>() {
             @Override
             public CoapResponse answer(InvocationOnMock invocation)
                     throws Throwable {
                 Object[] args = invocation.getArguments();
                 CoapResponse resp = (CoapResponse) args[0];
-                System.out
-                        .println("\t----payload : " + resp.getPayloadString());
-
-                System.out
-                        .println("\t----responsestatus : " + resp.getStatus());
                 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;
@@ -87,39 +132,192 @@ public class CrlResourceTest {
         }).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 testCrlGet() throws Exception {
+    public void testCrlGetContent() throws Exception {
         getTestMethodName();
         IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        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 testCrlGetNotFound() throws Exception {
+    public void testCrlGetNotFoundLastUpdateConditionFalse() throws Exception {
         getTestMethodName();
-        IRequest request = crlRequest(RequestMethod.GET, null,null);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        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 testCrlGetBadQuery() throws Exception {
+    public void testCrlGetNotFoundNullPointer() throws Exception {
         getTestMethodName();
-        IRequest request = crlRequest(RequestMethod.GET, CRL_URI,"lu=1231212asdzfg4123123123123123");
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        IRequest request = crlRequest(RequestMethod.GET, CRL_URI, null);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
         assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND));
     }
 
     @Test
-    public void testCrlPost() throws Exception {
+    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";
-        String serialNUmber = "123456";
-        IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        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
@@ -127,42 +325,129 @@ public class CrlResourceTest {
         getTestMethodName();
         String thisUpdate = "l;dkfjg;ls";
         String nextUpdate = "sdfgsdfg";
-        String serialNUmber = "123456";
+        String[] serialNUmber = new String[]{"123456"};
         IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
         assertTrue(methodCheck(mResponse, ResponseStatus.PRECONDITION_FAILED));
     }
 
     @Test
-    public void testCrlPostPreconditionFailed() throws Exception {
+    public void testCrlPostNullDate() throws Exception {
         getTestMethodName();
         String thisUpdate = null;
         String nextUpdate = null;
-        String serialNUmber = "123456";
+        String[] serialNUmber = new String[]{"123456"};
         IRequest request = crlRequest(RequestMethod.POST, thisUpdate, nextUpdate, serialNUmber);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        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);
-        certificateResource.onDefaultRequestReceived(mMockDevice, request);
+        crlResource.onDefaultRequestReceived(mMockDevice, request);
+        assertTrue(mResponse.getStatus().equals(ResponseStatus.BAD_REQUEST));
     }
 
-    private IRequest crlRequest(RequestMethod method, String uri, String query) {
+    public static IRequest crlRequest(RequestMethod method, String uri, String query) {
         IRequest request = MessageBuilder.createRequest(method, uri, query);
         return request;
     }
 
-    private IRequest crlRequest(RequestMethod method, String thisUpdate, String nextUpdate, String rcsn) {
+    private IRequest crlRequestSN(RequestMethod method, String[] keys, Object[] values) {
         HashMap<String, Object> payloadData = new HashMap<>();
-        payloadData.put(Constants.REQ_THIS_UPDATE, thisUpdate);
+        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);
+            }
 
-        payloadData.put(Constants.REQ_NEXT_UPDATE, nextUpdate);
-        payloadData.put(Constants.REQ_SERIAL_NUMBER, rcsn);
+        }
         IRequest request = MessageBuilder.createRequest(method, CRL_URI,
                 null, ContentFormat.APPLICATION_CBOR,
                 mCbor.encodingPayloadToCbor(payloadData));
@@ -170,6 +455,61 @@ public class CrlResourceTest {
     }
 
 
+    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];
@@ -184,9 +524,8 @@ public class CrlResourceTest {
             return false;
     }
 
-
     private boolean hashmapCheck(IResponse response, String propertyName) {
-        HashMap<String, Object> payloadData = mCbor
+        Map<String, Object> payloadData = mCbor
                 .parsePayloadFromCbor(response.getPayload(), HashMap.class);
         if (payloadData.containsKey(propertyName))
             return true;