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