/*! \brief indicating that provided file doesn't exists or cannot be accessed in the file system */
#define CKM_API_ERROR_FILE_ACCESS_DENIED -18
-#define CKM_API_OCSP_STATUS_GOOD 0
-#define CKM_API_OCSP_STATUS_UNKNOWN -21
-#define CKM_API_OCSP_STATUS_REVOKED -22
-#define CKM_API_OCSP_STATUS_NET_ERROR -23
-#define CKM_API_OCSP_STATUS_INVALID_URL -24
-#define CKM_API_OCSP_STATUS_INVALID_RESPONSE -25
-#define CKM_API_OCSP_STATUS_REMOTE_ERROR -26
-#define CKM_API_OCSP_STATUS_INTERNAL_ERROR -27
+#define CKM_API_OCSP_STATUS_GOOD (1<<0)
+#define CKM_API_OCSP_STATUS_UNSUPPORTED (1<<1)
+#define CKM_API_OCSP_STATUS_UNKNOWN (1<<2)
+#define CKM_API_OCSP_STATUS_REVOKED (1<<3)
+#define CKM_API_OCSP_STATUS_NET_ERROR (1<<4)
+#define CKM_API_OCSP_STATUS_INVALID_URL (1<<5)
+#define CKM_API_OCSP_STATUS_INVALID_RESPONSE (1<<6)
+#define CKM_API_OCSP_STATUS_REMOTE_ERROR (1<<7)
+#define CKM_API_OCSP_STATUS_INTERNAL_ERROR (1<<8)
/*! \brief indicating the error with unknown reason */
#define CKM_API_ERROR_UNKNOWN -255
secp384r1
};
+enum class CertificateFieldId : int {
+ ISSUER,
+ SUBJECT
+};
+
struct Policy {
Policy(const std::string &pass = std::string(), bool extract = true, bool rest = false)
: password(pass)
* @brief Key implementation.
*/
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <dpl/log/log.h>
unsigned char *rawDer = NULL;
int size = i2d_X509(m_x509, &rawDer);
if (!rawDer || size <= 0) {
- // TODO
LogError("i2d_X509 failed");
-// ThrowMsg(Exception::OpensslInternalError,
-// "i2d_X509 failed");
+ return RawBuffer();
}
RawBuffer output(
return GenericKey();
}
+X509_NAME *getX509Name(X509 *x509, CertificateFieldId type) {
+ if (!x509)
+ return NULL;
+
+ if (type == CertificateFieldId::ISSUER)
+ return X509_get_issuer_name(x509);
+ else if (type == CertificateFieldId::SUBJECT)
+ return X509_get_subject_name(x509);
+
+ LogError("Invalid param. Unknown CertificateFieldId");
+ return NULL;
+}
+
+std::string CertificateImpl::getOneLine(CertificateFieldId type) const
+{
+ X509_NAME *name = getX509Name(m_x509, type);
+ if (!name)
+ return std::string();
+ static const int MAXB = 1024;
+ char buffer[MAXB];
+ X509_NAME_oneline(name, buffer, MAXB);
+ return std::string(buffer);
+}
+
+std::string CertificateImpl::getField(CertificateFieldId type, int fieldNid) const {
+ X509_NAME *subjectName = getX509Name(m_x509, type);
+ X509_NAME_ENTRY *subjectEntry = NULL;
+
+ if (!subjectName)
+ return std::string();
+
+ int entryCount = X509_NAME_entry_count(subjectName);
+
+ for (int i = 0; i < entryCount; ++i) {
+ subjectEntry = X509_NAME_get_entry(subjectName, i);
+
+ if (!subjectEntry) {
+ continue;
+ }
+
+ int nid = OBJ_obj2nid(
+ static_cast<ASN1_OBJECT*>(
+ X509_NAME_ENTRY_get_object(subjectEntry)));
+
+ if (nid != fieldNid) {
+ continue;
+ }
+
+ ASN1_STRING* pASN1Str = subjectEntry->value;
+
+ unsigned char* pData = NULL;
+ int nLength = ASN1_STRING_to_UTF8(&pData, pASN1Str);
+
+ if (nLength < 0) {
+ LogError("Reading field error.");
+ return std::string();
+ }
+
+ std::string output(reinterpret_cast<char*>(pData), nLength);
+ OPENSSL_free(pData);
+ return output;
+ }
+ return std::string();
+}
+
+std::string CertificateImpl::getCommonName(CertificateFieldId type) const {
+ return getField(type, NID_commonName);
+}
+
+std::string CertificateImpl::getCountryName(CertificateFieldId type) const {
+ return getField(type, NID_countryName);
+}
+
+std::string CertificateImpl::getStateOrProvinceName(CertificateFieldId type) const {
+ return getField(type, NID_stateOrProvinceName);
+}
+
+std::string CertificateImpl::getLocalityName(CertificateFieldId type) const {
+ return getField(type, NID_localityName);
+}
+
+std::string CertificateImpl::getOrganizationName(CertificateFieldId type) const {
+ return getField(type, NID_organizationName);
+}
+
+std::string CertificateImpl::getOrganizationalUnitName(CertificateFieldId type) const {
+ return getField(type, NID_organizationalUnitName);
+}
+
+std::string CertificateImpl::getEmailAddres(CertificateFieldId type) const {
+ return getField(type, NID_pkcs9_emailAddress);
+}
+
+std::string CertificateImpl::getOCSPURL() const {
+ if (!m_x509)
+ return std::string();
+
+ STACK_OF(OPENSSL_STRING) *aia = X509_get1_ocsp(m_x509);
+
+ if (NULL == aia)
+ return std::string();
+
+ std::string result(sk_OPENSSL_STRING_value(aia, 0));
+ X509_email_free(aia); // TODO is it correct?
+ return result;
+}
+
CertificateImpl::~CertificateImpl() {
LogDebug("free cert start ptr: " << (void*)m_x509);
X509_free(m_x509);
GenericKey::EvpShPtr getEvpShPtr() const;
GenericKey getGenericKey() const;
+ std::string getOneLine(CertificateFieldId type) const;
+ std::string getField(CertificateFieldId type, int fieldNid) const;
+ std::string getCommonName(CertificateFieldId type) const;
+ std::string getCountryName(CertificateFieldId type) const;
+ std::string getStateOrProvinceName(CertificateFieldId type) const;
+ std::string getLocalityName(CertificateFieldId type) const;
+ std::string getOrganizationName(CertificateFieldId type) const;
+ std::string getOrganizationalUnitName(CertificateFieldId type) const;
+ std::string getEmailAddres(CertificateFieldId type) const;
+ std::string getOCSPURL() const;
+
X509* getX509() const;
virtual ~CertificateImpl();
/* Maximum leeway in validity period: default 5 minutes */
#define MAX_VALIDITY_PERIOD (5 * 60)
-#define CKM_DEF_STRING_LEN 256
-
namespace CKM {
OCSPModule::OCSPModule() {
}
int OCSPModule::verify(const CertificateImplVector &certificateChain) {
- char url[CKM_DEF_STRING_LEN];
- int result = -1;
+ bool unsupported = false; // ocsp is unsupported in certificate in chain (except root CA)
if((systemCerts = loadSystemCerts(CKM_SYSTEM_CERTS_PATH)) == NULL) {
LogDebug("Error in loadSystemCerts function");
LogDebug("Error. Broken certificate chain.");
return CKM_API_OCSP_STATUS_INTERNAL_ERROR;
}
+
X509 *cert = certificateChain[i].getX509();
X509 *issuer = certificateChain[i+1].getX509();
- extractAIAUrl(cert, url);
- result = ocsp_verify(cert, issuer, systemCerts, url);
+ std::string url = certificateChain[i].getOCSPURL();
+
+ if (url.empty()) {
+ LogDebug("Certificate does not provide OCSP extension.");
+ unsupported = true;
+ continue;
+ }
+
+ int result = ocsp_verify(cert, issuer, systemCerts, url);
+
if(result != CKM_API_OCSP_STATUS_GOOD) {
LogDebug("Fail to OCSP certification checking: " << result);
return result;
}
}
+ if (unsupported)
+ return CKM_API_OCSP_STATUS_UNSUPPORTED;
return CKM_API_OCSP_STATUS_GOOD;
}
-
-int OCSPModule::ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *systemCerts, char *url) {
+int OCSPModule::ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *systemCerts, const std::string &constUrl) {
OCSP_REQUEST *req = NULL;
OCSP_RESPONSE *resp = NULL;
OCSP_BASICRESP *bs = NULL;
// const char *reason_str = NULL;0
X509_STORE *trustedStore=NULL;
- if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) {
+ std::vector<char> url(constUrl.begin(), constUrl.end());
+
+ if (!OCSP_parse_url(url.data(), &host, &port, &path, &use_ssl)) {
/* report error */
return CKM_API_OCSP_STATUS_INVALID_URL;
}
- cbio = BIO_new_connect(host);
+ cbio = BIO_new_connect(host);
if (cbio == NULL) {
/*BIO_printf(bio_err, "Error creating connect BIO\n");*/
/* report error */
}
}
-void OCSPModule::extractAIAUrl(X509 *cert, char *url) {
- STACK_OF(OPENSSL_STRING) *aia = NULL;
- aia = X509_get1_ocsp(cert);
- if(aia == NULL) {
- return;
- }
- strcpy(url, sk_OPENSSL_STRING_value(aia, 0));
- X509_email_free(aia);
- return;
-}
-
} // namespace CKM
namespace CKM {
-
class OCSPModule {
public:
OCSPModule();
// OK, UNKNOWN, REVOKED, NO_NETWORK, TIMEOUT
int verify(const CertificateImplVector &certificateChain);
private:
- int ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *systemCerts, char *url);
- void extractAIAUrl(X509 *cert, char *url);
+ int ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *systemCerts, const std::string &url);
STACK_OF(X509) *systemCerts;
-
};
} // namespace CKM