From: yuseok.jeon Date: Mon, 27 Apr 2015 04:48:42 +0000 (+0900) Subject: Update the latest source codes from SPIN 2.4 repository X-Git-Tag: submit/accepted/tizen_3.0_ivi/20150430.023343^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F06%2F38706%2F6;p=platform%2Fcore%2Fsecurity%2Fcert-svc.git Update the latest source codes from SPIN 2.4 repository Change-Id: Ib89228f2f330d92f3e7de3cb3943a52e065e6e0b Signed-off-by: yuseok.jeon --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 1daf221..acf4991 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ SET(DEBUG_OUTPUT "-DCERT_SVC_LOG") # for debug SET(TARGET_CERT_SVC_LIB "cert-svc") SET(TARGET_VCORE_LIB "cert-svc-vcore") -SET(TARGET_SIGN_TOOL "dpkg-pki-sig") +#SET(TARGET_SIGN_TOOL "dpkg-pki-sig") # compiler options SET(GC_SECTIONS_FLAGS "-fdata-sections -ffunction-sections -Wl,--gc-sections") @@ -33,6 +33,8 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") SET(CMAKE_SKIP_RPATH "TRUE") SET(TZ_SYS_SHARE "${TZ_SYS_SHARE}") SET(TZ_SYS_BIN "${TZ_SYS_BIN}") +SET(TZ_SYS_ETC "${TZ_SYS_ETC}") +#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wmissing-declarations") ################################################################################ # for libcert-svc.so @@ -42,6 +44,7 @@ PKG_CHECK_MODULES(CERT_SVC_DEPS openssl dlog glib-2.0 + libxml-2.0 libtzplatform-config REQUIRED ) @@ -63,6 +66,11 @@ INCLUDE_DIRECTORIES( ${CERT_SVC_DEPS_INCLUDE_DIRS} ) +ADD_DEFINITIONS("-DDPL_LOGS_ENABLED") +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +ADD_DEFINITIONS("-DTIZEN_FEATURE_CERT_SVC_OCSP_CRL") +ENDIF() + ADD_LIBRARY(${TARGET_CERT_SVC_LIB} SHARED ${CERT_SVC_SOURCES}) SET_TARGET_PROPERTIES(${TARGET_CERT_SVC_LIB} PROPERTIES @@ -75,22 +83,6 @@ TARGET_LINK_LIBRARIES(${TARGET_CERT_SVC_LIB} ${CERT_SVC_DEPS_LIBRARIES} ) -################################################################################ -# for dpkg-pki-sig -################################################################################ - -SET(SIGN_TOOL_SOURCES - ${PROJECT_SOURCE_DIR}/srcs/dpkg-pki-sig.c - ${PROJECT_SOURCE_DIR}/srcs/cert-service-process.c - ${PROJECT_SOURCE_DIR}/srcs/cert-service-util.c -) - -ADD_EXECUTABLE(${TARGET_SIGN_TOOL} ${SIGN_TOOL_SOURCES}) - -TARGET_LINK_LIBRARIES(${TARGET_SIGN_TOOL} - ${TARGET_CERT_SVC_LIB} - ${CERT_SVC_DEPS_LIBRARIES} -) ################################################################################ @@ -105,18 +97,19 @@ INSTALL(FILES DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) INSTALL(FILES ${PROJECT_SOURCE_DIR}/targetinfo DESTINATION ${TZ_SYS_SHARE}/cert-svc/) +#INSTALL(FILES ${PROJECT_SOURCE_DIR}/res/pin/.pin DESTINATION ${TZ_SYS_SHARE}/cert-svc/pin/) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/cert-service.h DESTINATION ${INCLUDEDIR}) # Now we must create empty directory for certificates. # Without this directories rpm package will fail during build. -INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty - DESTINATION /usr/share/cert-svc/ca-certs/code-signing/native - FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH -) -INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty - DESTINATION /usr/share/cert-svc/ca-certs/code-signing/wac - FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH -) +#INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty +# DESTINATION ${TZ_SYS_SHARE}/cert-svc/ca-certs/code-signing/native +# FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH +#) +#INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty +# DESTINATION ${TZ_SYS_SHARE}/cert-svc/ca-certs/code-signing/wac +# FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH +#) INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty DESTINATION ${TZ_SYS_SHARE}/cert-svc/certs/code-signing/wac FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH @@ -125,6 +118,11 @@ INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty DESTINATION ${TZ_SYS_SHARE}/cert-svc/certs/code-signing/tizen FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH ) +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +INSTALL(FILES ${PROJECT_SOURCE_DIR}/res/fota/FOTA_ROOT.cer + DESTINATION ${TZ_SYS_SHARE}/cert-svc/certs/fota +) +ENDIF() INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty DESTINATION ${TZ_SYS_SHARE}/cert-svc/certs/sim/operator FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH diff --git a/etc/cert_svc_create_clean_db.sh b/etc/cert_svc_create_clean_db.sh index 105b492..e1a8f08 100755 --- a/etc/cert_svc_create_clean_db.sh +++ b/etc/cert_svc_create_clean_db.sh @@ -21,13 +21,18 @@ do rm -f ${TZ_SYS_DB}/.$name.db-journal SQL="PRAGMA journal_mode = PERSIST;" sqlite3 ${TZ_SYS_DB}/.$name.db "$SQL" - SQL=".read /usr/share/cert-svc/"$name"_db.sql" + SQL=".read ${TZ_SYS_SHARE}/cert-svc/"$name"_db.sql" sqlite3 ${TZ_SYS_DB}/.$name.db "$SQL" touch ${TZ_SYS_DB}/.$name.db-journal chown root:6026 ${TZ_SYS_DB}/.$name.db chown root:6026 ${TZ_SYS_DB}/.$name.db-journal chmod 660 ${TZ_SYS_DB}/.$name.db chmod 660 ${TZ_SYS_DB}/.$name.db-journal + if [ -f /usr/lib/rpm-plugins/msm.so ] + then + chsmack -a "cert-svc::db" ${TZ_SYS_DB}/.$name.db + chsmack -a "cert-svc::db" ${TZ_SYS_DB}/.$name.db-journal + fi done diff --git a/include/cert-service-process.h b/include/cert-service-process.h index 81d58ff..86658ae 100644 --- a/include/cert-service-process.h +++ b/include/cert-service-process.h @@ -1,7 +1,7 @@ /* * certification service * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Kidong Kim * @@ -24,6 +24,7 @@ #define CERT_SERVICE_PROCESS_H #include +#include #ifdef __cplusplus extern "C" { @@ -39,6 +40,7 @@ struct cert_svc_inode_set; /*********************************************************************************/ int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld); int parse_time_fld_data(unsigned char* before, unsigned char* after, cert_svc_validity_fld_data* fld); +int _parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld); int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descriptor* certDesc); int get_filelist_recur(char* dirName, cert_svc_filename_list* fileNames, struct cert_svc_inode_set *visited); @@ -47,21 +49,29 @@ int get_all_certificates(cert_svc_filename_list** allCerts); int sort_cert_chain(cert_svc_linked_list** unsorted, cert_svc_linked_list** sorted); cert_svc_linked_list* find_issuer_from_list(cert_svc_linked_list* list, cert_svc_linked_list* p); -int is_CAcert(cert_svc_mem_buff* cert, int* isCA); +int is_CACert(cert_svc_mem_buff* cert, int* isCA); int compare_period(int year, int month, int day, int hour, int min, int sec, struct tm* tm); int is_expired(cert_svc_mem_buff* cert, int* isExpired); - +int VerifyCallbackfunc(int ok, X509_STORE_CTX* store); +int _get_all_certificates(char* const *paths, cert_svc_filename_list **lst); + int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certList, cert_svc_filename_list* fileNames, int* validity); +int _verify_certificate_with_caflag(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certList, int checkCaFlag, cert_svc_filename_list* fileNames, int* validity); int _verify_signature(cert_svc_mem_buff* certBuf, unsigned char* message, int msgLen, unsigned char* signature, char* algo, int* validity); int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* certDesc); int _search_certificate(cert_svc_filename_list** fileNames, search_field fldName, char* fldData); -int _check_ocsp_status(cert_svc_mem_buff* cert, const char* uri); +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +int _check_ocsp_status(cert_svc_mem_buff* cert, cert_svc_linked_list** certList, const char* uri); +#endif +int _remove_selfsigned_cert_in_chain(cert_svc_linked_list** certList); int release_certificate_buf(cert_svc_mem_buff* certBuf); int release_certificate_data(cert_svc_cert_descriptor* certDesc); int release_cert_list(cert_svc_linked_list* certList); int release_filename_list(cert_svc_filename_list* fileNames); - + +int get_visibility(CERT_CONTEXT* context, int* visibility); + #ifdef __cplusplus } #endif diff --git a/include/cert-service-util.h b/include/cert-service-util.h index 3ca26d4..99d75af 100644 --- a/include/cert-service-util.h +++ b/include/cert-service-util.h @@ -23,6 +23,8 @@ #ifndef CERT_SERVICE_UTIL_H #define CERT_SERVICE_UTIL_H +#include + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -38,11 +40,13 @@ int get_content_into_buf_DER(unsigned char* content, cert_svc_mem_buff* cert); int cert_svc_util_get_file_size(const char* filepath, unsigned long int* length); int cert_svc_util_load_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf); -int cert_svc_util_load_PFX_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf, cert_svc_linked_list* certLink, unsigned char** privateKey, int* priKeyLen, char* passPhrase); +int cert_svc_util_load_PFX_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf, cert_svc_linked_list** certLink, unsigned char** privateKey, int* priKeyLen, char* passPhrase); int cert_svc_util_get_cert_path(const char* fileName, const char* location, char* retBuf); int cert_svc_util_base64_encode(char* in, int inLen, char* out, int* outLen); int cert_svc_util_base64_decode(char* in, int inLen, char* out, int* outLen); - +int cert_svc_util_get_extension(const char* filePath, cert_svc_mem_buff* certBuf); +int push_cert_into_linked_list(cert_svc_linked_list** certLink, X509* popedCert); +int get_visibility_by_fingerprint(const char* fingerprint, int* visibility); #ifdef __cplusplus } #endif // __cplusplus diff --git a/include/cert-service.h b/include/cert-service.h index 56607e7..352eb1d 100644 --- a/include/cert-service.h +++ b/include/cert-service.h @@ -55,10 +55,19 @@ extern "C" { #define CERT_SVC_ERR_INVALID_PARAMETER -15 #define CERT_SVC_ERR_PERMISSION_DENIED -16 #define CERT_SVC_ERR_IS_EXPIRED -17 +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +#define CERT_SVC_ERR_OCSP_REVOKED -18 +#define CERT_SVC_ERR_OCSP_UNKNOWN -19 +#define CERT_SVC_ERR_OCSP_VERIFICATION_ERROR -20 +#define CERT_SVC_ERR_OCSP_NO_SUPPORT -21 +#define CERT_SVC_ERR_OCSP_NETWORK_FAILED -22 +#define CERT_SVC_ERR_OCSP_INTERNAL -23 +#define CERT_SVC_ERR_OCSP_REMOTE -24 +#endif /* default certificate file path */ #define CERT_SVC_STORE_PATH tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/certs/") #define CERT_SVC_STORE_PATH_DEFAULT tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/certs/ssl/") -#define CERT_SVC_SEARCH_PATH_RO "/usr/share/cert-svc/ca-certs/" +#define CERT_SVC_SEARCH_PATH_RO tzplatform_mkpath(TZ_SYS_SHARE, "ca-certificates/tizen/") #define CERT_SVC_SEARCH_PATH_RW tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/certs/") /*********************************************************************************/ @@ -85,6 +94,17 @@ typedef enum { SEARCH_FIELD_END = 16, } search_field; +typedef enum cert_svc_visibility_t { + CERT_SVC_VISIBILITY_DEVELOPER = 1, + CERT_SVC_VISIBILITY_TEST = 1 << 1, + CERT_SVC_VISIBILITY_VERIFY = 1 << 2, + CERT_SVC_VISIBILITY_PUBLIC = 1 << 6, + CERT_SVC_VISIBILITY_PARTNER = 1 << 7, + CERT_SVC_VISIBILITY_PARTNER_OPERATOR = 1 << 8, + CERT_SVC_VISIBILITY_PARTNER_MANUFACTURER = 1 << 9, + CERT_SVC_VISIBILITY_PLATFORM = 1 << 10 +} cert_svc_visibility; + typedef struct { unsigned int firstSecond; unsigned int firstMinute; @@ -184,10 +204,16 @@ int cert_svc_push_file_into_context(CERT_CONTEXT* ctx, const char* filePath); int cert_svc_add_certificate_to_store(const char* filePath, const char* location); int cert_svc_delete_certificate_from_store(const char* fileName, const char* location); int cert_svc_verify_certificate(CERT_CONTEXT* ctx, int* validity); +int cert_svc_verify_certificate_with_caflag(CERT_CONTEXT* ctx, int* validity); int cert_svc_verify_signature(CERT_CONTEXT* ctx, unsigned char* message, int msgLen, unsigned char* signature, char* algo, int* validity); int cert_svc_extract_certificate_data(CERT_CONTEXT* ctx); int cert_svc_search_certificate(CERT_CONTEXT* ctx, search_field fldName, char* fldData); +int cert_svc_get_visibility(CERT_CONTEXT* ctx, int* visibility); +int cert_svc_get_visibility_by_root_certificate(const char* cert_data, int data_len, int* visibility); + +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL int cert_svc_check_ocsp_status(CERT_CONTEXT* ctx, const char* uri); +#endif char* cert_svc_get_certificate_crt_file_path(void); #ifdef __cplusplus } diff --git a/packaging/cert-svc.spec b/packaging/cert-svc.spec old mode 100644 new mode 100755 index f7dee5c..018067a --- a/packaging/cert-svc.spec +++ b/packaging/cert-svc.spec @@ -8,6 +8,7 @@ License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1001: %{name}.manifest BuildRequires: cmake +BuildRequires: boost-devel BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(openssl) BuildRequires: pkgconfig(evas) @@ -55,8 +56,8 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} -mkdir -p %{buildroot}/usr/share/license -cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} +mkdir -p %{buildroot}%{TZ_SYS_SHARE}/license +cp LICENSE.APLv2 %{buildroot}%{TZ_SYS_SHARE}/license/%{name} %make_install ln -sf %{TZ_SYS_ETC}/ssl/certs %{buildroot}%{TZ_SYS_SHARE}/cert-svc/certs/ssl touch %{buildroot}%{TZ_SYS_SHARE}/cert-svc/pkcs12/storage @@ -67,6 +68,7 @@ rm -rf %{buildroot} %post /sbin/ldconfig +%if 0%{?tizen_feature_certsvc_ocsp_crl} if [ -z ${2} ]; then echo "This is new install of wrt-security" echo "Calling %{TZ_SYS_BIN}/cert_svc_create_clean_db.sh" @@ -74,7 +76,7 @@ if [ -z ${2} ]; then else # Find out old and new version of databases VCORE_OLD_DB_VERSION=`sqlite3 %{TZ_SYS_DB}/.cert_svc_vcore.db ".tables" | grep "DB_VERSION_"` - VCORE_NEW_DB_VERSION=`cat /usr/share/cert-svc/cert_svc_vcore_db.sql | tr '[:blank:]' '\n' | grep DB_VERSION_` + VCORE_NEW_DB_VERSION=`cat %{TZ_SYS_SHARE}/cert-svc/cert_svc_vcore_db.sql | tr '[:blank:]' '\n' | grep DB_VERSION_` echo "OLD vcore database version ${VCORE_OLD_DB_VERSION}" echo "NEW vcore database version ${VCORE_NEW_DB_VERSION}" @@ -92,29 +94,33 @@ else fi chsmack -a 'User' %TZ_SYS_DB/.cert_svc_vcore.db* - +%endif #tizen_feature_certsvc_ocsp_crl %postun /sbin/ldconfig %files -%manifest %{name}.manifest + %defattr(-,root,root,-) +%manifest %{name}.manifest %attr(0755,root,root) %{_bindir}/cert_svc_create_clean_db.sh %{_libdir}/*.so.* -%{_bindir}/dpkg-pki-sig +#%{_bindir}/dpkg-pki-sig %{TZ_SYS_SHARE}/cert-svc/targetinfo +%if 0%{?tizen_feature_certsvc_ocsp_crl} %{_datadir}/cert-svc/cert_svc_vcore_db.sql +%endif %{_datadir}/license/%{name} -%dir %attr(0755,root,use_cert) /usr/share/cert-svc -%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs -%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing -%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing/native -%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing/wac +%dir %attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc +#%dir %attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/ca-certs +#%dir %attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/ca-certs/code-signing +#%dir %attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/ca-certs/code-signing/native +#%dir %attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/ca-certs/code-signing/wac + +#%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing +#%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing/wac +#%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing/tizen %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs -%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing -%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing/wac -%dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/code-signing/tizen %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/sim %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/sim/operator %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/sim/thirdparty @@ -124,6 +130,14 @@ chsmack -a 'User' %TZ_SYS_DB/.cert_svc_vcore.db* %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/mdm/security %dir %attr(0775,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/mdm/security/cert %dir %attr(0777,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/pkcs12 +#%{TZ_SYS_SHARE}/cert-svc/pin/.pin +%{TZ_SYS_SHARE}/cert-svc/certs/ssl +%{TZ_SYS_SHARE}/cert-svc/pkcs12/storage +#%dir %attr(0700, root, root) %{TZ_SYS_SHARE}/cert-svc/pin +%if 0%{?tizen_feature_certsvc_ocsp_crl} +%attr(0755,root,use_cert) %{TZ_SYS_SHARE}/cert-svc/certs/fota/* +%endif +#%{TZ_SYS_SHARE}/cert-svc/pin/.pin %{TZ_SYS_SHARE}/cert-svc/certs/ssl %{TZ_SYS_SHARE}/cert-svc/pkcs12/storage diff --git a/srcs/cert-service-process.c b/srcs/cert-service-process.c index 8afba16..5d62ac4 100644 --- a/srcs/cert-service-process.c +++ b/srcs/cert-service-process.c @@ -27,8 +27,9 @@ #include #include #include - -#include +#include +#include +#include #include "cert-service.h" #include "cert-service-util.h" @@ -49,12 +50,13 @@ typedef struct { int len; } name_field; -static char** __get_field_by_tag(unsigned char* str, int *tag_len, cert_svc_name_fld_data* fld) +int _check_certificate_author(cert_svc_mem_buff* first, cert_svc_mem_buff* second); +static unsigned char** __get_field_by_tag(unsigned char* str, int *tag_len, cert_svc_name_fld_data* fld) { const struct { - char* name; + const char* name; int len; - char **field; + unsigned char **field; } tags[] = { {"C=", 2, &(fld->countryName)}, {"ST=", 3, &(fld->stateOrProvinceName)}, @@ -64,10 +66,10 @@ static char** __get_field_by_tag(unsigned char* str, int *tag_len, cert_svc_name {"CN=", 3, &(fld->commonName)}, {"emailAddress=", 13, &(fld->emailAddress)} }; - char **field = NULL; + unsigned char **field = NULL; if (str[0] == '/') { int i = sizeof(tags) / sizeof(tags[0]) - 1; - while (i >= 0 && strncmp(str + 1, tags[i].name, tags[i].len)) { + while (i >= 0 && strncmp((const char*)(str + 1), (const char*)(tags[i].name), tags[i].len)) { i--; } if (i >= 0) { @@ -82,7 +84,7 @@ static char** __get_field_by_tag(unsigned char* str, int *tag_len, cert_svc_name int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) { int ret = CERT_SVC_ERR_NO_ERROR; - char **prev_field = NULL; + unsigned char **prev_field = NULL; int i = 0, l = 0; if (fld == NULL) { ret = CERT_SVC_ERR_INVALID_PARAMETER; @@ -91,13 +93,13 @@ int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) memset(fld, 0, sizeof(cert_svc_name_fld_data)); while (str[i] != '\0') { int tag_len; - char **field = __get_field_by_tag(str + i, &tag_len, fld); + unsigned char **field = __get_field_by_tag(str + i, &tag_len, fld); while (field == NULL && str[i] != '\0') { i++; field = __get_field_by_tag(str + i, &tag_len, fld); } if (prev_field != NULL) { - *prev_field = strndup(str + l, i - l); + *prev_field = (unsigned char*)strndup((const char*)(str + l), i - l); } if (field != NULL) { i += tag_len; @@ -109,9 +111,7 @@ int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) return ret; } - int _parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) -//int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) { int ret = CERT_SVC_ERR_NO_ERROR; int i = 0, j = 0, last = -1; @@ -127,7 +127,7 @@ int _parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) }; for(i = 0; i < 7; i++) { - if((tmpAddr = strstr(str, tmpFld[i].unitName)) != NULL) + if((tmpAddr = strstr((const char*)str, (const char*)(tmpFld[i].unitName))) != NULL) tmpFld[i].address = tmpAddr; else tmpFld[i].address = NULL; @@ -138,60 +138,75 @@ int _parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld) for(j = i + 1; j < 7; j++) { if(tmpFld[j].address != NULL) { last = j; - tmpFld[i].len = (int)(tmpFld[j].address) - (int)(tmpFld[i].address) - strlen(tmpFld[i].unitName); + tmpFld[i].len = (int)(tmpFld[j].address) - (int)(tmpFld[i].address) - strlen((const char*)(tmpFld[i].unitName)); break; } } } } - tmpFld[last].len = strlen(str) - ((int)(tmpFld[last].address) - (int)str) - strlen(tmpFld[last].unitName); + tmpFld[last].len = strlen((const char*)str) - ((int)(tmpFld[last].address) - (int)str) - strlen((const char*)(tmpFld[last].unitName)); if(tmpFld[0].address != NULL) { (*fld).countryName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[0].len + 1)); - memset((*fld).countryName, 0x00, (tmpFld[0].len + 1)); - memcpy((*fld).countryName, (tmpFld[0].address + strlen(tmpFld[0].unitName)), tmpFld[0].len); + if ((*fld).countryName != NULL) + { + memset((*fld).countryName, 0x00, (tmpFld[0].len + 1)); + memcpy((*fld).countryName, (tmpFld[0].address + strlen((const char*)(tmpFld[0].unitName))), tmpFld[0].len); + } } else (*fld).countryName = NULL; if(tmpFld[1].address != NULL) { (*fld).stateOrProvinceName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[1].len + 1)); - memset((*fld).stateOrProvinceName, 0x00, (tmpFld[1].len + 1)); - memcpy((*fld).stateOrProvinceName, (tmpFld[1].address + strlen(tmpFld[1].unitName)), tmpFld[1].len); + if ((*fld).stateOrProvinceName != NULL) { + memset((*fld).stateOrProvinceName, 0x00, (tmpFld[1].len + 1)); + memcpy((*fld).stateOrProvinceName, (tmpFld[1].address + strlen((const char*)(tmpFld[1].unitName))), tmpFld[1].len); + } } else (*fld).stateOrProvinceName = NULL; if(tmpFld[2].address != NULL) { (*fld).localityName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[2].len + 1)); - memset((*fld).localityName, 0x00, (tmpFld[2].len + 1)); - memcpy((*fld).localityName, (tmpFld[2].address + strlen(tmpFld[2].unitName)), tmpFld[2].len); + if ((*fld).localityName != NULL) { + memset((*fld).localityName, 0x00, (tmpFld[2].len + 1)); + memcpy((*fld).localityName, (tmpFld[2].address + strlen((const char*)(tmpFld[2].unitName))), tmpFld[2].len); + } } else (*fld).localityName = NULL; if(tmpFld[3].address != NULL) { (*fld).organizationName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[3].len + 1)); - memset((*fld).organizationName, 0x00, (tmpFld[3].len + 1)); - memcpy((*fld).organizationName, (tmpFld[3].address + strlen(tmpFld[3].unitName)), tmpFld[3].len); + if ((*fld).organizationName != NULL) { + memset((*fld).organizationName, 0x00, (tmpFld[3].len + 1)); + memcpy((*fld).organizationName, (tmpFld[3].address + strlen((const char*)(tmpFld[3].unitName))), tmpFld[3].len); + } } else (*fld).organizationName = NULL; if(tmpFld[4].address != NULL) { (*fld).organizationUnitName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[4].len + 1)); - memset((*fld).organizationUnitName, 0x00, (tmpFld[4].len + 1)); - memcpy((*fld).organizationUnitName, (tmpFld[4].address + strlen(tmpFld[4].unitName)), tmpFld[4].len); + if ((*fld).organizationUnitName != NULL) { + memset((*fld).organizationUnitName, 0x00, (tmpFld[4].len + 1)); + memcpy((*fld).organizationUnitName, (tmpFld[4].address + strlen((const char*)(tmpFld[4].unitName))), tmpFld[4].len); + } } else (*fld).organizationUnitName = NULL; if(tmpFld[5].address != NULL) { (*fld).commonName = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[5].len + 1)); - memset((*fld).commonName, 0x00, (tmpFld[5].len + 1)); - memcpy((*fld).commonName, (tmpFld[5].address + strlen(tmpFld[5].unitName)), tmpFld[5].len); + if ((*fld).commonName != NULL) { + memset((*fld).commonName, 0x00, (tmpFld[5].len + 1)); + memcpy((*fld).commonName, (tmpFld[5].address + strlen((const char*)(tmpFld[5].unitName))), tmpFld[5].len); + } } else (*fld).commonName = NULL; if(tmpFld[6].address != NULL) { (*fld).emailAddress = (unsigned char*)malloc(sizeof(unsigned char) * (tmpFld[6].len + 1)); - memset((*fld).emailAddress, 0x00, (tmpFld[6].len + 1)); - memcpy((*fld).emailAddress, (tmpFld[6].address + strlen(tmpFld[6].unitName)), tmpFld[6].len); + if ((*fld).emailAddress != NULL) { + memset((*fld).emailAddress, 0x00, (tmpFld[6].len + 1)); + memcpy((*fld).emailAddress, (tmpFld[6].address + strlen((const char*)(tmpFld[6].unitName))), tmpFld[6].len); + } } else (*fld).emailAddress = NULL; @@ -258,6 +273,11 @@ cert_svc_linked_list* find_issuer_from_list(cert_svc_linked_list* list, cert_svc cert_svc_cert_descriptor* tmp2 = NULL; tmp1 = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if (tmp1 == NULL) { + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + return NULL; + } + memset(tmp1, 0x00, sizeof(cert_svc_cert_descriptor)); if(_extract_certificate_data(p->certificate, tmp1) != CERT_SVC_ERR_NO_ERROR) { @@ -267,11 +287,16 @@ cert_svc_linked_list* find_issuer_from_list(cert_svc_linked_list* list, cert_svc for(q = list; q != NULL; q = q->next) { tmp2 = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if (tmp2 == NULL) { + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + goto err; + } + memset(tmp2, 0x00, sizeof(cert_svc_cert_descriptor)); _extract_certificate_data(q->certificate, tmp2); - if(!strncmp(tmp2->info.subjectStr, tmp1->info.issuerStr, strlen(tmp1->info.issuerStr))) { // success + if(!strncmp((const char*)(tmp2->info.subjectStr), (const char*)(tmp1->info.issuerStr), strlen((const char*)(tmp1->info.issuerStr)))) { // success release_certificate_data(tmp1); release_certificate_data(tmp2); return q; @@ -298,14 +323,23 @@ int sort_cert_chain(cert_svc_linked_list** unsorted, cert_svc_linked_list** sort if((*unsorted) == NULL) { for(p = (*sorted); p->next != NULL; p = p->next) { tmp1 = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if(tmp1 == NULL) { + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } memset(tmp1, 0x00, sizeof(cert_svc_cert_descriptor)); tmp2 = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if(tmp2 == NULL) { + release_certificate_data(tmp1); + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } memset(tmp2, 0x00, sizeof(cert_svc_cert_descriptor)); _extract_certificate_data(p->certificate, tmp1); _extract_certificate_data(p->next->certificate, tmp2); - if(strncmp(tmp1->info.issuerStr, tmp2->info.subjectStr, strlen(tmp2->info.subjectStr))) { + if(strncmp((const char*)(tmp1->info.issuerStr), (const char*)(tmp2->info.subjectStr), strlen((const char*)(tmp2->info.subjectStr)))) { SLOGE("[ERR][%s] Certificate chain is broken.\n", __func__); release_certificate_data(tmp1); release_certificate_data(tmp2); @@ -428,8 +462,12 @@ int is_expired(cert_svc_mem_buff* cert, int* isExpired) { int ret = CERT_SVC_ERR_NO_ERROR; cert_svc_cert_descriptor* certDesc = NULL; + int visibility = 0; time_t t; struct tm* tm; + unsigned char * certdata = NULL; + int certSize = 0; + unsigned char *fingerprint = NULL; // get current time t = time(NULL); @@ -437,6 +475,10 @@ int is_expired(cert_svc_mem_buff* cert, int* isExpired) // get descriptor certDesc = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if(certDesc == NULL) { + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } memset(certDesc, 0x00, sizeof(cert_svc_cert_descriptor)); if((ret = _extract_certificate_data(cert, certDesc)) != CERT_SVC_ERR_NO_ERROR) { @@ -445,35 +487,67 @@ int is_expired(cert_svc_mem_buff* cert, int* isExpired) goto err; } - // compare with not before - MUST bigger than this - if(compare_period(((int)certDesc->info.validPeriod.firstYear - 1900), - ((int)certDesc->info.validPeriod.firstMonth - 1), - (int)certDesc->info.validPeriod.firstDay, - (int)certDesc->info.validPeriod.firstHour, - (int)certDesc->info.validPeriod.firstMinute, - (int)certDesc->info.validPeriod.firstSecond, - tm) != 1) { - SLOGE("[ERR][%s] Certificate is expired.\n", __func__); - ret = CERT_SVC_ERR_IS_EXPIRED; + certdata = cert->data; + certSize = cert->size; + + if(certdata == NULL || !certSize) + { + SLOGE("cert is or invalid!"); + ret = CERT_SVC_ERR_INVALID_CERTIFICATE; (*isExpired) = 1; goto err; } - // compare with not after - MUST smaller than this - if(compare_period(((int)certDesc->info.validPeriod.secondYear - 1900), - ((int)certDesc->info.validPeriod.secondMonth - 1), - (int)certDesc->info.validPeriod.secondDay, - (int)certDesc->info.validPeriod.secondHour, - (int)certDesc->info.validPeriod.secondMinute, - (int)certDesc->info.validPeriod.secondSecond, - tm) != -1) { - SLOGE("[ERR][%s] Certificate is expired.\n", __func__); - ret = CERT_SVC_ERR_IS_EXPIRED; + ret = get_certificate_fingerprint(certdata, certSize, &fingerprint); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to get fingerprint data! %d", ret); + (*isExpired) = 1; + goto err; + } + + ret = get_visibility_by_fingerprint(fingerprint, &visibility); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to get visibility! %d", ret); (*isExpired) = 1; goto err; } - (*isExpired) = 0; // not expired + if(visibility == CERT_SVC_VISIBILITY_TEST || visibility == CERT_SVC_VISIBILITY_VERIFY) + { + // compare with not before - MUST bigger than this + if(compare_period(((int)certDesc->info.validPeriod.firstYear - 1900), + ((int)certDesc->info.validPeriod.firstMonth - 1), + (int)certDesc->info.validPeriod.firstDay, + (int)certDesc->info.validPeriod.firstHour, + (int)certDesc->info.validPeriod.firstMinute, + (int)certDesc->info.validPeriod.firstSecond, + tm) != 1) { + SLOGE("[ERR][%s] Certificate is expired.\n", __func__); + ret = CERT_SVC_ERR_IS_EXPIRED; + (*isExpired) = 1; + goto err; + } + + // compare with not after - MUST smaller than this + if(compare_period(((int)certDesc->info.validPeriod.secondYear - 1900), + ((int)certDesc->info.validPeriod.secondMonth - 1), + (int)certDesc->info.validPeriod.secondDay, + (int)certDesc->info.validPeriod.secondHour, + (int)certDesc->info.validPeriod.secondMinute, + (int)certDesc->info.validPeriod.secondSecond, + tm) != -1) { + SLOGE("[ERR][%s] Certificate is expired.\n", __func__); + ret = CERT_SVC_ERR_IS_EXPIRED; + (*isExpired) = 1; + goto err; + } + } + else// ignore check cert time with local time (internal concept) + { + (*isExpired) = 0; // not expired + } err: release_certificate_data(certDesc); @@ -512,6 +586,10 @@ int _remove_selfsigned_cert_in_chain(cert_svc_linked_list** certList) deleted = current; certdesc = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if(certdesc == NULL) { + SLOGE("[ERR][%s] Fail to allocate certificate descriptor.\n", __func__); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } memset(certdesc, 0x00, sizeof(cert_svc_cert_descriptor)); if((ret = _extract_certificate_data(current->certificate, certdesc)) != CERT_SVC_ERR_NO_ERROR) { @@ -519,7 +597,7 @@ int _remove_selfsigned_cert_in_chain(cert_svc_linked_list** certList) goto err; } - if(!strncmp(certdesc->info.subjectStr, certdesc->info.issuerStr, strlen(certdesc->info.issuerStr))) { // self-signed + if(!strncmp((const char*)(certdesc->info.subjectStr), (const char*)(certdesc->info.issuerStr), strlen((const char*)(certdesc->info.issuerStr)))) { // self-signed if(first_tag == 0) { // first cert is self-signed start = start->next; prev = start; @@ -557,7 +635,13 @@ err: return ret; } -int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certList, cert_svc_filename_list* rootPath, int* validity) +int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certList, cert_svc_filename_list* rootPath, int* validity){ + int ca_cflag_check_false = 0; + + return _verify_certificate_with_caflag(certBuf, certList, ca_cflag_check_false, rootPath, validity); +} + +int _verify_certificate_with_caflag(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certList, int checkCaFlag, cert_svc_filename_list* rootPath, int* validity) { int ret = CERT_SVC_ERR_NO_ERROR; cert_svc_linked_list* sorted = NULL; @@ -576,12 +660,21 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL X509** interCert = NULL; X509* targetCert = NULL; STACK_OF(X509) *tchain, *uchain; + STACK_OF(X509) *resultChain; + X509* tmpCert = NULL; + int caFlagValidity; OpenSSL_add_all_algorithms(); tchain = sk_X509_new_null(); uchain = sk_X509_new_null(); findRoot = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)); + if(findRoot == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory for certificate descriptor.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } + memset(findRoot, 0x00, sizeof(cert_svc_cert_descriptor)); if((*certList) != NULL) { @@ -614,7 +707,7 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL goto err; } - if((ret = _search_certificate(&fileNames, SUBJECT_STR, findRoot->info.issuerStr)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = _search_certificate(&fileNames, SUBJECT_STR, (char*)findRoot->info.issuerStr)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to search root certificate\n", __func__); goto err; } @@ -626,6 +719,12 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL } CACert = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)); + if(CACert == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory for ca cert.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } + memset(CACert, 0x00, sizeof(cert_svc_mem_buff)); // use the first found CA cert - ignore other certificate(s). assume that there is JUST one CA cert @@ -635,7 +734,8 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL } // store root certicate path into ctx - strncpy(rootPath->filename, fileNames->filename, strlen(fileNames->filename)); + strncpy(rootPath->filename, fileNames->filename, CERT_SVC_MAX_FILE_NAME_SIZE - 1); + rootPath->filename[CERT_SVC_MAX_FILE_NAME_SIZE - 1] = '\0'; /* check validity - is CA?, is expired? */ if((ret = is_CACert(CACert, &isCA)) != CERT_SVC_ERR_NO_ERROR) { @@ -677,6 +777,12 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL if(q != NULL) { // has 2 or more certificates certIndex = 0; interCert = (X509**)malloc(sizeof(X509*) * certNum); + if(interCert == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory for interim certificate.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } + memset(interCert, 0x00, (sizeof(X509*) * certNum)); while(1) { certContent = q->certificate->data; @@ -717,6 +823,19 @@ int _verify_certificate(cert_svc_mem_buff* certBuf, cert_svc_linked_list** certL if(((*validity) = X509_verify_cert(storeCtx)) != 1) { SLOGE("[ERR][%s] Fail to verify certificate chain, validity: [%d]\n", __func__, (*validity)); SLOGE("err str: [%s]\n", X509_verify_cert_error_string(X509_STORE_CTX_get_error(storeCtx))); + goto err; + } + + if(checkCaFlag) { // check strictly + resultChain = X509_STORE_CTX_get1_chain(storeCtx); + while((tmpCert = sk_X509_pop(resultChain))) { + caFlagValidity = X509_check_ca(tmpCert); + if(caFlagValidity != 1 && (tmpCert = sk_X509_pop(resultChain)) != NULL) { // the last one is not a CA. + (*validity) = 0; + SLOGE("[ERR][%s] Invalid CA Flag for CA Certificate, validity: [%d]\n", __func__, (*validity)); + break; + } + } } err: @@ -775,7 +894,7 @@ int _verify_signature(cert_svc_mem_buff* certBuf, unsigned char* message, int ms } /* load signature and decode */ - sigLen = strlen(signature); + sigLen = strlen((const char*)signature); decodedSigLen = ((sigLen / 4) * 3) + 1; if(!(decodedSig = (unsigned char*)malloc(sizeof(unsigned char) * decodedSigLen))) { @@ -784,7 +903,7 @@ int _verify_signature(cert_svc_mem_buff* certBuf, unsigned char* message, int ms goto err; } memset(decodedSig, 0x00, decodedSigLen); - if((ret = cert_svc_util_base64_decode(signature, sigLen, decodedSig, &decodedSigLen)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = cert_svc_util_base64_decode((char*)signature, sigLen, (char*)decodedSig, &decodedSigLen)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to base64 decode.\n", __func__); ret = CERT_SVC_ERR_INVALID_OPERATION; goto err; @@ -866,9 +985,6 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* unsigned char* pubkeyTmp = NULL; int pkeyLen = 0; EVP_PKEY* evp = NULL; - // get issuerUID, subjectUID - unsigned char* issuerUid = NULL; - unsigned char* subjectUid = NULL; int issuerUidLen = 0, subjectUidLen = 0; // get extension values X509_EXTENSION* ext = NULL; @@ -893,19 +1009,30 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* /* get type */ strncpy(certDesc->type, cert->type, 3); + certDesc->type[3] = '\0'; /* get version and serial number */ certDesc->info.version = get_ASN1_INTEGER(x->cert_info->version) + 1; // default is 0 --> version 1 certDesc->info.serialNumber = get_ASN1_INTEGER(x->cert_info->serialNumber); /* get signature algorithm */ signatureAlgo = (char*)get_ASN1_OBJECT(x->cert_info->signature->algorithm); - sigLen = strlen((char*)signatureAlgo); + sigLen = strlen((const char*)signatureAlgo); certDesc->info.sigAlgo = (unsigned char*)malloc(sizeof(unsigned char) * (sigLen + 1)); + if(certDesc->info.sigAlgo == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.sigAlgo, 0x00, (sigLen + 1)); memcpy(certDesc->info.sigAlgo, signatureAlgo, sigLen); /* get issuer */ tmpIssuerStr = (unsigned char*)get_X509_NAME(x->cert_info->issuer); - issuerStrLen = strlen(tmpIssuerStr); + issuerStrLen = strlen((const char*)tmpIssuerStr); certDesc->info.issuerStr = (unsigned char*)malloc(sizeof(unsigned char) * (issuerStrLen + 1)); + if(certDesc->info.issuerStr == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.issuerStr, 0x00, (issuerStrLen + 1)); memcpy(certDesc->info.issuerStr, tmpIssuerStr, issuerStrLen); @@ -921,9 +1048,14 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* goto err; } /* get subject */ - tmpSubjectStr = get_X509_NAME(x->cert_info->subject); - subjectStrLen = strlen(tmpSubjectStr); + tmpSubjectStr = (unsigned char*)get_X509_NAME(x->cert_info->subject); + subjectStrLen = strlen((const char*)tmpSubjectStr); certDesc->info.subjectStr = (unsigned char*)malloc(sizeof(unsigned char) * (subjectStrLen + 1)); + if(certDesc->info.subjectStr == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.subjectStr, 0x00, (subjectStrLen + 1)); memcpy(certDesc->info.subjectStr, tmpSubjectStr, subjectStrLen); @@ -933,8 +1065,13 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* } /* get public key algorithm */ publicKeyAlgo = (char*)get_ASN1_OBJECT(x->cert_info->key->algor->algorithm); - publicKeyAlgoLen = strlen(publicKeyAlgo); + publicKeyAlgoLen = strlen((const char*)publicKeyAlgo); certDesc->info.pubKeyAlgo = (unsigned char*)malloc(sizeof(unsigned char) * (publicKeyAlgoLen + 1)); + if(certDesc->info.pubKeyAlgo == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.pubKeyAlgo, 0x00, (publicKeyAlgoLen + 1)); memcpy(certDesc->info.pubKeyAlgo, publicKeyAlgo, publicKeyAlgoLen); /* get public key */ @@ -945,6 +1082,11 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* } pkeyLen = i2d_PublicKey(x->cert_info->key->pkey, NULL); certDesc->info.pubKey = (unsigned char*)malloc(sizeof(unsigned char) * (pkeyLen + 1)); + if(certDesc->info.pubKey == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } pubkeyTmp = certDesc->info.pubKey; i2d_PublicKey(x->cert_info->key->pkey, &pubkeyTmp); certDesc->info.pubKeyLen = pkeyLen; @@ -952,6 +1094,11 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* if(x->cert_info->issuerUID != NULL) { issuerUidLen = x->cert_info->issuerUID->length; certDesc->info.issuerUID = (unsigned char*)malloc(sizeof(unsigned char) * (issuerUidLen + 1)); + if(certDesc->info.issuerUID == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.issuerUID, 0x00, (issuerUidLen + 1)); memcpy(certDesc->info.issuerUID, x->cert_info->issuerUID->data, issuerUidLen); } @@ -962,6 +1109,11 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* if(x->cert_info->subjectUID != NULL) { subjectUidLen = x->cert_info->subjectUID->length; certDesc->info.subjectUID = (unsigned char*)malloc(sizeof(unsigned char) * (subjectUidLen + 1)); + if(certDesc->info.subjectUID == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->info.subjectUID, 0x00, (subjectUidLen + 1)); memcpy(certDesc->info.subjectUID, x->cert_info->subjectUID->data, subjectUidLen); } @@ -972,19 +1124,34 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* // certDesc->ext.numOfFields = x->cert_info->extensions->num; certDesc->ext.numOfFields = sk_X509_EXTENSION_num(x->cert_info->extensions); certDesc->ext.fields = (cert_svc_cert_fld_desc*)malloc(sizeof(cert_svc_cert_fld_desc) * certDesc->ext.numOfFields); + if(certDesc->ext.fields == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } - for(i = 0; i < certDesc->ext.numOfFields; i++) { + for(i = 0; i < (int)certDesc->ext.numOfFields; i++) { ext = sk_X509_EXTENSION_value(x->cert_info->extensions, i); if(ext != NULL) { extObject = (char*)get_ASN1_OBJECT(ext->object); - extObjLen = strlen(extObject); + extObjLen = strlen((const char*)extObject); certDesc->ext.fields[i].name = (unsigned char*)malloc(sizeof(unsigned char) * (extObjLen + 1)); + if(certDesc->ext.fields[i].name == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->ext.fields[i].name, 0x00, (extObjLen + 1)); memcpy(certDesc->ext.fields[i].name, extObject, extObjLen); - extValue = ext->value->data; + extValue = (char*)ext->value->data; extValLen = ext->value->length; certDesc->ext.fields[i].data = (unsigned char*)malloc(sizeof(unsigned char) * (extValLen + 1)); + if(certDesc->ext.fields[i].data == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->ext.fields[i].data, 0x00, (extValLen + 1)); memcpy(certDesc->ext.fields[i].data, extValue, extValLen); @@ -994,14 +1161,24 @@ int _extract_certificate_data(cert_svc_mem_buff* cert, cert_svc_cert_descriptor* } /* get signature algorithm and signature */ sigAlgo = (char*)get_ASN1_OBJECT(x->sig_alg->algorithm); - sigAlgoLen = strlen(sigAlgo); + sigAlgoLen = strlen((const char*)sigAlgo); certDesc->signatureAlgo = (unsigned char*)malloc(sizeof(unsigned char) * (sigAlgoLen + 1)); + if(certDesc->signatureAlgo == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->signatureAlgo, 0x00, (sigAlgoLen + 1)); memcpy(certDesc->signatureAlgo, sigAlgo, sigAlgoLen); sigDataLen = x->signature->length; certDesc->signatureLen = sigDataLen; certDesc->signatureData = (unsigned char*)malloc(sizeof(unsigned char) * (sigDataLen + 1)); + if(certDesc->signatureData == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } memset(certDesc->signatureData, 0x00, (sigDataLen + 1)); memcpy(certDesc->signatureData, x->signature->data, sigDataLen); @@ -1026,9 +1203,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip switch(fldName) { case ISSUER_COUNTRY: if(certDesc->info.issuer.countryName) { - len = strlen(certDesc->info.issuer.countryName); - if(!strncmp(fldData, certDesc->info.issuer.countryName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.countryName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.countryName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1037,9 +1214,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_STATEORPROVINCE: if(certDesc->info.issuer.stateOrProvinceName) { - len = strlen(certDesc->info.issuer.stateOrProvinceName); - if(!strncmp(fldData, certDesc->info.issuer.stateOrProvinceName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.stateOrProvinceName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.stateOrProvinceName), len)) { + if((int)strlen(fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1048,9 +1225,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_LOCALITY: if(certDesc->info.issuer.localityName) { - len = strlen(certDesc->info.issuer.localityName); - if(!strncmp(fldData, certDesc->info.issuer.localityName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.localityName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.localityName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1059,9 +1236,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_ORGANIZATION: if(certDesc->info.issuer.organizationName) { - len = strlen(certDesc->info.issuer.organizationName); - if(!strncmp(fldData, certDesc->info.issuer.organizationName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.organizationName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.organizationName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1070,9 +1247,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_ORGANIZATIONUNIT: if(certDesc->info.issuer.organizationUnitName) { - len = strlen(certDesc->info.issuer.organizationUnitName); - if(!strncmp(fldData, certDesc->info.issuer.organizationUnitName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.organizationUnitName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.organizationUnitName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1081,9 +1258,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_COMMONNAME: if(certDesc->info.issuer.commonName) { - len = strlen(certDesc->info.issuer.commonName); - if(!strncmp(fldData, certDesc->info.issuer.commonName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.commonName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.commonName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1092,9 +1269,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_EMAILADDRESS: if(certDesc->info.issuer.emailAddress) { - len = strlen(certDesc->info.issuer.emailAddress); - if(!strncmp(fldData, certDesc->info.issuer.emailAddress, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuer.emailAddress)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuer.emailAddress), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1103,9 +1280,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case ISSUER_STR: if(certDesc->info.issuerStr) { - len = strlen(certDesc->info.issuerStr); - if(!strncmp(fldData, certDesc->info.issuerStr, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.issuerStr)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.issuerStr), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1114,9 +1291,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_COUNTRY: if(certDesc->info.subject.countryName) { - len = strlen(certDesc->info.subject.countryName); - if(!strncmp(fldData, certDesc->info.subject.countryName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.countryName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.countryName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1125,9 +1302,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_STATEORPROVINCE: if(certDesc->info.subject.stateOrProvinceName) { - len = strlen(certDesc->info.subject.stateOrProvinceName); - if(!strncmp(fldData, certDesc->info.subject.stateOrProvinceName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.stateOrProvinceName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.stateOrProvinceName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1136,9 +1313,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_LOCALITY: if(certDesc->info.subject.localityName) { - len = strlen(certDesc->info.subject.localityName); - if(!strncmp(fldData, certDesc->info.subject.localityName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.localityName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.localityName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1147,9 +1324,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_ORGANIZATION: if(certDesc->info.subject.organizationName) { - len = strlen(certDesc->info.subject.organizationName); - if(!strncmp(fldData, certDesc->info.subject.organizationName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.organizationName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.organizationName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1158,9 +1335,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_ORGANIZATIONUNIT: if(certDesc->info.subject.organizationUnitName) { - len = strlen(certDesc->info.subject.organizationUnitName); - if(!strncmp(fldData, certDesc->info.subject.organizationUnitName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.organizationUnitName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.organizationUnitName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1169,9 +1346,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_COMMONNAME: if(certDesc->info.subject.commonName) { - len = strlen(certDesc->info.subject.commonName); - if(!strncmp(fldData, certDesc->info.subject.commonName, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.commonName)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.commonName), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1180,9 +1357,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_EMAILADDRESS: if(certDesc->info.subject.emailAddress) { - len = strlen(certDesc->info.subject.emailAddress); - if(!strncmp(fldData, certDesc->info.subject.emailAddress, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subject.emailAddress)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subject.emailAddress), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1191,9 +1368,9 @@ int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descrip break; case SUBJECT_STR: if(certDesc->info.subjectStr) { - len = strlen(certDesc->info.subjectStr); - if(!strncmp(fldData, certDesc->info.subjectStr, len)) { - if(strlen(fldData) == len) ret = 1; + len = strlen((const char*)(certDesc->info.subjectStr)); + if(!strncmp((const char*)fldData, (const char*)(certDesc->info.subjectStr), len)) { + if((int)strlen((const char*)fldData) == len) ret = 1; else ret = 0; } else ret = 0; @@ -1246,7 +1423,7 @@ int _get_all_certificates(char* const *paths, cert_svc_filename_list **lst) { el->next = local; local = el; - len = strlen(ftsent->fts_path); + len = strlen((const char*)(ftsent->fts_path)); local->filename = (char*)malloc(len+1); if (!local->filename) { ret = CERT_SVC_ERR_MEMORY_ALLOCATION; @@ -1275,7 +1452,7 @@ out: int get_all_certificates(cert_svc_filename_list** allCerts) { int ret; - char ** buffer[] = {CERT_SVC_SEARCH_PATH_RO, CERT_SVC_SEARCH_PATH_RW, NULL}; + char ** buffer[] = {(char **)CERT_SVC_SEARCH_PATH_RO, (char **)CERT_SVC_SEARCH_PATH_RW, NULL}; if (!allCerts) { SLOGE("[ERR][%s] Invalid argument.\n", __func__); @@ -1296,7 +1473,7 @@ int _search_certificate(cert_svc_filename_list** fileNames, search_field fldName cert_svc_filename_list* allCerts = NULL; cert_svc_filename_list* p = NULL; cert_svc_filename_list* q = NULL; - cert_svc_filename_list* new = NULL; + cert_svc_filename_list* newNode = NULL; cert_svc_mem_buff* certBuf = NULL; cert_svc_cert_descriptor* certDesc = NULL; int matched = 0; @@ -1353,30 +1530,32 @@ int _search_certificate(cert_svc_filename_list** fileNames, search_field fldName if(search_data_field(fldName, fldData, certDesc) == 1) { // found!! matched = 1; - if(!(new = (cert_svc_filename_list*)malloc(sizeof(cert_svc_filename_list)))) { + if(!(newNode = (cert_svc_filename_list*)malloc(sizeof(cert_svc_filename_list)))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } - if(!(new->filename = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE))) { + if(!(newNode->filename = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; - free(new); + free(newNode); goto err; } - memset(new->filename, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE); + memset(newNode->filename, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE); - strncpy(new->filename, p->filename, strlen(p->filename)); - new->next = NULL; + strncpy(newNode->filename, p->filename, CERT_SVC_MAX_FILE_NAME_SIZE - 1); + newNode->filename[CERT_SVC_MAX_FILE_NAME_SIZE - 1] = '\0'; + + newNode->next = NULL; if((*fileNames) == NULL) - (*fileNames) = new; + (*fileNames) = newNode; else { q = (*fileNames); while(q->next != NULL) q = q->next; - q->next = new; + q->next = newNode; } } @@ -1407,18 +1586,517 @@ err: return ret; } +X509 *__loadCert(const char *file) { + FILE *fp = fopen(file, "r"); + if(fp == NULL) + return NULL; + X509 *cert; + if(!(cert = d2i_X509_fp(fp, NULL))) { + fseek(fp, 0, SEEK_SET); + cert = PEM_read_X509(fp, NULL, NULL, NULL); + } + fclose(fp); + return cert; +} + +int __loadSystemCerts(STACK_OF(X509) *systemCerts) { + int ret = CERT_SVC_ERR_NO_ERROR; + cert_svc_filename_list* allCerts = NULL; + cert_svc_filename_list* p = NULL; + struct stat file_info; + X509 *cert; + + if((ret = get_all_certificates(&allCerts)) != CERT_SVC_ERR_NO_ERROR) { + SLOGE("[ERR][%s] Fail to get all certificate file list, ret: [%d]\n", __func__, ret); + goto err; + } + + p = allCerts; + while(1) { + if((lstat(p->filename, &file_info)) < 0) { // get file information + SECURE_SLOGE("[ERR][%s] Fail to get file(%s) information.\n", __func__, p->filename); + ret = CERT_SVC_ERR_INVALID_OPERATION; + goto err; + } + if((file_info.st_mode & S_IFLNK) == S_IFLNK) { // if symbolic link, continue +// SLOGD("[LOG][%s] %s is symbolic link, ignored.\n", __func__, p->filename); + goto fail_to_load_file; + } + + cert = __loadCert(p->filename); + if(cert != NULL) { + sk_X509_push(systemCerts, cert); + } +fail_to_load_file: + if(p->next == NULL) + break; + p = p->next; + } + + ret = CERT_SVC_ERR_NO_ERROR; +err: + release_filename_list(allCerts); + + return ret; +} + +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +int __ocsp_verify(X509 *cert, X509 *issuer, STACK_OF(X509) *systemCerts, char *url, int *ocspStatus) { + OCSP_REQUEST *req = NULL; + OCSP_RESPONSE *resp = NULL; + OCSP_BASICRESP *bs = NULL; + OCSP_CERTID *certid = NULL; + BIO *cbio = NULL; + SSL_CTX *use_ssl_ctx = NULL; + char *host = NULL, *port = NULL, *path = NULL; + ASN1_GENERALIZEDTIME *rev = NULL; + ASN1_GENERALIZEDTIME *thisupd = NULL; + ASN1_GENERALIZEDTIME *nextupd = NULL; + int use_ssl = 0; + X509_OBJECT obj; + int i,tmpIdx; + long nsec = (5 * 60), maxage = -1; /* Maximum leeway in validity period: default 5 minutes */ + int ret = 0; + char subj_buf[256]; + int reason; + X509_STORE *trustedStore=NULL; + + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + + if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) { + /* report error */ + return CERT_SVC_ERR_OCSP_NO_SUPPORT; + } + + cbio = BIO_new_connect(host); + if (!cbio) { + /*BIO_printf(bio_err, "Error creating connect BIO\n");*/ + /* report error */ + return CERT_SVC_ERR_OCSP_NO_SUPPORT; + } + + if (port) { + BIO_set_conn_port(cbio, port); + } + + if (use_ssl == 1) { + BIO *sbio; + use_ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + if (!use_ssl_ctx) { + /* report error */ + return CERT_SVC_ERR_OCSP_INTERNAL; + } + + SSL_CTX_set_mode(use_ssl_ctx, SSL_MODE_AUTO_RETRY); + sbio = BIO_new_ssl(use_ssl_ctx, 1); + if (!sbio) { + /* report error */ + return CERT_SVC_ERR_OCSP_INTERNAL; + } + + cbio = BIO_push(sbio, cbio); + if (!cbio) { + /* report error */ + return CERT_SVC_ERR_OCSP_INTERNAL; + } + } + + if (BIO_do_connect(cbio) <= 0) { + /*BIO_printf(bio_err, "Error connecting BIO\n");*/ + /* report error */ + /* free stuff */ + if (host) + OPENSSL_free(host); + if (port) + OPENSSL_free(port); + if (path) + OPENSSL_free(path); + host = port = path = NULL; + if (use_ssl && use_ssl_ctx) + SSL_CTX_free(use_ssl_ctx); + use_ssl_ctx = NULL; + if (cbio) + BIO_free_all(cbio); + cbio = NULL; + return CERT_SVC_ERR_OCSP_NETWORK_FAILED; + } + + req = OCSP_REQUEST_new(); + if(!req) { + return CERT_SVC_ERR_OCSP_INTERNAL; + } + certid = OCSP_cert_to_id(NULL, cert, issuer); + if(certid == NULL) { + return CERT_SVC_ERR_OCSP_INTERNAL; + } + + if(!OCSP_request_add0_id(req, certid)) { + return CERT_SVC_ERR_OCSP_INTERNAL; + } + + resp = OCSP_sendreq_bio(cbio, path, req); + + /* free some stuff we no longer need */ + if (host) + OPENSSL_free(host); + if (port) + OPENSSL_free(port); + if (path) + OPENSSL_free(path); + host = port = path = NULL; + if (use_ssl && use_ssl_ctx) + SSL_CTX_free(use_ssl_ctx); + use_ssl_ctx = NULL; + if (cbio) + BIO_free_all(cbio); + cbio = NULL; + + if (!resp) { + /*BIO_printf(bio_err, "Error querying OCSP responsder\n");*/ + /* report error */ + /* free stuff */ + OCSP_REQUEST_free(req); + return CERT_SVC_ERR_OCSP_NETWORK_FAILED; + } + + i = OCSP_response_status(resp); + + if (i != 0) { // OCSP_RESPONSE_STATUS_SUCCESSFUL + /*BIO_printf(out, "Responder Error: %s (%ld)\n", + OCSP_response_status_str(i), i); */ + /* report error */ + /* free stuff */ + OCSP_REQUEST_free(req); + OCSP_RESPONSE_free(resp); + return CERT_SVC_ERR_OCSP_REMOTE; + } + + bs = OCSP_response_get1_basic(resp); + if (!bs) { + /* BIO_printf(bio_err, "Error parsing response\n");*/ + /* report error */ + /* free stuff */ + OCSP_REQUEST_free(req); + OCSP_RESPONSE_free(resp); + return CERT_SVC_ERR_OCSP_REMOTE; + } + + if(systemCerts != NULL) { + trustedStore = X509_STORE_new(); + for(tmpIdx=0; tmpIdxnext != NULL) { + certNum++; + p = p->next; + } + certNum++; + ret = _extract_certificate_data(p->certificate, findRoot); + } + else { + ret = _extract_certificate_data(certBuf, findRoot); + } + + if(ret != CERT_SVC_ERR_NO_ERROR) { + SLOGE("[ERR][%s] Fail to extract certificate data\n", __func__); + goto err; + } + if((ret = _search_certificate(&fileNames, SUBJECT_STR, findRoot->info.issuerStr)) != CERT_SVC_ERR_NO_ERROR) { + ret = CERT_SVC_ERR_NO_ROOT_CERT; + SLOGE("[ERR][%s] Fail to search root certificate\n", __func__); + goto err; + } + if(fileNames->filename == NULL) { + SLOGE("[ERR][%s] There is no CA certificate.\n", __func__); + ret = CERT_SVC_ERR_NO_ROOT_CERT; + goto err; + } + CACert = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)); + if(CACert == NULL) { + SLOGE("[ERR][%s] Failed to allocate memory for ca cert.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } + memset(CACert, 0x00, sizeof(cert_svc_mem_buff)); + // use the first found CA cert - ignore other certificate(s). assume that there is JUST one CA cert + if((ret = cert_svc_util_load_file_to_buffer(fileNames->filename, CACert)) != CERT_SVC_ERR_NO_ERROR) { + SLOGE("[ERR][%s] Fail to load CA cert to buffer.\n", __func__); + goto err; + } + // ============================= + q = sorted; // first item is the certificate that user want to verify + + childCert = certBuf; + // To check oscp for all certificate chain except root + if(q != NULL) { // has 2 or more certificates + for( ; q != NULL; q = q->next) { + parentCert = q->certificate; + // OCSP Check + if(CERT_SVC_ERR_NO_ERROR != (ret = _verify_ocsp(childCert, parentCert, uri, &ocspStatus))) { + SLOGE("[ERR][%s] Error Occurred during OCSP Checking.\n", __func__); + goto err; + } + if(ocspStatus != 0) { // CERT_SVC_OCSP_GOOD + SLOGE("[ERR][%s] Invalid Certificate OCSP Status. ocspStatus=%d.\n", __func__, ocspStatus); + + switch(ocspStatus) { + case 0 : //OCSP_GOOD + ret = CERT_SVC_ERR_NO_ERROR; + break; + case 1 : //OCSP_REVOCKED + ret = CERT_SVC_ERR_OCSP_REVOKED; + break; + case 2 : //OCSP_UNKNOWN + ret = CERT_SVC_ERR_OCSP_UNKNOWN; + break; + default : + ret = CERT_SVC_ERR_OCSP_REMOTE; + break; + } + goto err; + } + + // move to next + childCert = parentCert; + } + } + + // Final OCSP Check + parentCert = CACert; + if(CERT_SVC_ERR_NO_ERROR != (ret = _verify_ocsp(childCert, parentCert, uri, &ocspStatus))) { + SLOGE("[ERR][%s] Error Occurred during OCSP Checking.\n", __func__); + goto err; + } + switch(ocspStatus) { + case 0 : //OCSP_GOOD + ret = CERT_SVC_ERR_NO_ERROR; + break; + case 1 : //OCSP_REVOCKED + ret = CERT_SVC_ERR_OCSP_REVOKED; + break; + case 2 : //OCSP_UNKNOWN + ret = CERT_SVC_ERR_OCSP_UNKNOWN; + break; + default : + ret = CERT_SVC_ERR_OCSP_REMOTE; + break; + } + if(ret != CERT_SVC_ERR_NO_ERROR) { + SLOGE("[ERR][%s] Invalid Certificate OCSP Status. ocspStatus=%d.\n", __func__, ocspStatus); + goto err; + } + // ============================= +err: + release_certificate_buf(CACert); + release_filename_list(fileNames); + release_certificate_data(findRoot); + release_cert_list(sorted); + return ret; +} + +int _verify_ocsp(cert_svc_mem_buff* child, cert_svc_mem_buff* parent, const char* uri, int* ocspStatus) +{ + int ret = CERT_SVC_ERR_NO_ERROR; + + X509 *childCert = NULL; + X509 *parentCert= NULL; + char *childData=NULL; + char *parentData=NULL; + char *certAiaUrl= NULL; + char *targetUrl= NULL; + STACK_OF(OPENSSL_STRING) *aia = NULL; + STACK_OF(X509) *systemCerts=NULL; + int i; + childData = malloc(child->size + 1); + memset(childData, 0x00, (child->size + 1)); + memcpy(childData, (child->data), child->size); + parentData = malloc(parent->size + 1); + memset(parentData, 0x00, (parent->size + 1)); + memcpy(parentData, (parent->data), parent->size); + d2i_X509(&childCert, &childData, child->size); + d2i_X509(&parentCert, &parentData, parent->size); // check parameter // - 1. if AIA field of cert is exist, use that // - 2. if AIA field of cert is not exist, use uri // - 3. if AIA field of cert is not exist and uri is NULL, fail to check ocsp + aia = X509_get1_ocsp(childCert); + if (aia) { + certAiaUrl = sk_OPENSSL_STRING_value(aia, 0); + } + if(uri != NULL) { + targetUrl = uri; + }else { + targetUrl = certAiaUrl; + } + if(targetUrl == NULL) { + SLOGE("[ERR][%s] No URI for OCSP.\n", __func__); + ret = CERT_SVC_ERR_OCSP_NO_SUPPORT; + goto err; + } + + // Load Trusted Store + systemCerts = sk_X509_new_null(); + ret = __loadSystemCerts(systemCerts) ; + if(ret != CERT_SVC_ERR_NO_ERROR) { + SLOGE("[ERR][%s] Fail to extract certificate data\n", __func__); + goto err; + } + // Do OCSP Check + ret = __ocsp_verify(childCert, parentCert, systemCerts, targetUrl, ocspStatus); + SLOGD("[%s] OCSP Response. ocspstaus=%d, ret=%d.\n", __func__, *ocspStatus, ret); + +err: + if(childData != NULL && *childData != NULL) + free(childData); + if(parentData != NULL && *parentData != NULL) + free(parentData); + if(childCert != NULL) + X509_free(childCert); + if(parentCert != NULL) + X509_free(parentCert); + if(aia != NULL) + X509_email_free(aia); + if(systemCerts != NULL) { + for(i=0; iext.numOfFields > 0) { - for(i = 0; i < certDesc->ext.numOfFields; i++) { + for(i = 0; i < (int)certDesc->ext.numOfFields; i++) { if(certDesc->ext.fields[i].name != NULL) free(certDesc->ext.fields[i].name); if(certDesc->ext.fields[i].data != NULL) free(certDesc->ext.fields[i].data); } @@ -1500,7 +2178,7 @@ int release_cert_list(cert_svc_linked_list* certList) while(1) { curCert = startCert; startCert = startCert->next; - + if(curCert->certificate != NULL) { if(curCert->certificate->data != NULL) { free(curCert->certificate->data); @@ -1555,3 +2233,59 @@ int release_filename_list(cert_svc_filename_list* fileNames) return ret; } + + +void __print_finger_print(const unsigned char *fingerPrint, unsigned int length) +{ + int i=0; + char buffer[21] = {0,}; + + for(; i<20; i++) + snprintf(buffer+i, 20, "%0X", fingerPrint[i]); + + SLOGE("FingerPrint : %s", buffer); +} + +int get_visibility(CERT_CONTEXT* context, int* visibility) +{ + int ret = CERT_SVC_ERR_NO_ERROR; + unsigned char * cert = NULL; + int certSize = 0; + unsigned char *fingerprint = NULL; + + if(!context->certBuf) + { + LOGE("certBuf is NULL!"); + return CERT_SVC_ERR_INVALID_PARAMETER; + } + if(!context->certBuf->size) + { + LOGE("certBuf size is wrong"); + return CERT_SVC_ERR_INVALID_PARAMETER; + } + + cert = context->certBuf->data; + certSize = context->certBuf->size; + + if(cert == NULL || !certSize) + { + LOGE("cert is or invalid!"); + return CERT_SVC_ERR_INVALID_CERTIFICATE; + } + + ret = get_certificate_fingerprint(cert, certSize, &fingerprint); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to get fingerprint data! %d", ret); + return ret; + } + + ret = get_visibility_by_fingerprint(fingerprint, visibility); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to get visibility! %d", ret); + return ret; + } + + return CERT_SVC_ERR_NO_ERROR; +} diff --git a/srcs/cert-service-store.c b/srcs/cert-service-store.c index c582d6c..132dd6a 100644 --- a/srcs/cert-service-store.c +++ b/srcs/cert-service-store.c @@ -39,25 +39,67 @@ int get_file_full_path(char* originalName, const char* location, char* outBuf) char buf[CERT_SVC_MAX_FILE_NAME_SIZE]; char* token = NULL; char seps[] = "_"; + int nameSize = 0 ; - memset(buf, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE); - memset(pathLocation, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE); + if (originalName == NULL) { + SLOGE("[ERR][%s] Check your parameter. Maybe file path is NULL.\n", __func__); + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + + nameSize = strlen(originalName); + + if (nameSize <= 0 || nameSize >= CERT_SVC_MAX_FILE_NAME_SIZE) { + SLOGE("[ERR][%s] Check your parameter. File path is too long.\n", __func__); + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + + memset(buf, 0x00, sizeof(buf)); + memset(pathLocation, 0x00, sizeof(pathLocation)); - if(location == NULL) // use default path - strncpy(buf, CERT_SVC_STORE_PATH_DEFAULT, strlen(CERT_SVC_STORE_PATH_DEFAULT)+1); + if(location == NULL) { // use default path + strncpy(buf, CERT_SVC_STORE_PATH_DEFAULT, sizeof(buf) - 1); + } else { - strncpy(pathLocation, location, strlen(location)); - strncpy(buf, CERT_SVC_STORE_PATH, strlen(CERT_SVC_STORE_PATH)+1); + int locSize = strlen(location) + strlen(CERT_SVC_STORE_PATH); + + if (locSize <= 0 || locSize >= CERT_SVC_MAX_FILE_NAME_SIZE) { + SLOGE("[ERR][%s] Check your parameter. Location is too long.\n", __func__); + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + + strncpy(pathLocation, location, sizeof(pathLocation) - 1); + + strncpy(buf, CERT_SVC_STORE_PATH, sizeof(buf) - 1); + token = strtok(pathLocation, seps); + while(token) { - strncat(buf, token, strlen(token)); - strncat(buf, "/", 1); - token = strtok(NULL, seps); + if((strlen(buf) + strlen(token)) < (CERT_SVC_MAX_FILE_NAME_SIZE - 1)) { + strncat(buf, token, strlen(token)); + strncat(buf, "/", 1); + token = strtok(NULL, seps); + } + else { + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } } } - strncat(buf, originalName, strlen(originalName)); - strncpy(outBuf, buf, CERT_SVC_MAX_FILE_NAME_SIZE); + if ((nameSize + strlen(buf)) >= CERT_SVC_MAX_FILE_NAME_SIZE) { + SLOGE("[ERR][%s] Check your parameter. File path is too long.\n", __func__); + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + + strncat(buf, originalName, nameSize); + strncpy(outBuf, buf, CERT_SVC_MAX_FILE_NAME_SIZE - 1); + outBuf[ CERT_SVC_MAX_FILE_NAME_SIZE - 1] = '\0'; + +err: return ret; } @@ -72,8 +114,6 @@ int _add_certificate_to_store(const char* filePath, const char* location) FILE* fp_out = NULL; unsigned long int inFileLen = 0; char* fileContent = NULL; - /* check certificate or not */ - X509* x = NULL; /* initialize variable */ fileFullPath = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE); diff --git a/srcs/cert-service-util.c b/srcs/cert-service-util.c index af65f84..af5ade7 100644 --- a/srcs/cert-service-util.c +++ b/srcs/cert-service-util.c @@ -23,14 +23,17 @@ #include #include -#include #include +#include #include "cert-service.h" #include "cert-service-util.h" #include "cert-service-debug.h" #include "cert-service-process.h" +#include +#include + #ifndef CERT_SVC_API #define CERT_SVC_API __attribute__((visibility("default"))) #endif @@ -76,27 +79,27 @@ int get_content_into_buf_PEM(unsigned char* content, cert_svc_mem_buff* cert) int decodedSize = 0; int i = 0, j = 0; - if(!content) { - ret = CERT_SVC_ERR_INVALID_PARAMETER; - goto err; - } - startPEM = strstr((const char *)content, CERT_BODY_PREFIX); - startPEM = (startPEM) ? startPEM + strlen(CERT_BODY_PREFIX) : NULL; - endPEM = strstr((const char *)content, CERT_BODY_SUFIX); - if(!startPEM || !endPEM) { - startPEM = strstr((const char *)content, ICERT_BODY_PREFIX); - startPEM = (startPEM) ? startPEM + strlen(ICERT_BODY_PREFIX) : NULL; - endPEM = strstr((const char *)content, ICERT_BODY_SUFIX); - } - if(!startPEM || !endPEM) { - ret = CERT_SVC_ERR_UNKNOWN_ERROR; - goto err; - } - else { - ++startPEM; - --endPEM; - size = (long)endPEM - (long)startPEM; - } + if(!content) { + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + startPEM = strstr((const char *)content, CERT_BODY_PREFIX); + startPEM = (startPEM) ? startPEM + strlen(CERT_BODY_PREFIX) : NULL; + endPEM = strstr((const char *)content, CERT_BODY_SUFIX); + if(!startPEM || !endPEM) { + startPEM = strstr((const char *)content, ICERT_BODY_PREFIX); + startPEM = (startPEM) ? startPEM + strlen(ICERT_BODY_PREFIX) : NULL; + endPEM = strstr((const char *)content, ICERT_BODY_SUFIX); + } + if(!startPEM || !endPEM) { + ret = CERT_SVC_ERR_UNKNOWN_ERROR; + goto err; + } + else { + ++startPEM; + --endPEM; + size = (long)endPEM - (long)startPEM; + } if(!(original = (char*)malloc(sizeof(char) * (size + 1)))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); @@ -225,8 +228,6 @@ int cert_svc_util_load_file_to_buffer(const char* filePath, cert_svc_mem_buff* c FILE* fp_in = NULL; unsigned char* content = NULL; unsigned long int fileSize = 0; - // get extension, type of certificate - const char* extension = NULL; /* get file size */ if((ret = cert_svc_util_get_file_size(filePath, &fileSize)) != CERT_SVC_ERR_NO_ERROR) { @@ -290,19 +291,19 @@ int push_cert_into_linked_list(cert_svc_linked_list** certLink, X509* popedCert) { int ret = CERT_SVC_ERR_NO_ERROR; cert_svc_linked_list* cur = NULL; - cert_svc_linked_list* new = NULL; + cert_svc_linked_list* newNode = NULL; unsigned char* pCert = NULL; unsigned char* bufCert = NULL; int certLen = 0; - if(!(new = (cert_svc_linked_list*)malloc(sizeof(cert_svc_linked_list)))) { + if(!(newNode = (cert_svc_linked_list*)malloc(sizeof(cert_svc_linked_list)))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } - if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { + if(!(newNode->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); - free(new); + free(newNode); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } @@ -310,38 +311,38 @@ int push_cert_into_linked_list(cert_svc_linked_list** certLink, X509* popedCert) /* get certificate data and store in certLink */ if((certLen = i2d_X509(popedCert, NULL)) < 0) { SLOGE("[ERR][%s] Fail to convert certificate.\n", __func__); - release_cert_list(new); + release_cert_list(newNode); ret = CERT_SVC_ERR_INVALID_OPERATION; goto err; } if(!(bufCert = (unsigned char*)malloc(sizeof(unsigned char) * certLen))) { SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; - release_cert_list(new); + release_cert_list(newNode); goto err; } pCert = bufCert; i2d_X509(popedCert, &pCert); - new->certificate->data = bufCert; - new->certificate->size = certLen; + newNode->certificate->data = bufCert; + newNode->certificate->size = certLen; if(NULL == *certLink) { // first item - *certLink = new; + *certLink = newNode; } else { /* attach to linked list */ cur = *certLink; while(cur->next) cur = cur->next; - cur->next = new; + cur->next = newNode; } err: return ret; } -int cert_svc_util_load_PFX_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf, cert_svc_linked_list* certLink, unsigned char** privateKey, int* priKeyLen, char* passPhrase) +int cert_svc_util_load_PFX_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf, cert_svc_linked_list** certLink, unsigned char** privateKey, int* priKeyLen, char* passPhrase) { int ret = CERT_SVC_ERR_NO_ERROR; // related pkcs12 and x509 @@ -538,3 +539,202 @@ int cert_svc_util_base64_decode(char* in, int inLen, char* out, int* outLen) err: return ret; } + +// fingerprint format - AA:BB:CC:DD:EE... +// cert - der(binary) format +int get_certificate_fingerprint(const char *cert, int cert_size, unsigned char** fingerprint) +{ + X509* x509Cert = NULL; + unsigned char x509_fingerprint[EVP_MAX_MD_SIZE] = {0,}; + char* uniformedFingerprint[EVP_MAX_MD_SIZE *3] = {0,}; + int fp_len = 0; + int i = 0; + char buff[8] = {0,}; + int x509_length = 0; + + if(d2i_X509(&x509Cert, &cert, cert_size) == NULL) + { + SLOGE("d2i_x509 failed!"); + *fingerprint = NULL; + return CERT_SVC_ERR_INVALID_CERTIFICATE; + } + + if(!X509_digest(x509Cert, EVP_sha1(), x509_fingerprint, &x509_length)) + { + SLOGE("X509_digest failed"); + X509_free(x509Cert); + *fingerprint = NULL; + return CERT_SVC_ERR_INVALID_CERTIFICATE; + } + + for(i=0; i < x509_length; i++) + { + snprintf(buff, sizeof(buff), "%02X:", x509_fingerprint[i]); + strncat(uniformedFingerprint, buff, 3); + } + uniformedFingerprint[x509_length*3-1] = 0; // remove last : + fp_len = strlen(uniformedFingerprint); + + *fingerprint = (char*)calloc(sizeof(char),fp_len + 1); + if(*fingerprint == NULL) + { + SLOGE("Failed to allocate memory"); + X509_free(x509Cert); + *fingerprint = NULL; + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } + + memcpy(*fingerprint, uniformedFingerprint, fp_len-1); + + LOGD("fingerprint : %s", *fingerprint); + + X509_free(x509Cert); + + return CERT_SVC_ERR_NO_ERROR; +} + +int get_visibility_by_fingerprint(const char* fingerprint, int* visibility) +{ + LOGD("fingerprint : %s", fingerprint); + int ret = 0; + xmlChar *xmlPathCertificateSet = (xmlChar*) "CertificateSet"; + xmlChar *xmlPathCertificateDomain = (xmlChar*) "CertificateDomain";// name=\"tizen-platform\""; + xmlChar *xmlPathDomainPlatform = (xmlChar*) "tizen-platform"; + xmlChar *xmlPathDomainPublic = (xmlChar*) "tizen-public"; + xmlChar *xmlPathDomainPartner = (xmlChar*) "tizen-partner"; + xmlChar *xmlPathDomainDeveloper = (xmlChar*) "tizen-developer"; + xmlChar *xmlPathDomainTest = (xmlChar*) "tizen-test"; + xmlChar *xmlPathDomainVerify = (xmlChar*) "tizen-verify"; + xmlChar *xmlPathFingerPrintSHA1 = (xmlChar*) "FingerprintSHA1"; + + /* load file */ + xmlDocPtr doc = xmlParseFile(tzplatform_mkpath(TZ_SYS_SHARE, "ca-certificates/fingerprint/fingerprint_list.xml")); + + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)) + { + LOGE("Failed to prase fingerprint_list.xml"); + return CERT_SVC_ERR_FILE_IO; + } + + xmlNodePtr curPtr = xmlFirstElementChild(xmlDocGetRootElement(doc)); + if(curPtr == NULL) + { + LOGE("Can not find root"); + xmlFreeDoc(doc); + return CERT_SVC_ERR_FILE_IO; + } + + while(curPtr != NULL) + { + xmlAttr* attr = curPtr->properties; + if(!attr->children || !attr->children->content) + { + LOGE("Failed to get fingerprints from list"); + ret = CERT_SVC_ERR_NO_ROOT_CERT; + goto out; + } + + xmlChar* strLevel = attr->children->content; + xmlNodePtr FpPtr = xmlFirstElementChild(curPtr); + if(FpPtr == NULL) + { + LOGE("Could not find fingerprint"); + ret = CERT_SVC_ERR_NO_ROOT_CERT; + goto out; + } + + while(FpPtr) + { + xmlChar *content = xmlNodeGetContent(FpPtr); + if(xmlStrcmp(content, (xmlChar*)fingerprint) == 0) + { + LOGD("fingerprint : %s are %s", content, strLevel); + if(!xmlStrcmp(strLevel, xmlPathDomainPlatform)){ + *visibility = CERT_SVC_VISIBILITY_PLATFORM; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainPublic)){ + *visibility = CERT_SVC_VISIBILITY_PUBLIC; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainPartner)){ + *visibility = CERT_SVC_VISIBILITY_PARTNER; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainDeveloper)){ + *visibility = CERT_SVC_VISIBILITY_DEVELOPER; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainTest)){ + *visibility = CERT_SVC_VISIBILITY_TEST; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainVerify)){ + *visibility = CERT_SVC_VISIBILITY_VERIFY; + ret = CERT_SVC_ERR_NO_ERROR; + goto out; + } + } + FpPtr = xmlNextElementSibling(FpPtr); + } + curPtr = xmlNextElementSibling(curPtr); + } + + xmlFreeDoc(doc); + return CERT_SVC_ERR_NO_ROOT_CERT; + +out: + xmlFreeDoc(doc); + return ret; +} + + +// expect input cert data is base64 encoded format +int get_visibility_by_certificate(const char* cert_data, int data_len, int* visibility) +{ + if(!cert_data || !data_len) + { + return CERT_SVC_ERR_INVALID_PARAMETER; + } + + int decodedSize = ((data_len / 4) * 3) + 1; + char* decoded = NULL; + char* fingerprint = NULL; + int ret = CERT_SVC_ERR_NO_ERROR; + + if(!(decoded = (char*)malloc(sizeof(char) * decodedSize))) { + SLOGE("Fail to allocate memory."); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } + memset(decoded, 0x00, decodedSize); + + if((ret = cert_svc_util_base64_decode(cert_data, data_len, decoded, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to decode data %d", ret); + free(decoded); + return ret; + } + + ret = get_certificate_fingerprint(decoded, decodedSize, &fingerprint); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + LOGE("Can not get fingerprint! %d", ret); + return ret; + } + + ret = get_visibility_by_fingerprint(fingerprint, visibility); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + LOGE("Can not find visibility %d", ret); + return ret; + } + + free(decoded); + free(fingerprint); + return CERT_SVC_ERR_NO_ERROR; +} diff --git a/srcs/cert-service.c b/srcs/cert-service.c index 9da5b12..c073c7a 100644 --- a/srcs/cert-service.c +++ b/srcs/cert-service.c @@ -1,7 +1,7 @@ /* * certification service * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Kidong Kim * @@ -44,8 +44,7 @@ int cert_svc_add_certificate_to_store(const char* filePath, const char* location { int ret = CERT_SVC_ERR_NO_ERROR; char _filePath[CERT_SVC_MAX_FILE_NAME_SIZE]; - - memset(_filePath, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE); + int pathSize = 0; if(filePath == NULL) { SLOGE("[ERR][%s] Check your parameter. Maybe file path is NULL.\n", __func__); @@ -53,13 +52,42 @@ int cert_svc_add_certificate_to_store(const char* filePath, const char* location goto err; } + pathSize = strlen(filePath); + + if (pathSize <= 0 || pathSize >= CERT_SVC_MAX_FILE_NAME_SIZE) { + SLOGE("[ERR][%s] Check your parameter. Maybe file path is NULL.\n", __func__); + ret = CERT_SVC_ERR_INVALID_PARAMETER; + goto err; + } + + memset(_filePath, 0x0, sizeof(_filePath)); + if(filePath[0] != '/') { // not absolute path, this is regarded relative file path - getcwd(_filePath, CERT_SVC_MAX_FILE_NAME_SIZE); - strncat(_filePath, "/", 1); - strncat(_filePath, filePath, strlen(filePath)); + if (getcwd(_filePath, sizeof(_filePath))) { + int cwdSize = 0; + //just in case + _filePath[sizeof(_filePath) - 1] = '\0'; + + cwdSize = strlen(_filePath); + + if (cwdSize <=0 || (cwdSize + pathSize + 1) >= CERT_SVC_MAX_FILE_NAME_SIZE) { + SLOGE("[ERR][%s] Check your parameter. Maybe file path is NULL.\n", __func__); + ret = CERT_SVC_ERR_INVALID_OPERATION; + goto err; + } + + strncat(_filePath, "/", 1); + strncat(_filePath, filePath, pathSize); + + } else { + SLOGE("[ERR][%s] Check your parameter. Maybe file path is NULL.\n", __func__); + ret = CERT_SVC_ERR_INVALID_OPERATION; + goto err; + } + } + else { + strncpy(_filePath, filePath, pathSize); } - else - strncpy(_filePath, filePath, strlen(filePath)); ret = _add_certificate_to_store(_filePath, location); @@ -95,8 +123,7 @@ err: return ret; } -CERT_SVC_API -int cert_svc_verify_certificate(CERT_CONTEXT* ctx, int* validity) +int _cert_svc_verify_certificate_with_caflag(CERT_CONTEXT* ctx, int checkCAFlag, int* validity) { int ret = CERT_SVC_ERR_NO_ERROR; @@ -126,7 +153,7 @@ int cert_svc_verify_certificate(CERT_CONTEXT* ctx, int* validity) ctx->fileNames->next = NULL; /* call verify function */ - if((ret = _verify_certificate(ctx->certBuf, &(ctx->certLink), ctx->fileNames, validity)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = _verify_certificate_with_caflag(ctx->certBuf, &(ctx->certLink), checkCAFlag, ctx->fileNames, validity)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to verify certificate.\n", __func__); goto err; } @@ -137,6 +164,20 @@ err: return ret; } +CERT_SVC_API +int cert_svc_verify_certificate(CERT_CONTEXT* ctx, int* validity) +{ + int ca_cflag_check_false = 0; + return _cert_svc_verify_certificate_with_caflag(ctx, ca_cflag_check_false, validity); +} + +CERT_SVC_API +int cert_svc_verify_certificate_with_caflag(CERT_CONTEXT* ctx, int* validity) +{ + int ca_cflag_check_true = 1; + return _cert_svc_verify_certificate_with_caflag(ctx, ca_cflag_check_true, validity); +} + /* * message : unsigned character string * signature : base64 encoded string @@ -210,8 +251,8 @@ int cert_svc_search_certificate(CERT_CONTEXT* ctx, search_field fldName, char* f { int ret = CERT_SVC_ERR_NO_ERROR; - /* check parameter */ - if((ctx == NULL) || (fldName < SEARCH_FIELD_START ) || (fldName > SEARCH_FIELD_END) || (fldData == NULL)) { + /* check parameter, fldName is unsigned int. It will never be negative */ + if((ctx == NULL) || (fldName > SEARCH_FIELD_END) || (fldData == NULL)) { SLOGE("[ERR][%s] Invalid parameter. Check your parameter\n", __func__); ret = CERT_SVC_ERR_INVALID_PARAMETER; goto err; @@ -226,7 +267,8 @@ int cert_svc_search_certificate(CERT_CONTEXT* ctx, search_field fldName, char* f /* search specific field */ if((ret = _search_certificate(&(ctx->fileNames), fldName, fldData)) != CERT_SVC_ERR_NO_ERROR) { - SLOGE("[ERR][%s] Fail to search sertificate.\n", __func__); + SLOGE("[ERR][%s] Fail to search certificate.\n", __func__); + SLOGE("[ERR][%s] Fail to search certificate.\n", ctx->fileNames); goto err; } SLOGD("[%s] Success to search certificate(s).\n", __func__); @@ -307,14 +349,14 @@ int cert_svc_load_buf_to_context(CERT_CONTEXT* ctx, unsigned char* buf) goto err; } if(!(ctx->certBuf = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { - SLOGE("[ERR][%s] Fail to allovate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } memset(ctx->certBuf, 0x00, sizeof(cert_svc_mem_buff)); /* memory allocation for decoded string */ - size = strlen(buf); + size = strlen((char*)buf); decodedSize = ((size / 4) * 3) + 1; if(!(decodedStr = (char*)malloc(sizeof(char) * decodedSize))) { @@ -324,7 +366,7 @@ int cert_svc_load_buf_to_context(CERT_CONTEXT* ctx, unsigned char* buf) } /* decode */ - if((ret = cert_svc_util_base64_decode(buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = cert_svc_util_base64_decode((char*)buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to decode string, ret: [%d]\n", __func__, ret); ret = CERT_SVC_ERR_INVALID_OPERATION; free(decodedStr); @@ -332,7 +374,7 @@ int cert_svc_load_buf_to_context(CERT_CONTEXT* ctx, unsigned char* buf) } /* load content to CERT_CONTEXT */ - ctx->certBuf->data = decodedStr; + ctx->certBuf->data = (unsigned char*)decodedStr; ctx->certBuf->size = decodedSize; SLOGD("[%s] Success to load certificate buffer content to context.\n", __func__); @@ -360,7 +402,7 @@ int cert_svc_load_file_to_context(CERT_CONTEXT* ctx, const char* filePath) goto err; } if(!(ctx->certBuf = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { - SLOGE("[ERR][%s] Fail to allovate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } @@ -372,7 +414,7 @@ int cert_svc_load_file_to_context(CERT_CONTEXT* ctx, const char* filePath) ret = CERT_SVC_ERR_INVALID_OPERATION; goto err; } - + SLOGD("[%s] Success to load certificate file content to context.\n", __func__); err: @@ -397,19 +439,19 @@ int cert_svc_push_buf_into_context(CERT_CONTEXT *ctx, unsigned char* buf) /* memory alloction new item */ if(!(new = (cert_svc_linked_list*)malloc(sizeof(cert_svc_linked_list)))) { - SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { - SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); free(new); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } /* memory allocation for decoded string */ - size = strlen(buf); + size = strlen((char*)buf); decodedSize = ((size / 4) * 3) + 1; if(!(decodedStr = (char*)malloc(sizeof(char) * decodedSize))) { @@ -420,7 +462,7 @@ int cert_svc_push_buf_into_context(CERT_CONTEXT *ctx, unsigned char* buf) } /* decode */ - if((ret = cert_svc_util_base64_decode(buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = cert_svc_util_base64_decode((char*)buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to decode string, ret: [%d]\n", __func__, ret); release_cert_list(new); free(decodedStr); @@ -429,7 +471,7 @@ int cert_svc_push_buf_into_context(CERT_CONTEXT *ctx, unsigned char* buf) } /* load content to CERT_CONTEXT */ - new->certificate->data = decodedStr; + new->certificate->data = (unsigned char*)decodedStr; new->certificate->size = decodedSize; new->next = NULL; @@ -442,7 +484,7 @@ int cert_svc_push_buf_into_context(CERT_CONTEXT *ctx, unsigned char* buf) cur = cur->next; cur->next = new; } - + SLOGD("[%s] Success to push certificate buffer content to context.\n", __func__); err: @@ -465,13 +507,13 @@ int cert_svc_push_file_into_context(CERT_CONTEXT *ctx, const char* filePath) /* memory alloction new item */ if(!(new = (cert_svc_linked_list*)malloc(sizeof(cert_svc_linked_list)))) { - SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } memset(new, 0x00, sizeof(cert_svc_linked_list)); if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { - SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; free(new); goto err; @@ -497,7 +539,7 @@ int cert_svc_push_file_into_context(CERT_CONTEXT *ctx, const char* filePath) cur->next = new; } - + SLOGD("[%s] Success to push certificate file content to context.\n", __func__); err: @@ -523,47 +565,53 @@ int cert_svc_load_PFX_file_to_context(CERT_CONTEXT* ctx, unsigned char** private goto err; } if(!(ctx->certBuf = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) { - SLOGE("[ERR][%s] Fail to allovate memory.\n", __func__); + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); ret = CERT_SVC_ERR_MEMORY_ALLOCATION; goto err; } memset(ctx->certBuf, 0x00, sizeof(cert_svc_mem_buff)); /* get content to ctx->certBuf */ - if((ret = cert_svc_util_load_PFX_file_to_buffer(filePath, ctx->certBuf, ctx->certLink, privateKey, priKeyLen, passPhrase)) != CERT_SVC_ERR_NO_ERROR) { + if((ret = cert_svc_util_load_PFX_file_to_buffer(filePath, ctx->certBuf, &ctx->certLink, privateKey, priKeyLen, passPhrase)) != CERT_SVC_ERR_NO_ERROR) { SECURE_SLOGE("[ERR][%s] Fail to load file, filepath: [%s], ret: [%d]\n", __func__, filePath, ret); ret = CERT_SVC_ERR_INVALID_OPERATION; goto err; } - + SLOGD("[%s] Success to load certificate file content to context.\n", __func__); err: return ret; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL CERT_SVC_API int cert_svc_check_ocsp_status(CERT_CONTEXT* ctx, const char* uri) { int ret = CERT_SVC_ERR_NO_ERROR; + cert_svc_linked_list** certList=NULL; + /* check revocation status */ /* check parameter */ if((ctx == NULL) || (ctx->certBuf == NULL)) { SLOGE("[ERR][%s] certBuf must have value.\n", __func__); - ret = CERT_SVC_ERR_INVALID_OPERATION; + ret = CERT_SVC_ERR_INVALID_PARAMETER; goto err; } /* check revocation status */ - if((ret = _check_ocsp_status(ctx->certBuf, uri)) != CERT_SVC_ERR_NO_ERROR) { + if(ctx->certLink != NULL) { + certList = &(ctx->certLink); + } + if((ret = _check_ocsp_status(ctx->certBuf, certList, uri)) != CERT_SVC_ERR_NO_ERROR) { SLOGE("[ERR][%s] Fail to check revocation status.\n", __func__); - ret = CERT_SVC_ERR_INVALID_CERTIFICATE; goto err; } err: return ret; } +#endif CERT_SVC_API char* cert_svc_get_certificate_crt_file_path(void) @@ -571,3 +619,60 @@ char* cert_svc_get_certificate_crt_file_path(void) return CRT_FILE_PATH; } +CERT_SVC_API +int cert_svc_get_visibility(CERT_CONTEXT *ctx, int* visibility) +{ + CERT_CONTEXT* context = NULL; + int ret = CERT_SVC_ERR_NO_ERROR; + const char* root_cert_path = NULL; + + if(!ctx || !visibility) + { + SLOGE("Invalid prameters"); + return CERT_SVC_ERR_INVALID_PARAMETER; + } + + if(!ctx->fileNames || !ctx->fileNames->filename) + { + SLOGE("Can not find root certificate path"); + return CERT_SVC_ERR_INVALID_PARAMETER; + } + + context = cert_svc_cert_context_init(); + if(!context) + { + SLOGE("Out of memory"); + return CERT_SVC_ERR_MEMORY_ALLOCATION; + } + + ret = cert_svc_load_file_to_context(context, ctx->fileNames->filename); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("failed to load root certficiate"); + cert_svc_cert_context_final(context); + return CERT_SVC_ERR_INVALID_CERTIFICATE; + } + + ret = get_visibility(context, visibility); + + cert_svc_cert_context_final(context); + + return ret; +} + +CERT_SVC_API +int cert_svc_get_visibility_by_root_certificate(const char* base64_encoded_data, int data_len, int* visibility) +{ + if(!base64_encoded_data|| !data_len) + { + return CERT_SVC_ERR_INVALID_PARAMETER; + } + + int ret = get_visibility_by_certificate(base64_encoded_data, data_len, visibility); + if(ret != CERT_SVC_ERR_NO_ERROR) + { + SLOGE("Failed to get_visibility :%d", ret); + return ret; + } + return CERT_SVC_ERR_NO_ERROR; +} diff --git a/vcore/CMakeLists.txt b/vcore/CMakeLists.txt index 4fdf270..bc29121 100644 --- a/vcore/CMakeLists.txt +++ b/vcore/CMakeLists.txt @@ -1,4 +1,5 @@ #DB vcore +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) PKG_CHECK_MODULES(VCORE_DB_DEP dpl-efl REQUIRED) @@ -30,7 +31,7 @@ ADD_CUSTOM_COMMAND( OUTPUT .cert_svc_vcore.db-journal ADD_CUSTOM_TARGET(Sqlite3DbVCORE ALL DEPENDS .cert_svc_vcore.db .cert_svc_vcore.db-journal) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/cert_svc_vcore_db.sql - DESTINATION /usr/share/cert-svc/ + DESTINATION ${TZ_SYS_SHARE}/cert-svc/ ) - +ENDIF() ADD_SUBDIRECTORY(src) diff --git a/vcore/src/CMakeLists.txt b/vcore/src/CMakeLists.txt index a7d22cc..373966c 100644 --- a/vcore/src/CMakeLists.txt +++ b/vcore/src/CMakeLists.txt @@ -14,6 +14,22 @@ PKG_CHECK_MODULES(VCORE_DEPS secure-storage REQUIRED) +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +PKG_CHECK_MODULES(VCORE_DEPS + dpl-db-efl + ) +ENDIF() + +IF(TIZEN_FEAT_OSP_DISABLE EQUAL 1) +ADD_DEFINITIONS("-DTIZEN_FEATURE_OSP_DISABLE") +ENDIF() + +SET(LIBCRYPTSVC_DIR + ${PROJECT_SOURCE_DIR}/vcore + ) + +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include) + SET(VCORE_DIR ${PROJECT_SOURCE_DIR}/vcore ) @@ -25,34 +41,19 @@ SET(VCORE_SRC_DIR SET(VCORE_SOURCES ${VCORE_SRC_DIR}/api.cpp ${VCORE_SRC_DIR}/Base64.cpp - ${VCORE_SRC_DIR}/CachedCRL.cpp - ${VCORE_SRC_DIR}/CachedOCSP.cpp ${VCORE_SRC_DIR}/Certificate.cpp - ${VCORE_SRC_DIR}/CertificateCacheDAO.cpp ${VCORE_SRC_DIR}/CertificateCollection.cpp ${VCORE_SRC_DIR}/CertificateConfigReader.cpp ${VCORE_SRC_DIR}/CertificateLoader.cpp - ${VCORE_SRC_DIR}/CertificateVerifier.cpp ${VCORE_SRC_DIR}/CertStoreType.cpp ${VCORE_SRC_DIR}/Config.cpp - ${VCORE_SRC_DIR}/CRL.cpp - ${VCORE_SRC_DIR}/CRLImpl.cpp - ${VCORE_SRC_DIR}/CRLCacheDAO.cpp ${VCORE_SRC_DIR}/CryptoHash.cpp - ${VCORE_SRC_DIR}/Database.cpp - ${VCORE_SRC_DIR}/DeveloperModeValidator.cpp - ${VCORE_SRC_DIR}/OCSP.cpp - ${VCORE_SRC_DIR}/OCSPImpl.cpp ${VCORE_SRC_DIR}/OCSPCertMgrUtil.cpp - ${VCORE_SRC_DIR}/OCSPUtil.c ${VCORE_SRC_DIR}/ReferenceValidator.cpp ${VCORE_SRC_DIR}/RevocationCheckerBase.cpp ${VCORE_SRC_DIR}/SaxReader.cpp ${VCORE_SRC_DIR}/SignatureFinder.cpp ${VCORE_SRC_DIR}/SignatureReader.cpp - ${VCORE_SRC_DIR}/SoupMessageSendBase.cpp - ${VCORE_SRC_DIR}/SoupMessageSendSync.cpp - ${VCORE_SRC_DIR}/SoupMessageSendAsync.cpp ${VCORE_SRC_DIR}/TimeConversion.cpp ${VCORE_SRC_DIR}/VerificationStatus.cpp ${VCORE_SRC_DIR}/ValidatorFactories.cpp @@ -61,13 +62,58 @@ SET(VCORE_SOURCES ${VCORE_SRC_DIR}/SignatureValidator.cpp ${VCORE_SRC_DIR}/XmlsecAdapter.cpp ${VCORE_SRC_DIR}/pkcs12.c + ) + +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +SET(VCORE_SOURCES + ${VCORE_SRC_DIR}/api.cpp + ${VCORE_SRC_DIR}/Base64.cpp + ${VCORE_SRC_DIR}/Certificate.cpp + ${VCORE_SRC_DIR}/CertificateCollection.cpp + ${VCORE_SRC_DIR}/CertificateConfigReader.cpp + ${VCORE_SRC_DIR}/CertificateLoader.cpp + ${VCORE_SRC_DIR}/CertStoreType.cpp + ${VCORE_SRC_DIR}/Config.cpp + ${VCORE_SRC_DIR}/CryptoHash.cpp + ${VCORE_SRC_DIR}/OCSPCertMgrUtil.cpp + ${VCORE_SRC_DIR}/ReferenceValidator.cpp + ${VCORE_SRC_DIR}/RevocationCheckerBase.cpp + ${VCORE_SRC_DIR}/SaxReader.cpp + ${VCORE_SRC_DIR}/SignatureFinder.cpp + ${VCORE_SRC_DIR}/SignatureReader.cpp + ${VCORE_SRC_DIR}/TimeConversion.cpp + ${VCORE_SRC_DIR}/VerificationStatus.cpp + ${VCORE_SRC_DIR}/ValidatorFactories.cpp + ${VCORE_SRC_DIR}/VCore.cpp + ${VCORE_SRC_DIR}/DUID.cpp + ${VCORE_SRC_DIR}/WrtSignatureValidator.cpp + ${VCORE_SRC_DIR}/SignatureValidator.cpp + ${VCORE_SRC_DIR}/XmlsecAdapter.cpp + ${VCORE_SRC_DIR}/pkcs12.c + ${VCORE_SRC_DIR}/CachedCRL.cpp + ${VCORE_SRC_DIR}/CachedOCSP.cpp + ${VCORE_SRC_DIR}/CertificateCacheDAO.cpp + ${VCORE_SRC_DIR}/CertificateVerifier.cpp + ${VCORE_SRC_DIR}/CRL.cpp + ${VCORE_SRC_DIR}/CRLImpl.cpp + ${VCORE_SRC_DIR}/CRLCacheDAO.cpp + ${VCORE_SRC_DIR}/Database.cpp + ${VCORE_SRC_DIR}/OCSP.cpp + ${VCORE_SRC_DIR}/OCSPImpl.cpp + ${VCORE_SRC_DIR}/SoupMessageSendBase.cpp + ${VCORE_SRC_DIR}/SoupMessageSendSync.cpp + ${VCORE_SRC_DIR}/SoupMessageSendAsync.cpp + ${VCORE_SRC_DIR}/OCSPUtil.c ) +ENDIF() SET(VCORE_INCLUDES ${VCORE_DEPS_INCLUDE_DIRS} ${VCORE_SRC_DIR} ${VCORE_DIR}/src +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) ${VCORE_DIR}/src/orm +ENDIF() ${VCORE_DIR}/src/legacy ${CMAKE_BINARY_DIR}/vcore/src ) @@ -77,6 +123,9 @@ ADD_DEFINITIONS(${VCORE_DEPS_CFLAGS_OTHER}) ADD_DEFINITIONS("-DSEPARATED_SINGLETON_IMPLEMENTATION") ADD_DEFINITIONS("-DDPL_LOGS_ENABLED") ADD_DEFINITIONS("-DCERT_SVC_LOG") +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +ADD_DEFINITIONS("-DTIZENUCT_FEATURE_CERT_SVC_OCSP_CRL") +ENDIF() INCLUDE_DIRECTORIES(${VCORE_INCLUDES}) @@ -87,32 +136,33 @@ ADD_LIBRARY(${TARGET_VCORE_LIB} SHARED ${VCORE_SOURCES}) SET_TARGET_PROPERTIES(${TARGET_VCORE_LIB} PROPERTIES SOVERSION ${SO_VERSION} VERSION ${VERSION}) - +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) ADD_DEPENDENCIES(${TARGET_VCORE_LIB} Sqlite3DbWTF) +ENDIF() +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) TARGET_LINK_LIBRARIES(${TARGET_VCORE_LIB} ${VCORE_DEPS_LIBRARIES} ${TARGET_CERT_SVC_LIB} + dpl-db-efl ) - +ELSE() +TARGET_LINK_LIBRARIES(${TARGET_VCORE_LIB} + ${VCORE_DEPS_LIBRARIES} + ${TARGET_CERT_SVC_LIB} + ) +ENDIF () INSTALL(TARGETS ${TARGET_VCORE_LIB} DESTINATION ${LIB_INSTALL_DIR} ) INSTALL(FILES ${VCORE_SRC_DIR}/Base64.h - ${VCORE_SRC_DIR}/CachedCRL.h - ${VCORE_SRC_DIR}/CachedOCSP.h ${VCORE_SRC_DIR}/Certificate.h ${VCORE_SRC_DIR}/CertificateCollection.h ${VCORE_SRC_DIR}/CertStoreType.h - ${VCORE_SRC_DIR}/CRL.h - ${VCORE_SRC_DIR}/CRLCacheInterface.h ${VCORE_SRC_DIR}/CryptoHash.h - ${VCORE_SRC_DIR}/DeveloperModeValidator.h ${VCORE_SRC_DIR}/IAbstractResponseCache.h - ${VCORE_SRC_DIR}/OCSP.h - ${VCORE_SRC_DIR}/OCSPCertMgrUtil.h ${VCORE_SRC_DIR}/ParserSchema.h ${VCORE_SRC_DIR}/ReferenceValidator.h ${VCORE_SRC_DIR}/SaxReader.h @@ -126,16 +176,34 @@ INSTALL(FILES DESTINATION ${INCLUDEDIR}/cert-svc/vcore ) +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +INSTALL(FILES + ${VCORE_SRC_DIR}/CachedCRL.h + ${VCORE_SRC_DIR}/CachedOCSP.h + ${VCORE_SRC_DIR}/CRL.h + ${VCORE_SRC_DIR}/CRLCacheInterface.h + ${VCORE_SRC_DIR}/OCSP.h + ${VCORE_SRC_DIR}/OCSPCertMgrUtil.h + DESTINATION ${INCLUDEDIR}/cert-svc/vcore + ) +ENDIF() + INSTALL(FILES ${VCORE_DIR}/src/cert-svc/ccert.h - ${VCORE_DIR}/src/cert-svc/ccrl.h ${VCORE_DIR}/src/cert-svc/cinstance.h ${VCORE_DIR}/src/cert-svc/cerror.h - ${VCORE_DIR}/src/cert-svc/cocsp.h ${VCORE_DIR}/src/cert-svc/cpkcs12.h ${VCORE_DIR}/src/cert-svc/cprimitives.h ${VCORE_DIR}/src/cert-svc/cstring.h DESTINATION ${INCLUDEDIR}/cert-svc/cert-svc ) -#FILE(MAKE_DIRECTORY /opt/share/cert-svc/pkcs12) +IF(TIZEN_FEAT_PROFILE_CERT_SVC_OCSP_CRL) +INSTALL(FILES + ${VCORE_DIR}/src/cert-svc/ccrl.h + ${VCORE_DIR}/src/cert-svc/cocsp.h + DESTINATION ${INCLUDEDIR}/cert-svc/cert-svc + ) +ENDIF() + +#FILE(MAKE_DIRECTORY %{TZ_SYS_SHARE}/cert-svc/pkcs12) diff --git a/vcore/src/cert-svc/ccert.h b/vcore/src/cert-svc/ccert.h index dd288b2..d26837e 100644 --- a/vcore/src/cert-svc/ccert.h +++ b/vcore/src/cert-svc/ccert.h @@ -68,6 +68,16 @@ typedef enum CertSvcCertificateField_t { CERTSVC_SIGNATURE_ALGORITHM } CertSvcCertificateField; +typedef enum CertSvcVisibility_t { + CERTSVC_VISIBILITY_DEVELOPER = 1, + CERTSVC_VISIBILITY_TEST = 1 << 1, + CERTSVC_VISIBILITY_PUBLIC = 1 << 6, + CERTSVC_VISIBILITY_PARTNER = 1 << 7, + CERTSVC_VISIBILITY_PARTNER_OPERATOR = 1 << 8, + CERTSVC_VISIBILITY_PARTNER_MANUFACTURER = 1 << 9, + CERTSVC_VISIBILITY_PLATFORM = 1 << 10 +} CertSvcVisibility; + /** * Read certificate from file. Certificate must be in PEM/CER/DER format. * @@ -238,8 +248,10 @@ int certsvc_certificate_is_root_ca(CertSvcCertificate certificate, int *status); * } * certsvc_string_list_free(handler); // optional */ +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL int certsvc_certificate_get_crl_distribution_points(CertSvcCertificate certificate, CertSvcStringList *handler); +#endif /** * Sort certificates chain. This fuction modifies certificate_array. @@ -317,6 +329,42 @@ int certsvc_certificate_verify( int untrustedSize, int *status); +/** + * This function will create full chain and verify in. + * And this function checks the CA Flag strictly. + * + * First argument of function will be treatet as endentity certificate. + * + * This function will success if root CA certificate is stored in + * trusted array. + * + * @param[in] certificate Certificate to verify. + * @param[in] trusted Array with trusted certificates. + * @param[in] trustedSize Number of trusted certificates in array. + * @param[in] untrusted Array with untrusted certificates. + * @param[in] untrustedSize Number of untrusted certificate in array. + * @param[out] status Will be set only if function return CERTSVC_SUCCESS. + * It could be set to: CERTSVC_SUCCESS, CERTSVC_FAIL + * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT + */ +int certsvc_certificate_verify_with_caflag( + CertSvcCertificate certificate, + CertSvcCertificate *trusted, + int trustedSize, + CertSvcCertificate *untrusted, + int untrustedSize, + int *status); + +/** + * This function returns visibility of input certificate. + * + * @param[in] The root certificate to check visibility. + * @param[out] Visibility level + * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR + * + */ +int certsvc_certificate_get_visibility(CertSvcCertificate certificate, int* visibility); + #ifdef __cplusplus } #endif diff --git a/vcore/src/cert-svc/cocsp.h b/vcore/src/cert-svc/cocsp.h index da37d2b..f86816d 100644 --- a/vcore/src/cert-svc/cocsp.h +++ b/vcore/src/cert-svc/cocsp.h @@ -35,8 +35,8 @@ extern "C" { #define CERTSVC_OCSP_UNKNOWN (1<<2) #define CERTSVC_OCSP_VERIFICATION_ERROR (1<<3) #define CERTSVC_OCSP_NO_SUPPORT (1<<4) -#define CERTSVC_OCSP_ERROR (1<<5) - +#define CERTSVC_OCSP_CONNECTION_FAILED (1<<5) +#define CERTSVC_OCSP_ERROR (1<<6) /** * Implementation of ocsp call. * diff --git a/vcore/src/vcore/CRL.h b/vcore/src/vcore/CRL.h index 2acda27..51915ee 100644 --- a/vcore/src/vcore/CRL.h +++ b/vcore/src/vcore/CRL.h @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/vcore/src/vcore/CRLImpl.cpp b/vcore/src/vcore/CRLImpl.cpp index 776aa74..b2e18f9 100644 --- a/vcore/src/vcore/CRLImpl.cpp +++ b/vcore/src/vcore/CRLImpl.cpp @@ -35,8 +35,6 @@ #include #include #include -#include -#include #include #include @@ -47,7 +45,7 @@ #include namespace { -const char *CRL_LOOKUP_DIR_1 = "/usr/share/cert-svc/ca-certs/code-signing/wac"; +const char *CRL_LOOKUP_DIR_1 = tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/ca-certs/code-signing/wac"); const char *CRL_LOOKUP_DIR_2 = tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/certs/code-signing/wac"); } //anonymous namespace @@ -473,9 +471,9 @@ CRLImpl::CRLDataPtr CRLImpl::getCRL(const std::string &uri) const } std::string crlBody = decoder.get(); - DPL::ScopedArray bodyBuffer(new char[crlBody.length()]); - crlBody.copy(bodyBuffer.Get(), crlBody.length()); - return CRLDataPtr(new CRLData(bodyBuffer.Release(), crlBody.length(), + std::unique_ptr bodyBuffer(new char[crlBody.length()]); + crlBody.copy(bodyBuffer.get(), crlBody.length()); + return CRLDataPtr(new CRLData(bodyBuffer.release(), crlBody.length(), uri)); } diff --git a/vcore/src/vcore/CRLImpl.h b/vcore/src/vcore/CRLImpl.h index e9f90c4..72d8d43 100644 --- a/vcore/src/vcore/CRLImpl.h +++ b/vcore/src/vcore/CRLImpl.h @@ -24,7 +24,7 @@ #define _VALIDATION_CORE_ENGINE_CRLIMPL_H_ #include -#include +#include #include #include @@ -79,7 +79,7 @@ class CRLImpl : DPL::Noncopyable delete[] buffer; } }; - typedef DPL::SharedPtr CRLDataPtr; + typedef std::shared_ptr CRLDataPtr; CRLDataPtr getCRL(const std::string &uri) const; CRLDataPtr downloadCRL(const std::string &uri); diff --git a/vcore/src/vcore/CachedOCSP.cpp b/vcore/src/vcore/CachedOCSP.cpp index 5bff52a..c0e3695 100644 --- a/vcore/src/vcore/CachedOCSP.cpp +++ b/vcore/src/vcore/CachedOCSP.cpp @@ -123,13 +123,6 @@ VerificationStatus CachedOCSP::checkEndEntity(CertificateCollection &certs) OCSP ocsp; ocsp.setTrustedStore(certs.getCertificateList()); - const char *defResponderURI = getenv(OCSPImpl::DEFAULT_RESPONDER_URI_ENV); - - if (defResponderURI) { - ocsp.setUseDefaultResponder(true); - ocsp.setDefaultResponder(defResponderURI); - } - VerificationStatusSet statusSet = ocsp.validateCertificateList(clst); db_status.ocsp_status = statusSet.convertToStatus(); db_status.next_update_time = ocsp.getResponseValidity(); diff --git a/vcore/src/vcore/CertStoreType.cpp b/vcore/src/vcore/CertStoreType.cpp index 9122b4f..4a994b7 100644 --- a/vcore/src/vcore/CertStoreType.cpp +++ b/vcore/src/vcore/CertStoreType.cpp @@ -28,12 +28,30 @@ namespace CertStoreId { Set::Set() : m_certificateStorage(0) + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + , m_ocspUrl(NULL) + #endif {} void Set::add(Type second) { m_certificateStorage |= second; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +void Set::add(std::string ocspUrl) { + + if (strlen(ocspUrl.c_str()) == 0) + { + return; + } + + m_ocspUrl = new char[ocspUrl.size() + 1]; + if (m_ocspUrl != NULL) { + strncpy(m_ocspUrl, ocspUrl.c_str(), ocspUrl.size() + 1); + } +} +#endif + bool Set::contains(Type second) const { return static_cast(m_certificateStorage & second); } @@ -42,5 +60,11 @@ bool Set::isEmpty() const { return m_certificateStorage == 0; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +char* Set::getOcspUrl() { + return m_ocspUrl; +} +#endif + } // namespace CertStoreId } // namespace ValidationCore diff --git a/vcore/src/vcore/CertStoreType.h b/vcore/src/vcore/CertStoreType.h index ca24b18..e5f79a5 100644 --- a/vcore/src/vcore/CertStoreType.h +++ b/vcore/src/vcore/CertStoreType.h @@ -24,6 +24,9 @@ #ifndef _VALIDATION_CORE_CERTSTORETYPE_H_ #define _VALIDATION_CORE_CERTSTORETYPE_H_ +#include +#include + namespace ValidationCore { namespace CertStoreId { typedef unsigned int Type; @@ -32,7 +35,7 @@ typedef unsigned int Type; const Type TIZEN_DEVELOPER = 1; // RootCA certificates for author signatures. const Type TIZEN_TEST = 1 << 1; - +const Type TIZEN_VERIFY = 1 << 2; // RootCA's visibility level : public const Type VIS_PUBLIC = 1 << 6; // RootCA's visibility level : partner @@ -51,12 +54,19 @@ class Set void add(Type second); - bool contains(Type second) const; + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + void add(std::string ocspUrl); + char* getOcspUrl(); + #endif + bool contains(Type second) const; bool isEmpty() const; private: Type m_certificateStorage; + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + char* m_ocspUrl; + #endif }; } // namespace CertStoreId diff --git a/vcore/src/vcore/Certificate.cpp b/vcore/src/vcore/Certificate.cpp index 6ffedb1..37399dd 100644 --- a/vcore/src/vcore/Certificate.cpp +++ b/vcore/src/vcore/Certificate.cpp @@ -72,7 +72,9 @@ Certificate::Certificate(const std::string &der, Base64Decoder base64; base64.reset(); base64.append(der); - base64.finalize(); + if (!base64.finalize()) { + LogWarning("Error during decoding"); + } tmp = base64.get(); ptr = reinterpret_cast(tmp.c_str()); size = static_cast(tmp.size()); @@ -136,7 +138,7 @@ bool Certificate::isSignedBy(const CertificatePtr &parent) const Certificate::Fingerprint Certificate::getFingerprint( Certificate::FingerprintType type) const { - unsigned int fingerprintlength = EVP_MAX_MD_SIZE; //EVP_MAX_MD_SIZE is smaller than 2^64 + size_t fingerprintlength = EVP_MAX_MD_SIZE; unsigned char fingerprint[EVP_MAX_MD_SIZE]; Fingerprint raw; @@ -197,12 +199,12 @@ DPL::String Certificate::getOneLine(FieldType type) const return DPL::FromUTF8String(buffer); } -DPL::OptionalString Certificate::getField(FieldType type, +boost::optional Certificate::getField(FieldType type, int fieldNid) const { X509_NAME *subjectName = getX509Name(type); X509_NAME_ENTRY *subjectEntry = NULL; - DPL::Optional < DPL::String > output; + boost::optional < DPL::String > output; int entryCount = X509_NAME_entry_count(subjectName); for (int i = 0; i < entryCount; ++i) { @@ -241,45 +243,45 @@ DPL::OptionalString Certificate::getField(FieldType type, return output; } -DPL::OptionalString Certificate::getCommonName(FieldType type) const +boost::optional Certificate::getCommonName(FieldType type) const { return getField(type, NID_commonName); } -DPL::OptionalString Certificate::getCountryName(FieldType type) const +boost::optional Certificate::getCountryName(FieldType type) const { return getField(type, NID_countryName); } -DPL::OptionalString Certificate::getStateOrProvinceName(FieldType type) const +boost::optional Certificate::getStateOrProvinceName(FieldType type) const { return getField(type, NID_stateOrProvinceName); } -DPL::OptionalString Certificate::getLocalityName(FieldType type) const +boost::optional Certificate::getLocalityName(FieldType type) const { return getField(type, NID_localityName); } -DPL::OptionalString Certificate::getOrganizationName(FieldType type) const +boost::optional Certificate::getOrganizationName(FieldType type) const { return getField(type, NID_organizationName); } -DPL::OptionalString Certificate::getOrganizationalUnitName(FieldType type) const +boost::optional Certificate::getOrganizationalUnitName(FieldType type) const { return getField(type, NID_organizationalUnitName); } -DPL::OptionalString Certificate::getEmailAddres(FieldType type) const +boost::optional Certificate::getEmailAddres(FieldType type) const { return getField(type, NID_pkcs9_emailAddress); } -DPL::OptionalString Certificate::getOCSPURL() const +boost::optional Certificate::getOCSPURL() const { // TODO verify this code - DPL::OptionalString retValue; + boost::optional retValue; AUTHORITY_INFO_ACCESS *aia = static_cast( X509_get_ext_d2i(m_x509, NID_info_access, @@ -300,7 +302,7 @@ DPL::OptionalString Certificate::getOCSPURL() const ad->location->type == GEN_URI) { void* data = ASN1_STRING_data(ad->location->d.ia5); - retValue = DPL::OptionalString(DPL::FromUTF8String( + retValue = boost::optional(DPL::FromUTF8String( static_cast(data))); break; @@ -310,6 +312,8 @@ DPL::OptionalString Certificate::getOCSPURL() const return retValue; } + + Certificate::AltNameSet Certificate::getAlternativeNameDNS() const { AltNameSet set; @@ -391,9 +395,10 @@ ASN1_TIME* Certificate::getNotBeforeTime() const bool Certificate::isRootCert() { // based on that root certificate has the same subject as issuer name - return isSignedBy(this->SharedFromThis()); + return isSignedBy(this->shared_from_this()); } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL std::list Certificate::getCrlUris() const { @@ -441,6 +446,7 @@ Certificate::getCrlUris() const sk_DIST_POINT_pop_free(distPoints, DIST_POINT_free); return result; } +#endif long Certificate::getVersion() const { diff --git a/vcore/src/vcore/Certificate.h b/vcore/src/vcore/Certificate.h index d084dda..8611436 100644 --- a/vcore/src/vcore/Certificate.h +++ b/vcore/src/vcore/Certificate.h @@ -30,11 +30,10 @@ #include #include -#include -#include -#include -#include +#include #include +#include + #include @@ -51,10 +50,10 @@ namespace ValidationCore { class Certificate; -typedef DPL::SharedPtr CertificatePtr; +typedef std::shared_ptr CertificatePtr; typedef std::list CertificateList; -class Certificate : public DPL::EnableSharedFromThis +class Certificate : public std::enable_shared_from_this { public: typedef std::vector Fingerprint; @@ -111,17 +110,19 @@ class Certificate : public DPL::EnableSharedFromThis // getName uses deprecated functions. Usage is strongly discouraged. DPL::String getOneLine(FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getCommonName(FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getCountryName(FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getStateOrProvinceName( + + boost::optional getCommonName(FieldType type = FIELD_SUBJECT) const; + boost::optional getCountryName(FieldType type = FIELD_SUBJECT) const; + boost::optional getStateOrProvinceName( FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getLocalityName(FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getOrganizationName( + boost::optional getLocalityName(FieldType type = FIELD_SUBJECT) const; + boost::optional getOrganizationName( FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getOrganizationalUnitName( + boost::optional getOrganizationalUnitName( FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getEmailAddres(FieldType type = FIELD_SUBJECT) const; - DPL::OptionalString getOCSPURL() const; + boost::optional getEmailAddres(FieldType type = FIELD_SUBJECT) const; + boost::optional getOCSPURL() const; + // Openssl supports 9 types of alternative name filed. // 4 of them are "string similar" types so it is possible @@ -175,7 +176,7 @@ class Certificate : public DPL::EnableSharedFromThis protected: X509_NAME *getX509Name(FieldType type) const; - DPL::OptionalString getField(FieldType type, + boost::optional getField(FieldType type, int fieldNid) const; X509 *m_x509; diff --git a/vcore/src/vcore/CertificateCollection.cpp b/vcore/src/vcore/CertificateCollection.cpp index 27213c5..90d1d4e 100644 --- a/vcore/src/vcore/CertificateCollection.cpp +++ b/vcore/src/vcore/CertificateCollection.cpp @@ -37,7 +37,7 @@ inline std::string toBinaryString(int data) { char buffer[sizeof(int)]; memcpy(buffer, &data, sizeof(int)); - return std::string(buffer, buffer + sizeof(int)); + return std::string(buffer, sizeof(int)); } } // namespace diff --git a/vcore/src/vcore/CertificateConfigReader.cpp b/vcore/src/vcore/CertificateConfigReader.cpp index 2fcbbba..e98e747 100644 --- a/vcore/src/vcore/CertificateConfigReader.cpp +++ b/vcore/src/vcore/CertificateConfigReader.cpp @@ -33,8 +33,12 @@ const std::string TOKEN_CERTIFICATE_DOMAIN = "CertificateDomain"; const std::string TOKEN_FINGERPRINT_SHA1 = "FingerprintSHA1"; const std::string TOKEN_ATTR_NAME = "name"; +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +const std::string TOKEN_ATTR_URL_NAME = "ocspUrl"; +#endif const std::string TOKEN_VALUE_TIZEN_DEVELOPER = "tizen-developer"; const std::string TOKEN_VALUE_TIZEN_TEST = "tizen-test"; +const std::string TOKEN_VALUE_TIZEN_VERIFY = "tizen-verify"; const std::string TOKEN_VALUE_VISIBILITY_PUBLIC = "tizen-public"; const std::string TOKEN_VALUE_VISIBILITY_PARTNER = "tizen-partner"; const std::string TOKEN_VALUE_VISIBILITY_PARTNER_OPERATOR = "tizen-partner-operator"; @@ -95,7 +99,7 @@ CertificateConfigReader::CertificateConfigReader() : void CertificateConfigReader::tokenCertificateDomain(CertificateIdentifier &) { std::string name = m_parserSchema.getReader(). - attribute(TOKEN_ATTR_NAME, SaxReader::THROW_DISABLE); + attribute(TOKEN_ATTR_NAME, SaxReader::THROW_DISABLE); if (name.empty()) { LogWarning("Invalid fingerprint file. Domain name is mandatory"); @@ -105,6 +109,8 @@ void CertificateConfigReader::tokenCertificateDomain(CertificateIdentifier &) m_certificateDomain = CertStoreId::TIZEN_DEVELOPER; } else if (name == TOKEN_VALUE_TIZEN_TEST) { m_certificateDomain = CertStoreId::TIZEN_TEST; + } else if (name == TOKEN_VALUE_TIZEN_VERIFY) { + m_certificateDomain = CertStoreId::TIZEN_VERIFY; } else if (name == TOKEN_VALUE_VISIBILITY_PUBLIC) { m_certificateDomain = CertStoreId::VIS_PUBLIC; } else if (name == TOKEN_VALUE_VISIBILITY_PARTNER) { @@ -124,6 +130,10 @@ void CertificateConfigReader::tokenCertificateDomain(CertificateIdentifier &) void CertificateConfigReader::tokenEndFingerprintSHA1( CertificateIdentifier &identificator) { + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + std::string url = m_parserSchema.getReader().attribute(TOKEN_ATTR_URL_NAME, SaxReader::THROW_DISABLE); + #endif + std::string text = m_parserSchema.getText(); text += ":"; // add guard at the end of fingerprint Certificate::Fingerprint fingerprint; @@ -145,6 +155,10 @@ void CertificateConfigReader::tokenEndFingerprintSHA1( Assert(0 && "Unussported fingerprint format in xml file."); } } + identificator.add(fingerprint, m_certificateDomain); + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + identificator.add(fingerprint, url); + #endif } } // namespace ValidationCore diff --git a/vcore/src/vcore/CertificateIdentifier.h b/vcore/src/vcore/CertificateIdentifier.h index f9ed48c..0090d2c 100644 --- a/vcore/src/vcore/CertificateIdentifier.h +++ b/vcore/src/vcore/CertificateIdentifier.h @@ -25,7 +25,6 @@ _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_CERTIFICATEIDENTIFICATOR_H_ #include - #include #include "Certificate.h" @@ -34,7 +33,7 @@ namespace ValidationCore { class CertificateIdentifier : public DPL::Noncopyable { - public: +public: typedef std::map FingerPrintMap; CertificateIdentifier() @@ -50,6 +49,14 @@ class CertificateIdentifier : public DPL::Noncopyable fingerPrintMap[fingerprint].add(domain); } + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + void add(const Certificate::Fingerprint &fingerprint, + std::string ocspUrl) + { + fingerPrintMap[fingerprint].add(ocspUrl); + } + #endif + CertStoreId::Set find(const Certificate::Fingerprint &fingerprint) const { FingerPrintMap::const_iterator iter = fingerPrintMap.find(fingerprint); diff --git a/vcore/src/vcore/CertificateLoader.cpp b/vcore/src/vcore/CertificateLoader.cpp index 5aac8bb..038e0fc 100644 --- a/vcore/src/vcore/CertificateLoader.cpp +++ b/vcore/src/vcore/CertificateLoader.cpp @@ -22,7 +22,9 @@ #include #include +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL #include +#endif namespace { const int MIN_RSA_KEY_LENGTH = 1024; diff --git a/vcore/src/vcore/OCSPCertMgrUtil.cpp b/vcore/src/vcore/OCSPCertMgrUtil.cpp index f463d00..5db4290 100644 --- a/vcore/src/vcore/OCSPCertMgrUtil.cpp +++ b/vcore/src/vcore/OCSPCertMgrUtil.cpp @@ -21,9 +21,11 @@ #include #include +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +#include +#endif #include -#include #include #include #include @@ -147,7 +149,7 @@ void getCertFromStore(X509_NAME *subject, CertificatePtr getParentFromStore(const CertificatePtr &certificate) { - Assert(certificate.Get()); + Assert(certificate.get()); X509* rawPtr = certificate->getX509(); /* TODO Add getIssuerName function to Certificate.h */ @@ -159,7 +161,6 @@ CertificatePtr getParentFromStore(const CertificatePtr &certificate) if (rawTemp == NULL) { return CertificatePtr(); } - SSLSmartContainer scope(rawTemp); return CertificatePtr(new Certificate(rawTemp)); } @@ -172,7 +173,7 @@ CertificateList completeCertificateChain(const CertificateList &certificateList) return result; } CertificatePtr parent = getParentFromStore(last); - if (parent.Get()) { + if (parent.get()) { result.push_back(parent); } return result; diff --git a/vcore/src/vcore/OCSPImpl.cpp b/vcore/src/vcore/OCSPImpl.cpp index fb5bb18..face891 100644 --- a/vcore/src/vcore/OCSPImpl.cpp +++ b/vcore/src/vcore/OCSPImpl.cpp @@ -18,7 +18,7 @@ * @author Michal Ciepielski(m.ciepielski@samsung.com) * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com) * @version 0.4 - * @file OCPS.cpp + * @file OCSP.cpp * @brief Routines for certificate validation over OCSP */ @@ -43,14 +43,15 @@ #include #include +#include extern "C" { // This function is needed to fix "Invalid conversion from void* // to unsigned char*" C++ compiler error during calling // i2d_OCSP_REQUEST_bio macro - extern bool convertToBuffer(OCSP_REQUEST* req, - char** buf, - int* size); +extern bool convertToBuffer(OCSP_REQUEST* req, + char** buf, + int* size); } namespace { @@ -158,7 +159,7 @@ SoupWrapper::SoupMessageSendBase::RequestStatus OCSPImpl::sendOcspRequest( ValidationCore::VerificationStatusSet OCSPImpl::validateCertificateList( const CertificateList &certs) { - VerificationStatusSet statusSet; + VerificationStatusSet statusSet; if (certs.size() < 2) { // no certificates to verify, just return a error @@ -169,7 +170,17 @@ ValidationCore::VerificationStatusSet OCSPImpl::validateCertificateList( return statusSet; } - CertificateList::const_iterator iter = certs.begin(); + CertificatePtr root = certs.back(); + CertStoreId::Set storedSetId = createCertificateIdentifier().find(root); + char* ocspUrl = storedSetId.getOcspUrl(); + + if (ocspUrl != NULL) + { + setUseDefaultResponder(true); + setDefaultResponder(ocspUrl); + } + + CertificateList::const_iterator iter = certs.begin(); CertificateList::const_iterator parent = iter; time_t minValidity = 0; @@ -187,22 +198,16 @@ ValidationCore::VerificationStatusSet OCSPImpl::validateCertificateList( } m_responseValidity = minValidity; - return statusSet; + return statusSet; } VerificationStatus OCSPImpl::checkEndEntity( - const CertificateCollection &chain) + const CertificateCollection &chain) { - const char *defResponderURI = getenv(OCSPImpl::DEFAULT_RESPONDER_URI_ENV); - - VerificationStatusSet verSet; - if (defResponderURI) { - setUseDefaultResponder(true); - setDefaultResponder(defResponderURI); - } + // this is temporary fix. it must be rewriten + VerificationStatusSet verSet; - // this is temporary fix. it must be rewriten - CertificateList clst; + CertificateList clst; if (chain.isChain() && chain.size() >= 2) { CertificateList::const_iterator icert = chain.begin(); clst.push_back(*icert); @@ -211,7 +216,7 @@ VerificationStatus OCSPImpl::checkEndEntity( } verSet += validateCertificateList(clst); - return verSet.convertToStatus(); + return verSet.convertToStatus(); } VerificationStatus OCSPImpl::validateCertificate(CertificatePtr argCert, diff --git a/vcore/src/vcore/OCSPImpl.h b/vcore/src/vcore/OCSPImpl.h index 21e244f..451a244 100644 --- a/vcore/src/vcore/OCSPImpl.h +++ b/vcore/src/vcore/OCSPImpl.h @@ -38,7 +38,8 @@ #include #include -#include +#include + #include #include @@ -165,8 +166,10 @@ class OCSPImpl typedef std::pair HttpResponseBuffer; SoupWrapper::SoupMessageSendBase::RequestStatus sendOcspRequest( - OCSP_REQUEST* argRequest, - const DPL::OptionalString& argUri); + OCSP_REQUEST* argRequest, + const boost::optional& argUri); + + //! Validates a single certificate /*! diff --git a/vcore/src/vcore/OCSPUtil.c b/vcore/src/vcore/OCSPUtil.c index 451884a..314c7c2 100644 --- a/vcore/src/vcore/OCSPUtil.c +++ b/vcore/src/vcore/OCSPUtil.c @@ -25,6 +25,8 @@ * This function is needed to fix "Invalid conversion from void* to unsigned char*" * C++ compiler error during calling i2d_OCSP_REQUEST_bio macro */ +int convertToBuffer(OCSP_REQUEST *req, char **buf, int *size); + int convertToBuffer(OCSP_REQUEST *req, char **buf, int *size) { BIO *req_mem_bio; BUF_MEM req_bmem; diff --git a/vcore/src/vcore/SignatureValidator.cpp b/vcore/src/vcore/SignatureValidator.cpp index c0d1a6c..35ffaa3 100644 --- a/vcore/src/vcore/SignatureValidator.cpp +++ b/vcore/src/vcore/SignatureValidator.cpp @@ -20,10 +20,11 @@ * @brief Implementatin of tizen signature validation protocol. */ #include - +#include #include - +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL #include +#endif #include #include #include @@ -40,7 +41,7 @@ const std::string TOKEN_ROLE_DISTRIBUTOR_URI = const std::string TOKEN_PROFILE_URI = "http://www.w3.org/ns/widgets-digsig#profile"; -const char* TIZEN_STORE_CN = "Tizen Store"; +//const char* TIZEN_STORE_CN = "Tizen Store"; //un-used variable } // namespace anonymouse @@ -57,7 +58,7 @@ static tm _ASN1_GetTimeT(ASN1_TIME* time) { t.tm_year = (str[i++] - '0') * 10 + (str[++i] - '0'); if (t.tm_year < 70) - t.tm_year += 100; + t.tm_year += 100; } else if (time->type == V_ASN1_GENERALIZEDTIME) /* four digit year */ { @@ -91,9 +92,11 @@ public: explicit ImplSignatureValidator(bool ocspEnable, bool crlEnable, bool complianceMode) - : m_ocspEnable(ocspEnable) + : m_complianceModeEnabled(complianceMode) + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + , m_ocspEnable(ocspEnable) , m_crlEnable(crlEnable) - , m_complianceModeEnabled(complianceMode) + #endif {} virtual ~ImplSignatureValidator(){ } @@ -143,9 +146,11 @@ public: return true; } protected: + bool m_complianceModeEnabled; +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL bool m_ocspEnable; bool m_crlEnable; - bool m_complianceModeEnabled; +#endif }; class ImplTizenSignatureValidator : public SignatureValidator::ImplSignatureValidator @@ -214,6 +219,8 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( << storeIdSet.contains(CertStoreId::TIZEN_DEVELOPER)); LogDebug("Is root certificate from TIZEN_TEST domain: " << storeIdSet.contains(CertStoreId::TIZEN_TEST)); + LogDebug("Is root certificate from TIZEN_VERIFY domain: " + << storeIdSet.contains(CertStoreId::TIZEN_VERIFY)); LogDebug("Is root certificate from TIZEN_PUBLIC domain: " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Is root certificate from TIZEN_PARTNER domain: " @@ -240,7 +247,9 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( } else { - LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); +LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + //Additional Check for certificate registration + if (data.getSignatureNumber() == 1) { if (storeIdSet.contains(CertStoreId::VIS_PUBLIC) || storeIdSet.contains(CertStoreId::VIS_PARTNER) || storeIdSet.contains(CertStoreId::VIS_PLATFORM)) @@ -249,7 +258,7 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( } else { - LogWarning("author-signature.xml has got unrecognized Root CA " + LogWarning("signature1.xml has got unrecognized Root CA " "certificate. Signature will be disregarded."); disregard = true; } @@ -259,12 +268,17 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( data.setStorageType(storeIdSet); data.setSortedCertificateList(sortedCertificateList); + // We add only Root CA certificate because WAC ensure that the rest + // of certificates are present in signature files ;-) XmlSec::XmlSecContext context; context.signatureFile = data.getSignatureFileName(); context.certificatePtr = root; - if (!(root->isSignedBy(root))) { - LogWarning("Root CA certificate not found. Chain is incomplete."); + // Now we should have full certificate chain. + // If the end certificate is not ROOT CA we should disregard signature + // but still signature must be valid... Aaaaaa it's so stupid... + if (!(root->isSignedBy(root))) { + LogWarning("Root CA certificate not found. Chain is incomplete."); // context.allowBrokenChain = true; } @@ -277,29 +291,80 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( ASN1_TIME* notBeforeTime = data.getEndEntityCertificatePtr()->getNotBeforeTime(); if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) - { - struct tm *t; - struct tm ta; - char msg[1024]; - - t = localtime(&nowTime); - - sprintf(msg, "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); - LogDebug("## System's current Year : " << msg); - fprintf(stderr, "## System's current Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notBeforeTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notBefore Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notAfterTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notAfterTime Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - return SignatureValidator::SIGNATURE_INVALID; - } + { + struct tm *t; + struct tm ta, tb, tc; + char msg[1024]; + + t = localtime(&nowTime); + + memset(&tc, 0, sizeof(tc)); + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); + LogDebug("## System's currentTime : " << msg); + fprintf(stderr, "## System's currentTime : %s\n", msg); + + tb = _ASN1_GetTimeT(notBeforeTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tb.tm_year + 1900, tb.tm_mon + 1,tb.tm_mday ); + LogDebug("## certificate's notBeforeTime : " << msg); + fprintf(stderr, "## certificate's notBeforeTime : %s\n", msg); + + ta = _ASN1_GetTimeT(notAfterTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); + LogDebug("## certificate's notAfterTime : " << msg); + fprintf(stderr, "## certificate's notAfterTime : %s\n", msg); + + if (storeIdSet.contains(CertStoreId::TIZEN_VERIFY)) + { + LogDebug("## TIZEN_VERIFY : check certificate Time : FALSE"); + fprintf(stderr, "## TIZEN_VERIFY : check certificate Time : FALSE\n"); + return SignatureValidator::SIGNATURE_INVALID; + } + + int year = (ta.tm_year - tb.tm_year) / 4; + + if(year == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon + 1; + tc.tm_mday = tb.tm_mday; + + if(tc.tm_mon == 12) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon - 1; + tc.tm_mday = ta.tm_mday; + + if(tc.tm_mon < 0) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon; + tc.tm_mday = ta.tm_mday -1; + + if(tc.tm_mday == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon; + tc.tm_mday = tb.tm_mday +1; + } + } + } + } + else{ + tc.tm_year = tb.tm_year + year; + tc.tm_mon = (tb.tm_mon + ta.tm_mon )/2; + tc.tm_mday = (tb.tm_mday + ta.tm_mday)/2; + } + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tc.tm_year + 1900, tc.tm_mon + 1,tc.tm_mday ); + LogDebug("## cmp cert with validation time : " << msg); + fprintf(stderr, "## cmp cert with validation time : %s\n", msg); + + time_t outCurrent = mktime(&tc); + context.validationTime = outCurrent; + fprintf(stderr, "## cmp outCurrent time : %ld\n", outCurrent); + //return SignatureValidator::SIGNATURE_INVALID; + } #endif // WAC 2.0 SP-2066 The wrt must not block widget installation @@ -367,6 +432,7 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( } */ +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL // It is good time to do OCSP check // ocspCheck will throw an exception on any error. // TODO Probably we should catch this exception and add @@ -390,9 +456,12 @@ SignatureValidator::Result ImplTizenSignatureValidator::check( if (result == VERIFICATION_STATUS_UNKNOWN || result == VERIFICATION_STATUS_ERROR) { + #ifdef _OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ disregard = true; + #endif } } +#endif if (disregard) { LogWarning("Signature is disregard. RootCA is not a member of Tizen."); @@ -453,6 +522,8 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData << storeIdSet.contains(CertStoreId::TIZEN_DEVELOPER)); LogDebug("Is root certificate from TIZEN_TEST domain: " << storeIdSet.contains(CertStoreId::TIZEN_TEST)); + LogDebug("Is root certificate from TIZEN_VERIFY domain: " + << storeIdSet.contains(CertStoreId::TIZEN_VERIFY)); LogDebug("Is root certificate from TIZEN_PUBLIC domain: " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Is root certificate from TIZEN_PARTNER domain: " @@ -479,7 +550,9 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData } else { - LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + //Additional Check for certificate registration + if (data.getSignatureNumber() == 1) { if (storeIdSet.contains(CertStoreId::VIS_PUBLIC) || storeIdSet.contains(CertStoreId::VIS_PARTNER) || storeIdSet.contains(CertStoreId::VIS_PLATFORM)) @@ -488,7 +561,7 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData } else { - LogWarning("author-signature.xml has got unrecognized Root CA " + LogWarning("signature1.xml has got unrecognized Root CA " "certificate. Signature will be disregarded."); disregard = true; } @@ -522,31 +595,51 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData ASN1_TIME* notAfterTime = data.getEndEntityCertificatePtr()->getNotAfterTime(); ASN1_TIME* notBeforeTime = data.getEndEntityCertificatePtr()->getNotBeforeTime(); - + if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) { - struct tm *t; - struct tm ta; - char msg[1024]; - - t = localtime(&nowTime); - - sprintf(msg, "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); - LogDebug("## System's current Year : " << msg); - fprintf(stderr, "## System's current Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notBeforeTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notBefore Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notAfterTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notAfterTime Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - return SignatureValidator::SIGNATURE_INVALID; - } + struct tm *t; + struct tm ta, tb, tc; + char msg[1024]; + + t = localtime(&nowTime); + + memset(&tc, 0, sizeof(tc)); + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); + LogDebug("## System's currentTime : " << msg); + fprintf(stderr, "## System's currentTime : %s\n", msg); + + tb = _ASN1_GetTimeT(notBeforeTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tb.tm_year + 1900, tb.tm_mon + 1,tb.tm_mday ); + LogDebug("## certificate's notBeforeTime : " << msg); + fprintf(stderr, "## certificate's notBeforeTime : %s\n", msg); + + ta = _ASN1_GetTimeT(notAfterTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); + LogDebug("## certificate's notAfterTime : " << msg); + fprintf(stderr, "## certificate's notAfterTime : %s\n", msg); + + if (storeIdSet.contains(CertStoreId::TIZEN_VERIFY)) + { + LogDebug("## TIZEN_VERIFY : check certificate Time : FALSE"); + fprintf(stderr, "## TIZEN_VERIFY : check certificate Time : FALSE\n"); + return SignatureValidator::SIGNATURE_INVALID; + } + + int year = (ta.tm_year - tb.tm_year) / 4; + tc.tm_year = tb.tm_year + year; + tc.tm_mon = (tb.tm_mon + ta.tm_mon )/2; + tc.tm_mday = (tb.tm_mday + ta.tm_mday)/2; + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tc.tm_year + 1900, tc.tm_mon + 1,tc.tm_mday ); + LogDebug("## cmp cert with validation time : " << msg); + fprintf(stderr, "## cmp cert with validation time : %s\n", msg); + + time_t outCurrent = mktime(&tc); + context.validationTime = outCurrent; + //return SignatureValidator::SIGNATURE_INVALID; + } #endif @@ -614,7 +707,7 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData data.setReference(context.referenceSet); //if (!checkObjectReferences(data)) { // return SignatureValidator::SIGNATURE_INVALID; - //} + // } /* ReferenceValidator fileValidator(widgetContentPath); @@ -624,6 +717,7 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData } */ +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL // It is good time to do OCSP check // ocspCheck will throw an exception on any error. // TODO Probably we should catch this exception and add @@ -647,9 +741,12 @@ SignatureValidator::Result ImplTizenSignatureValidator::checkList(SignatureData if (result == VERIFICATION_STATUS_UNKNOWN || result == VERIFICATION_STATUS_ERROR) { + #ifdef _OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ disregard = true; + #endif } } +#endif if (disregard) { LogWarning("Signature is disregard. RootCA is not a member of Tizen."); @@ -733,6 +830,8 @@ SignatureValidator::Result ImplWacSignatureValidator::check( << storeIdSet.contains(CertStoreId::TIZEN_DEVELOPER)); LogDebug("Is root certificate from TIZEN_TEST domain: " << storeIdSet.contains(CertStoreId::TIZEN_TEST)); + LogDebug("Is root certificate from TIZEN_VERIFY domain: " + << storeIdSet.contains(CertStoreId::TIZEN_VERIFY)); LogDebug("Is root certificate from TIZEN_PUBLIC domain: " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Is root certificate from TIZEN_PARTNER domain: " @@ -758,6 +857,9 @@ SignatureValidator::Result ImplWacSignatureValidator::check( LogDebug("Root CA for author signature is correct."); } else { LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + + //Additional Check for certificate registration + if (data.getSignatureNumber() == 1) { if (storeIdSet.contains(CertStoreId::VIS_PUBLIC) || storeIdSet.contains(CertStoreId::VIS_PARTNER) || storeIdSet.contains(CertStoreId::VIS_PLATFORM)) @@ -766,7 +868,7 @@ SignatureValidator::Result ImplWacSignatureValidator::check( } else { - LogWarning("author-signature.xml has got unrecognized Root CA " + LogWarning("signature1.xml has got unrecognized Root CA " "certificate. Signature will be disregarded."); disregard = true; } @@ -799,32 +901,51 @@ SignatureValidator::Result ImplWacSignatureValidator::check( ASN1_TIME* notAfterTime = data.getEndEntityCertificatePtr()->getNotAfterTime(); ASN1_TIME* notBeforeTime = data.getEndEntityCertificatePtr()->getNotBeforeTime(); - - if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) + if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) { - struct tm *t; - struct tm ta; - char msg[1024]; - - t = localtime(&nowTime); - - sprintf(msg, "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); - LogDebug("## System's current Year : " << msg); - fprintf(stderr, "## System's current Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notBeforeTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notBefore Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - ta = _ASN1_GetTimeT(notAfterTime); - sprintf(msg, "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); - LogDebug("## certificate's notAfterTime Year : " << msg); - fprintf(stderr, "## certificate's notAfterTime Year : %s\n", msg); - - return SignatureValidator::SIGNATURE_INVALID; - } - + struct tm *t; + struct tm ta, tb, tc; + char msg[1024]; + + t = localtime(&nowTime); + + memset(&tc, 0, sizeof(tc)); + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); + LogDebug("## System's currentTime : " << msg); + fprintf(stderr, "## System's currentTime : %s\n", msg); + + tb = _ASN1_GetTimeT(notBeforeTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tb.tm_year + 1900, tb.tm_mon + 1,tb.tm_mday ); + LogDebug("## certificate's notBeforeTime : " << msg); + fprintf(stderr, "## certificate's notBeforeTime : %s\n", msg); + + ta = _ASN1_GetTimeT(notAfterTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); + LogDebug("## certificate's notAfterTime : " << msg); + fprintf(stderr, "## certificate's notAfterTime : %s\n", msg); + + if (storeIdSet.contains(CertStoreId::TIZEN_VERIFY)) + { + LogDebug("## TIZEN_VERIFY : check certificate Time : FALSE"); + fprintf(stderr, "## TIZEN_VERIFY : check certificate Time : FALSE\n"); + return SignatureValidator::SIGNATURE_INVALID; + } + + int year = (ta.tm_year - tb.tm_year) / 4; + tc.tm_year = tb.tm_year + year; + tc.tm_mon = (tb.tm_mon + ta.tm_mon )/2; + tc.tm_mday = (tb.tm_mday + ta.tm_mday)/2; + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tc.tm_year + 1900, tc.tm_mon + 1,tc.tm_mday ); + LogDebug("## cmp cert with validation time : " << msg); + fprintf(stderr, "## cmp cert with validation time : %s\n", msg); + + time_t outCurrent = mktime(&tc); + context.validationTime = outCurrent; + //return SignatureValidator::SIGNATURE_INVALID; + } + #endif #if 0 @@ -884,6 +1005,7 @@ SignatureValidator::Result ImplWacSignatureValidator::check( return SignatureValidator::SIGNATURE_INVALID; } + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL // It is good time to do OCSP check // ocspCheck will throw an exception on any error. // TODO Probably we should catch this exception and add @@ -907,9 +1029,12 @@ SignatureValidator::Result ImplWacSignatureValidator::check( if (result == VERIFICATION_STATUS_UNKNOWN || result == VERIFICATION_STATUS_ERROR) { + #ifdef _OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ disregard = true; + #endif } } +#endif if (disregard) { LogWarning("Signature is disregard. RootCA is not a member of Tizen."); diff --git a/vcore/src/vcore/VCore.cpp b/vcore/src/vcore/VCore.cpp index b714773..287b37f 100644 --- a/vcore/src/vcore/VCore.cpp +++ b/vcore/src/vcore/VCore.cpp @@ -21,23 +21,28 @@ #include #include +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL #include -#include #include +#endif +#include #include #include #include #include +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL namespace { DPL::DB::ThreadDatabaseSupport *threadInterface = NULL; } // namespace anonymous +#endif namespace ValidationCore { void AttachToThreadRO(void) { +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL Assert(threadInterface); static bool check = true; threadInterface->AttachToThread( @@ -48,12 +53,14 @@ void AttachToThreadRO(void) check = false; Assert(ThreadInterface().CheckTableExist(DB_CHECKSUM_STR) && "Not a valid vcore database version"); - } + } +#endif } void AttachToThreadRW(void) { - Assert(threadInterface); +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + Assert(threadInterface); static bool check = true; threadInterface->AttachToThread( DPL::DB::SqlConnection::Flag::RW); @@ -64,23 +71,27 @@ void AttachToThreadRW(void) Assert(ThreadInterface().CheckTableExist(DB_CHECKSUM_STR) && "Not a valid vcore database version"); } +#endif } void DetachFromThread(void){ +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL Assert(threadInterface); threadInterface->DetachFromThread(); +#endif } - +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL DPL::DB::ThreadDatabaseSupport& ThreadInterface(void) { Assert(threadInterface); return *threadInterface; } - +#endif bool VCoreInit(const std::string& configFilePath, const std::string& configSchemaPath, const std::string& databasePath) { - if(threadInterface) { +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + if(threadInterface) { LogDebug("Already Initialized"); return true; } @@ -88,7 +99,7 @@ bool VCoreInit(const std::string& configFilePath, threadInterface = new DPL::DB::ThreadDatabaseSupport( databasePath.c_str(), DPL::DB::SqlConnection::Flag::UseLucene); - +#endif SSL_library_init(); // g_thread_init(NULL); g_type_init(); @@ -103,9 +114,11 @@ bool VCoreInit(const std::string& configFilePath, void VCoreDeinit() { +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL Assert(threadInterface && "Not initialized or already deinitialized"); delete threadInterface; threadInterface = NULL; +#endif } } // namespace ValidationCore diff --git a/vcore/src/vcore/VCorePrivate.h b/vcore/src/vcore/VCorePrivate.h index ed85958..a2955b1 100644 --- a/vcore/src/vcore/VCorePrivate.h +++ b/vcore/src/vcore/VCorePrivate.h @@ -24,11 +24,15 @@ #include #include +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL #include #include +#endif namespace ValidationCore { +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL DPL::DB::ThreadDatabaseSupport& ThreadInterface(void); +#endif } // namespace ValidationCore #endif // _VCORE_SRC_VCORE_VCORE_H_ diff --git a/vcore/src/vcore/WrtSignatureValidator.cpp b/vcore/src/vcore/WrtSignatureValidator.cpp index 57a3618..654b05b 100644 --- a/vcore/src/vcore/WrtSignatureValidator.cpp +++ b/vcore/src/vcore/WrtSignatureValidator.cpp @@ -22,7 +22,6 @@ #include #include - #include #include #include @@ -41,6 +40,36 @@ const std::string TOKEN_PROFILE_URI = "http://www.w3.org/ns/widgets-digsig#profile"; } // namespace anonymouse +static tm _ASN1_GetTimeT(ASN1_TIME* time) +{ + struct tm t; + const char* str = (const char*) time->data; + size_t i = 0; + + memset(&t, 0, sizeof(t)); + + if (time->type == V_ASN1_UTCTIME) /* two digit year */ + { + t.tm_year = (str[i++] - '0') * 10 + (str[++i] - '0'); + if (t.tm_year < 70) + t.tm_year += 100; + } + else if (time->type == V_ASN1_GENERALIZEDTIME) /* four digit year */ + { + t.tm_year = (str[i++] - '0') * 1000 + (str[++i] - '0') * 100 + (str[++i] - '0') * 10 + (str[++i] - '0'); + t.tm_year -= 1900; + } + t.tm_mon = ((str[i++] - '0') * 10 + (str[++i] - '0')) - 1; // -1 since January is 0 not 1. + t.tm_mday = (str[i++] - '0') * 10 + (str[++i] - '0'); + t.tm_hour = (str[i++] - '0') * 10 + (str[++i] - '0'); + t.tm_min = (str[i++] - '0') * 10 + (str[++i] - '0'); + t.tm_sec = (str[i++] - '0') * 10 + (str[++i] - '0'); + + /* Note: we did not adjust the time based on time zone information */ + return t; +} + + namespace ValidationCore { class WrtSignatureValidator::Impl { @@ -52,9 +81,11 @@ public: explicit Impl(bool ocspEnable, bool crlEnable, bool complianceMode) - : m_ocspEnable(ocspEnable) + : m_complianceModeEnabled(complianceMode) + #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL + , m_ocspEnable(ocspEnable) , m_crlEnable(crlEnable) - , m_complianceModeEnabled(complianceMode) + #endif {} virtual ~Impl(){} @@ -104,9 +135,12 @@ public: return true; } protected: + bool m_complianceModeEnabled; +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL bool m_ocspEnable; bool m_crlEnable; - bool m_complianceModeEnabled; +#endif + }; class ImplTizen : public WrtSignatureValidator::Impl @@ -171,13 +205,14 @@ WrtSignatureValidator::Result ImplTizen::check( << storeIdSet.contains(CertStoreId::TIZEN_DEVELOPER)); LogDebug("Is root certificate from TIZEN_TEST domain: " << storeIdSet.contains(CertStoreId::TIZEN_TEST)); + LogDebug("Is root certificate from TIZEN_VERIFY domain: " + << storeIdSet.contains(CertStoreId::TIZEN_VERIFY)); LogDebug("Is root certificate from TIZEN_PUBLIC domain: " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Is root certificate from TIZEN_PARTNER domain: " << storeIdSet.contains(CertStoreId::VIS_PARTNER)); LogDebug("Is root certificate from TIZEN_PLATFORM domain: " << storeIdSet.contains(CertStoreId::VIS_PLATFORM)); - LogDebug("Visibility level is public : " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Visibility level is partner : " @@ -198,6 +233,7 @@ WrtSignatureValidator::Result ImplTizen::check( else { LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + if (data.getSignatureNumber() == 1) { if (storeIdSet.contains(CertStoreId::VIS_PUBLIC) || storeIdSet.contains(CertStoreId::VIS_PARTNER) || storeIdSet.contains(CertStoreId::VIS_PLATFORM)) @@ -206,7 +242,7 @@ WrtSignatureValidator::Result ImplTizen::check( } else { - LogWarning("author-signature.xml has got unrecognized Root CA " + LogWarning("signature1.xml has got unrecognized Root CA " "certificate. Signature will be disregarded."); disregard = true; } @@ -227,7 +263,7 @@ WrtSignatureValidator::Result ImplTizen::check( // but still signature must be valid... Aaaaaa it's so stupid... if (!(root->isSignedBy(root))) { LogWarning("Root CA certificate not found. Chain is incomplete."); - context.allowBrokenChain = true; + //context.allowBrokenChain = true; } // WAC 2.0 SP-2066 The wrt must not block widget installation @@ -239,20 +275,84 @@ WrtSignatureValidator::Result ImplTizen::check( ASN1_TIME* notAfterTime = data.getEndEntityCertificatePtr()->getNotAfterTime(); ASN1_TIME* notBeforeTime = data.getEndEntityCertificatePtr()->getNotBeforeTime(); - if (data.isAuthorSignature()) - { - if (X509_cmp_time(notBeforeTime, &nowTime) > 0) - { - LogDebug("notBeforeTime is greater then current time"); - return WrtSignatureValidator::SIGNATURE_INVALID; - } + if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) + { + struct tm *t; + struct tm ta, tb, tc; + char msg[1024]; + + t = localtime(&nowTime); + + memset(&tc, 0, sizeof(tc)); + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); + LogDebug("## System's currentTime : " << msg); + fprintf(stderr, "## System's currentTime : %s\n", msg); + + tb = _ASN1_GetTimeT(notBeforeTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tb.tm_year + 1900, tb.tm_mon + 1,tb.tm_mday ); + LogDebug("## certificate's notBeforeTime : " << msg); + fprintf(stderr, "## certificate's notBeforeTime : %s\n", msg); + + ta = _ASN1_GetTimeT(notAfterTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); + LogDebug("## certificate's notAfterTime : " << msg); + fprintf(stderr, "## certificate's notAfterTime : %s\n", msg); + + if (storeIdSet.contains(CertStoreId::TIZEN_VERIFY)) + { + LogDebug("## TIZEN_VERIFY : check certificate Time : FALSE"); + fprintf(stderr, "## TIZEN_VERIFY : check certificate Time : FALSE\n"); + return WrtSignatureValidator::SIGNATURE_INVALID; + } + + int year = (ta.tm_year - tb.tm_year) / 4; + + if(year == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon + 1; + tc.tm_mday = tb.tm_mday; + + if(tc.tm_mon == 12) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon - 1; + tc.tm_mday = ta.tm_mday; + + if(tc.tm_mon < 0) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon; + tc.tm_mday = ta.tm_mday -1; + + if(tc.tm_mday == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon; + tc.tm_mday = tb.tm_mday +1; + } + } + } + } + else{ + tc.tm_year = tb.tm_year + year; + tc.tm_mon = (tb.tm_mon + ta.tm_mon )/2; + tc.tm_mday = (tb.tm_mday + ta.tm_mday)/2; + } + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tc.tm_year + 1900, tc.tm_mon + 1,tc.tm_mday ); + LogDebug("## cmp cert with validation time : " << msg); + fprintf(stderr, "## cmp cert with validation time : %s\n", msg); + + time_t outCurrent = mktime(&tc); + context.validationTime = outCurrent; + + fprintf(stderr, "## cmp outCurrent time : %ld\n", outCurrent); + + //return WrtSignatureValidator::SIGNATURE_INVALID; + } - if (X509_cmp_time(notAfterTime, &nowTime) < 0) - { - LogDebug("notAfterTime is less then current time"); - return WrtSignatureValidator::SIGNATURE_INVALID; - } - } #endif #if 0 @@ -316,6 +416,7 @@ WrtSignatureValidator::Result ImplTizen::check( return WrtSignatureValidator::SIGNATURE_INVALID; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL // It is good time to do OCSP check // ocspCheck will throw an exception on any error. // TODO Probably we should catch this exception and add @@ -339,9 +440,12 @@ WrtSignatureValidator::Result ImplTizen::check( if (result == VERIFICATION_STATUS_UNKNOWN || result == VERIFICATION_STATUS_ERROR) { + #ifdef _OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ disregard = true; + #endif } } +#endif if (disregard) { LogWarning("Signature is disregard. RootCA is not a member of Tizen"); @@ -412,6 +516,8 @@ WrtSignatureValidator::Result ImplWac::check( << storeIdSet.contains(CertStoreId::TIZEN_DEVELOPER)); LogDebug("Is root certificate from TIZEN_TEST domain: " << storeIdSet.contains(CertStoreId::TIZEN_TEST)); + LogDebug("Is root certificate from TIZEN_VERIFY domain: " + << storeIdSet.contains(CertStoreId::TIZEN_VERIFY)); LogDebug("Is root certificate from TIZEN_PUBLIC domain: " << storeIdSet.contains(CertStoreId::VIS_PUBLIC)); LogDebug("Is root certificate from TIZEN_PARTNER domain: " @@ -439,6 +545,8 @@ WrtSignatureValidator::Result ImplWac::check( else { LogDebug("signaturefile name = " << data.getSignatureFileName().c_str()); + //Additional Check for certificate registration + if (data.getSignatureNumber() == 1) { if (storeIdSet.contains(CertStoreId::VIS_PUBLIC) || storeIdSet.contains(CertStoreId::VIS_PARTNER) || storeIdSet.contains(CertStoreId::VIS_PLATFORM)) @@ -447,7 +555,7 @@ WrtSignatureValidator::Result ImplWac::check( } else { - LogWarning("author-signature.xml has got unrecognized Root CA " + LogWarning("signature1.xml has got unrecognized Root CA " "certificate. Signature will be disregarded."); disregard = true; } @@ -468,7 +576,7 @@ WrtSignatureValidator::Result ImplWac::check( // but still signature must be valid... Aaaaaa it's so stupid... if (!(root->isSignedBy(root))) { LogWarning("Root CA certificate not found. Chain is incomplete."); - context.allowBrokenChain = true; +// context.allowBrokenChain = true; } time_t nowTime = time(NULL); @@ -480,20 +588,84 @@ WrtSignatureValidator::Result ImplWac::check( ASN1_TIME* notAfterTime = data.getEndEntityCertificatePtr()->getNotAfterTime(); ASN1_TIME* notBeforeTime = data.getEndEntityCertificatePtr()->getNotBeforeTime(); - if (data.isAuthorSignature()) - { - if (X509_cmp_time(notBeforeTime, &nowTime) > 0) - { - LogDebug("notBeforeTime is greater then current time"); - return WrtSignatureValidator::SIGNATURE_INVALID; - } + if (X509_cmp_time(notBeforeTime, &nowTime) > 0 || X509_cmp_time(notAfterTime, &nowTime) < 0) + { + struct tm *t; + struct tm ta, tb, tc; + char msg[1024]; + + t = localtime(&nowTime); + + memset(&tc, 0, sizeof(tc)); + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", t->tm_year + 1900, t->tm_mon + 1,t->tm_mday ); + LogDebug("## System's currentTime : " << msg); + fprintf(stderr, "## System's currentTime : %s\n", msg); + + tb = _ASN1_GetTimeT(notBeforeTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tb.tm_year + 1900, tb.tm_mon + 1,tb.tm_mday ); + LogDebug("## certificate's notBeforeTime : " << msg); + fprintf(stderr, "## certificate's notBeforeTime : %s\n", msg); + + ta = _ASN1_GetTimeT(notAfterTime); + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", ta.tm_year + 1900, ta.tm_mon + 1,ta.tm_mday ); + LogDebug("## certificate's notAfterTime : " << msg); + fprintf(stderr, "## certificate's notAfterTime : %s\n", msg); + + if (storeIdSet.contains(CertStoreId::TIZEN_VERIFY)) + { + LogDebug("## TIZEN_VERIFY : check certificate Time : FALSE"); + fprintf(stderr, "## TIZEN_VERIFY : check certificate Time : FALSE\n"); + return WrtSignatureValidator::SIGNATURE_INVALID; + } + + int year = (ta.tm_year - tb.tm_year) / 4; + + if(year == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon + 1; + tc.tm_mday = tb.tm_mday; + + if(tc.tm_mon == 12) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon - 1; + tc.tm_mday = ta.tm_mday; + + if(tc.tm_mon < 0) + { + tc.tm_year = ta.tm_year; + tc.tm_mon = ta.tm_mon; + tc.tm_mday = ta.tm_mday -1; + + if(tc.tm_mday == 0) + { + tc.tm_year = tb.tm_year; + tc.tm_mon = tb.tm_mon; + tc.tm_mday = tb.tm_mday +1; + } + } + } + } + else{ + tc.tm_year = tb.tm_year + year; + tc.tm_mon = (tb.tm_mon + ta.tm_mon )/2; + tc.tm_mday = (tb.tm_mday + ta.tm_mday)/2; + } + + snprintf(msg, sizeof(msg), "Year: %d, month: %d, day : %d", tc.tm_year + 1900, tc.tm_mon + 1,tc.tm_mday ); + LogDebug("## cmp cert with validation time : " << msg); + fprintf(stderr, "## cmp cert with validation time : %s\n", msg); + + time_t outCurrent = mktime(&tc); + + fprintf(stderr, "## cmp outCurrent time : %ld\n", outCurrent); + + context.validationTime = outCurrent; + //return WrtSignatureValidator::SIGNATURE_INVALID; + } - if (X509_cmp_time(notAfterTime, &nowTime) < 0) - { - LogDebug("notAfterTime is less then current time"); - return WrtSignatureValidator::SIGNATURE_INVALID; - } - } #endif #if 0 @@ -553,6 +725,7 @@ WrtSignatureValidator::Result ImplWac::check( return WrtSignatureValidator::SIGNATURE_INVALID; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL // It is good time to do OCSP check // ocspCheck will throw an exception on any error. // TODO Probably we should catch this exception and add @@ -576,9 +749,12 @@ WrtSignatureValidator::Result ImplWac::check( if (result == VERIFICATION_STATUS_UNKNOWN || result == VERIFICATION_STATUS_ERROR) { +#ifdef _OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ disregard = true; +#endif //_OCSP_POLICY_DISREGARD_UNKNOWN_OR_ERROR_CERTS_ } } +#endif if (disregard) { LogWarning("Signature is disregard. RootCA is not a member of Tizen."); diff --git a/vcore/src/vcore/XmlsecAdapter.cpp b/vcore/src/vcore/XmlsecAdapter.cpp index dc89397..c1d4529 100644 --- a/vcore/src/vcore/XmlsecAdapter.cpp +++ b/vcore/src/vcore/XmlsecAdapter.cpp @@ -126,12 +126,12 @@ void XmlSec::fileExtractPrefix(XmlSecContext *context) } } -void LogDebugPrint(const char* file, int line, const char* func, - const char* errorObject, const char* errorSubject, +void LogDebugPrint(const char* file, int line, const char* func, + const char* errorObject, const char* errorSubject, int reason, const char* msg) { char total[1024]; - sprintf(total, "[%s(%d)] : [%s] : [%s] : [%s]", func, line, errorObject, errorSubject, msg); + snprintf(total, sizeof(total), "[%s(%d)] : [%s] : [%s] : [%s]", func, line, errorObject, errorSubject, msg); if(reason != 256) { @@ -306,7 +306,7 @@ XmlSec::Result XmlSec::validateFile(XmlSecContext *context, char* uri = NULL; int len; - for(itr; itr != m_pList->end(); ++itr) { + for(; itr != m_pList->end(); ++itr) { tmpString = (*itr); uri = (char*)tmpString.c_str(); len = strlen(uri); @@ -458,7 +458,7 @@ XmlSec::Result XmlSec::validate(XmlSecContext *context) { Assert(context); Assert(!(context->signatureFile.empty())); - Assert(context->certificatePtr.Get() || !(context->certificatePath.empty())); + Assert(context->certificatePtr.get() || !(context->certificatePath.empty())); xmlSecErrorsSetCallback(LogDebugPrint); @@ -480,7 +480,7 @@ XmlSec::Result XmlSec::validate(XmlSecContext *context) } context->referenceSet.clear(); - if (context->certificatePtr.Get()) { + if (context->certificatePtr.get()) { loadDERCertificateMemory(context, mngr.get()); } diff --git a/vcore/src/vcore/api.cpp b/vcore/src/vcore/api.cpp index 297395b..742b434 100644 --- a/vcore/src/vcore/api.cpp +++ b/vcore/src/vcore/api.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include #include @@ -52,26 +52,34 @@ #include #include -#include #include -#include #include #include #include #include #include +#include + +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL +#include +#include #include #include #include -#include +#endif + +#include +#include +#define LOG_TAG "CERT_SVC" using namespace ValidationCore; namespace { typedef std::unique_ptr > ScopedCertCtx; +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL class CRLCacheCAPI : public CRLCacheInterface { public: CRLCacheCAPI( @@ -124,6 +132,7 @@ private: CertSvcCrlFree m_crlFree; void *m_userParam; }; +#endif class CertSvcInstanceImpl { public: @@ -131,9 +140,11 @@ public: : m_certificateCounter(0) , m_idListCounter(0) , m_stringListCounter(0) +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL , m_crlWrite(NULL) , m_crlRead(NULL) , m_crlFree(NULL) +#endif {} ~CertSvcInstanceImpl(){ @@ -232,13 +243,14 @@ public: } auto certPtr = iter->second; - DPL::OptionalString result; + + boost::optional result; switch(field) { case CERTSVC_SUBJECT: - result = DPL::OptionalString(certPtr->getOneLine()); + result = boost::optional(certPtr->getOneLine()); break; case CERTSVC_ISSUER: - result = DPL::OptionalString(certPtr->getOneLine(Certificate::FIELD_ISSUER)); + result = boost::optional(certPtr->getOneLine(Certificate::FIELD_ISSUER)); break; case CERTSVC_SUBJECT_COMMON_NAME: result = certPtr->getCommonName(); @@ -274,26 +286,26 @@ public: { std::stringstream stream; stream << (certPtr->getVersion()+1); - result = DPL::OptionalString(DPL::FromUTF8String(stream.str())); + result = boost::optional(DPL::FromUTF8String(stream.str())); break; } case CERTSVC_SERIAL_NUMBER: - result = DPL::OptionalString(certPtr->getSerialNumberString()); + result = boost::optional(certPtr->getSerialNumberString()); break; case CERTSVC_KEY_USAGE: - result = DPL::OptionalString(certPtr->getKeyUsageString()); + result = boost::optional(certPtr->getKeyUsageString()); break; case CERTSVC_KEY: - result = DPL::OptionalString(certPtr->getPublicKeyString()); + result = boost::optional(certPtr->getPublicKeyString()); break; case CERTSVC_SIGNATURE_ALGORITHM: - result = DPL::OptionalString(certPtr->getSignatureAlgorithmString()); + result = boost::optional(certPtr->getSignatureAlgorithmString()); break; default: break; } - if (result.IsNull()) { + if (!result) { buffer->privateHandler = NULL; buffer->privateLength = 0; buffer->privateInstance = cert.privateInstance; @@ -302,6 +314,13 @@ public: std::string output = DPL::ToUTF8String(*result); char *cstring = new char[output.size()+1]; + if (cstring == NULL) { + buffer->privateHandler = NULL; + buffer->privateLength = 0; + buffer->privateInstance = cert.privateInstance; + return CERTSVC_BAD_ALLOC; + } + strncpy(cstring, output.c_str(), output.size()+1); buffer->privateHandler = cstring; @@ -348,6 +367,7 @@ public: return CERTSVC_SUCCESS; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL inline int getCrl(const CertSvcCertificate &cert, CertSvcStringList *handler){ auto iter = m_certificateMap.find(cert.privateHandler); if (iter == m_certificateMap.end()) { @@ -365,6 +385,7 @@ public: return CERTSVC_SUCCESS; } +#endif inline int getStringFromList( const CertSvcStringList &handler, @@ -516,7 +537,7 @@ public: if (cert == m_certificateMap.end()) { return CERTSVC_WRONG_ARGUMENT; } - translator[cert->second.Get()] = pos; + translator[cert->second.get()] = pos; certList.push_back(cert->second); } @@ -531,7 +552,7 @@ public: int i=0; for (auto iter = chain.begin(); iter != chain.end() && iGet()]; + certificate_array[i].privateHandler = translator[iter->get()]; } return CERTSVC_SUCCESS; @@ -566,6 +587,7 @@ public: return CERTSVC_SUCCESS; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL inline int ocspCheck(const CertSvcCertificate *chain, int chain_size, const CertSvcCertificate *trusted, @@ -642,6 +664,9 @@ public: if (statusSet.contains(VERIFICATION_STATUS_NOT_SUPPORT)) { ret |= CERTSVC_OCSP_NO_SUPPORT; } + if (statusSet.contains(VERIFICATION_STATUS_CONNECTION_FAILED)) { + ret |= CERTSVC_OCSP_CONNECTION_FAILED; + } if (statusSet.contains(VERIFICATION_STATUS_ERROR)) { ret |= CERTSVC_OCSP_ERROR; } @@ -649,6 +674,7 @@ public: *status = ret; return CERTSVC_SUCCESS; } +#endif inline int verify( CertSvcCertificate certificate, @@ -746,6 +772,9 @@ public: base.finalize(); info = base.get(); char *ptr = new char[info.size()+1]; + if(ptr == NULL) { + return CERTSVC_BAD_ALLOC; + } memcpy(ptr, info.c_str(), info.size()+1); m_allocatedStringSet.insert(ptr); base64->privateHandler = ptr; @@ -770,6 +799,9 @@ public: } info = base.get(); char *ptr = new char[info.size()+1]; + if(ptr == NULL) { + return CERTSVC_BAD_ALLOC; + } memcpy(ptr, info.c_str(), info.size()+1); m_allocatedStringSet.insert(ptr); message->privateHandler = ptr; @@ -794,6 +826,9 @@ public: allocSize++; char *ptr = new char[allocSize]; + if(ptr == NULL) { + return CERTSVC_BAD_ALLOC; + } memcpy(ptr, str, size); ptr[allocSize-1] = 0; @@ -806,6 +841,7 @@ public: return CERTSVC_SUCCESS; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL inline void setCRLFunction( CertSvcCrlCacheWrite writePtr, CertSvcCrlCacheRead readPtr, @@ -867,6 +903,7 @@ public: return CERTSVC_SUCCESS; } +#endif inline int certificateVerify( CertSvcCertificate certificate, @@ -874,6 +911,7 @@ public: int trustedSize, CertSvcCertificate *untrusted, int untrustedSize, + int checkCaFlag, int *status) { if (!trusted || !status) { @@ -913,6 +951,20 @@ public: X509_STORE_CTX context; X509_STORE_CTX_init(&context, store, cert, ustore); int result = X509_verify_cert(&context); + + if(result == 1 && checkCaFlag) { // check strictly + STACK_OF(X509) *resultChain = X509_STORE_CTX_get1_chain(&context); + X509* tmpCert = NULL; + int caFlagValidity; + while((tmpCert = sk_X509_pop(resultChain))) { + caFlagValidity = X509_check_ca(tmpCert); + if(caFlagValidity != 1 && (tmpCert = sk_X509_pop(resultChain)) != NULL) { // the last one is not a CA. + result = 0; + break; + } + } + } + X509_STORE_CTX_cleanup(&context); X509_STORE_free(store); sk_X509_free(ustore); @@ -925,6 +977,103 @@ public: return CERTSVC_SUCCESS; } + int getVisibility(CertSvcCertificate certificate, int* visibility) + { + int ret = CERTSVC_FAIL; + xmlChar *xmlPathCertificateSet = (xmlChar*) "CertificateSet"; + xmlChar *xmlPathCertificateDomain = (xmlChar*) "CertificateDomain";// name=\"tizen-platform\""; + xmlChar *xmlPathDomainPlatform = (xmlChar*) "tizen-platform"; + xmlChar *xmlPathDomainPublic = (xmlChar*) "tizen-public"; + xmlChar *xmlPathDomainPartner = (xmlChar*) "tizen-partner"; + xmlChar *xmlPathDomainDeveloper = (xmlChar*) "tizen-developer"; + xmlChar *xmlPathFingerPrintSHA1 = (xmlChar*) "FingerprintSHA1"; + + CertificatePtr certPtr = m_certificateMap[0]; + if(certPtr == NULL) + { + LOGE("Invalid Parameter. certificate is not initialized"); + return CERTSVC_FAIL; + } + std::string fingerprint = Certificate::FingerprintToColonHex(certPtr->getFingerprint(Certificate::FINGERPRINT_SHA1)); + + /* load file */ + xmlDocPtr doc = xmlParseFile(tzplatform_mkpath(TZ_SYS_SHARE, "ca-certificates/fingerprint/fingerprint_list.xml")); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)) + { + LOGE("Failed to prase fingerprint_list.xml\n"); + return CERTSVC_IO_ERROR; + } + + xmlNodePtr curPtr = xmlFirstElementChild(xmlDocGetRootElement(doc)); + if(curPtr == NULL) + { + LOGE("Can not find root"); + ret = CERTSVC_IO_ERROR; + goto out; + } + + while(curPtr != NULL) + { + xmlAttr* attr = curPtr->properties; + if(!attr->children || !attr->children->content) + { + LOGE("Failed to get fingerprints from list"); + ret = CERTSVC_FAIL; + goto out; + } + + xmlChar* strLevel = attr->children->content; + xmlNodePtr FpPtr = xmlFirstElementChild(curPtr); + if(FpPtr == NULL) + { + LOGE("Could not find fingerprint"); + ret = CERTSVC_FAIL; + goto out; + } + + LOGD("Retrieve level : %s", strLevel); + while(FpPtr) + { + xmlChar *content = xmlNodeGetContent(FpPtr); + if(xmlStrcmp(content, (xmlChar*)fingerprint.c_str()) == 0) + { + LOGD("fingerprint : %s are %s", content, strLevel); + if(!xmlStrcmp(strLevel, xmlPathDomainPlatform)) + { + *visibility = CERTSVC_VISIBILITY_PLATFORM; + ret = CERTSVC_SUCCESS; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainPublic)) + { + *visibility = CERTSVC_VISIBILITY_PUBLIC; + ret = CERTSVC_SUCCESS; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainPartner)) + { + *visibility = CERTSVC_VISIBILITY_PARTNER; + ret = CERTSVC_SUCCESS; + goto out; + } + else if(!xmlStrcmp(strLevel, xmlPathDomainDeveloper)) + { + *visibility = CERTSVC_VISIBILITY_DEVELOPER; + ret = CERTSVC_SUCCESS; + goto out; + } + } + FpPtr = xmlNextElementSibling(FpPtr); + } + curPtr = xmlNextElementSibling(curPtr); + } + xmlFreeDoc(doc); + return CERTSVC_FAIL; +out: + xmlFreeDoc(doc); + return ret; + } + inline int pkcsNameIsUnique( CertSvcString pfxIdString, int *is_unique) @@ -1038,9 +1187,11 @@ private: std::set m_allocatedStringSet; +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL CertSvcCrlCacheWrite m_crlWrite; CertSvcCrlCacheRead m_crlRead; CertSvcCrlFree m_crlFree; +#endif }; inline CertSvcInstanceImpl *impl(CertSvcInstance instance) { @@ -1137,7 +1288,8 @@ int certsvc_certificate_new_from_memory( void certsvc_certificate_free(CertSvcCertificate certificate) { - impl(certificate.privateInstance)->removeCert(certificate); + if (certificate.privateHandler != 0) + impl(certificate.privateInstance)->removeCert(certificate); } int certsvc_certificate_save_file( @@ -1231,6 +1383,7 @@ int certsvc_certificate_is_root_ca(CertSvcCertificate certificate, int *status) return impl(certificate.privateInstance)->isRootCA(certificate, status); } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL int certsvc_certificate_get_crl_distribution_points( CertSvcCertificate certificate, CertSvcStringList *handler) @@ -1240,6 +1393,7 @@ int certsvc_certificate_get_crl_distribution_points( } catch (...) {} return CERTSVC_FAIL; } +#endif int certsvc_string_list_get_one( CertSvcStringList handler, @@ -1263,12 +1417,17 @@ int certsvc_string_list_get_length( void certsvc_string_list_free(CertSvcStringList handler) { - impl(handler.privateInstance)->removeStringList(handler); + if (handler.privateHandler != 0) + { + impl(handler.privateInstance)->removeStringList(handler); + handler.privateHandler = 0; + } } void certsvc_string_free(CertSvcString string) { - impl(string.privateInstance)->removeString(string); + if (string.privateHandler) + impl(string.privateInstance)->removeString(string); } void certsvc_string_to_cstring( @@ -1310,7 +1469,8 @@ int certsvc_certificate_dup_x509(CertSvcCertificate certificate, X509 **cert) void certsvc_certificate_free_x509(X509 *x509) { - X509_free(x509); + if (x509) + X509_free(x509); } int certsvc_pkcs12_dup_evp_pkey( @@ -1362,6 +1522,7 @@ void certsvc_pkcs12_free_evp_pkey(EVP_PKEY* pkey) EVP_PKEY_free(pkey); } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL int certsvc_ocsp_check( CertSvcCertificate *chain, int chain_size, @@ -1386,6 +1547,7 @@ int certsvc_ocsp_check( } catch (...) {} return CERTSVC_FAIL; } +#endif int certsvc_message_verify( CertSvcCertificate certificate, @@ -1448,6 +1610,7 @@ int certsvc_string_not_managed( return CERTSVC_SUCCESS; } +#ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL void certsvc_crl_cache_functions( CertSvcInstance instance, CertSvcCrlCacheWrite writePtr, @@ -1476,6 +1639,7 @@ int certsvc_crl_check( } catch (...) {} return CERTSVC_FAIL; } +#endif int certsvc_certificate_verify( CertSvcCertificate certificate, @@ -1486,17 +1650,52 @@ int certsvc_certificate_verify( int *status) { try { + int check_caflag_false = 0; + return impl(certificate.privateInstance)->certificateVerify( + certificate, + trusted, + trustedSize, + untrusted, + untrustedSize, + check_caflag_false, + status); + } catch (...) {} + return CERTSVC_FAIL; +} + +int certsvc_certificate_verify_with_caflag( + CertSvcCertificate certificate, + CertSvcCertificate *trusted, + int trustedSize, + CertSvcCertificate *untrusted, + int untrustedSize, + int *status) +{ + try { + int check_caflag_true = 1; return impl(certificate.privateInstance)->certificateVerify( certificate, trusted, trustedSize, untrusted, untrustedSize, + check_caflag_true, status); } catch (...) {} return CERTSVC_FAIL; } +int certsvc_certificate_get_visibility(CertSvcCertificate certificate, int* visibility) +{ + try { + return impl(certificate.privateInstance)->getVisibility(certificate, visibility); + } catch (...) + { + LOGE("exception occur"); + } + return CERTSVC_FAIL; +} + int certsvc_pkcs12_alias_exists(CertSvcInstance instance, CertSvcString pfxIdString, int *is_unique) diff --git a/vcore/src/vcore/pkcs12.c b/vcore/src/vcore/pkcs12.c index 84524ed..1239dda 100755 --- a/vcore/src/vcore/pkcs12.c +++ b/vcore/src/vcore/pkcs12.c @@ -22,6 +22,8 @@ #define _GNU_SOURCE #define _CERT_SVC_VERIFY_PKCS12 +#include +#include "cert-service-util.h" #include "pkcs12.h" #include #include @@ -39,12 +41,29 @@ #include #include #include +#include #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) #define CERTSVC_PKCS12_STORAGE_DIR tzplatform_mkpath(TZ_SYS_SHARE, "cert-svc/pkcs12") #define CERTSVC_PKCS12_STORAGE_FILE "storage" #define CERTSVC_PKCS12_STORAGE_PATH tzplatform_mkpath3(TZ_SYS_SHARE,"cert-svc/pkcs12", CERTSVC_PKCS12_STORAGE_FILE) +#define MAX_PASSWORD_SIZE 32 +#define MAX_SEND_DATA_SIZE 4096 // internal buffer = 4KB + +typedef enum +{ + SSA_PARAM_ERROR = TIZEN_ERROR_SYSTEM_CLASS | 0x01, /** < Invalid parameters */ + SSA_AUTHENTICATION_ERROR = TIZEN_ERROR_SYSTEM_CLASS | 0x02, /** < Authentication error */ + SSA_TZ_ERROR = TIZEN_ERROR_SYSTEM_CLASS | 0x03, /** < Trust zone error */ + SSA_SOCKET_ERROR = TIZEN_ERROR_CONNECTION, /** < Connection error */ + SSA_PERMISSION_ERROR = TIZEN_ERROR_PERMISSION_DENIED, /** < Permission denied */ + SSA_SECURITY_SERVER_ERROR = TIZEN_ERROR_SYSTEM_CLASS | 0x04,/** < Security server error */ + SSA_CIPHER_ERROR = TIZEN_ERROR_SYSTEM_CLASS | 0x05, /** < Encryption / Decryption error */ + SSA_IO_ERROR = TIZEN_ERROR_IO_ERROR, /** < I/O error */ + SSA_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /** < Out of memory */ + SSA_UNKNOWN_ERROR = TIZEN_ERROR_UNKNOWN, /** < Unknown error */ +} ssa_error_e; static const char CERTSVC_PKCS12_STORAGE_KEY_PKEY[] = "pkey"; static const char CERTSVC_PKCS12_STORAGE_KEY_CERTS[] = "certs"; @@ -120,19 +139,29 @@ static int unique_filename(char **filepath, gboolean with_secure_storage) { int result; ssm_file_info_t sfi; gboolean exists; + char* data = NULL; + char* tempfilepath = NULL; trial = 0U; try_again: ++trial; - result = generate_random_filepath(filepath); + result = generate_random_filepath(&tempfilepath); if(result != CERTSVC_SUCCESS) return result; if(with_secure_storage) - exists = (access(*filepath, F_OK) == 0 || ssm_getinfo(*filepath, &sfi, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP) == 0); + exists = (access(*tempfilepath, F_OK) == 0 || ssm_getinfo(*filepath, &sfi, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP) == 0); else - exists = (access(*filepath, F_OK) == 0); - if(exists) { - free(*filepath); + exists = (access(*tempfilepath, F_OK) == 0); + + if(!exists) { + *filepath = tempfilepath; + } + else { + if(data){ + free(data); + data = NULL; + } + free(tempfilepath); if(trial + 1 > attempts) return CERTSVC_FAIL; else @@ -173,9 +202,10 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar STACK_OF(X509) *certv; int nicerts; char *unique; - int result; + int result = 0; struct stat st; int wr_res; + void* dlHandle = NULL; GKeyFile *keyfile; gchar *bare; gchar *pkvalue; @@ -185,6 +215,8 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar gsize length; static int initFlag = 0; const char appInfo[] = "certsvcp12"; + int readLen = 0; + char fileBuffer[4096] = {0,}; certv = NULL; pkvalue = NULL; @@ -216,10 +248,28 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar result = CERTSVC_FAIL; goto free_keyfile; } + +#ifdef TIZEN_FEATURE_OSP_DISABLE + LOGD("TIZEN_FEAT_OSP_DISABLE is 1"); +#endif + +#ifndef TIZEN_FEATURE_OSP_DISABLE + LOGD("TIZEN_FEAT_OSP_DISABLE is 0"); +#endif + +#ifndef TIZEN_FEATURE_OSP_DISABLE + dlHandle = dlopen("/usr/lib/osp/libosp-appfw.so", RTLD_LAZY); + if (!dlHandle) + { + LOGD("Failed to open so with reason : %s", dlerror()); + goto free_keyfile; + } +#endif result = PKCS12_parse(container, password, &key, &cert, &certv); PKCS12_free(container); if (result == 0) { + LOGD("Failed to parse PKCS12"); result = CERTSVC_FAIL; goto free_keyfile; } @@ -253,7 +303,7 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar if (strcmp((const char*)pSubject, (const char*)pIssuerName) == 0) { //self signed.. - isSelfSigned = 1; + //isSelfSigned = 1; EVP_PKEY* pKey = X509_get_pubkey(cert); if (!pKey) @@ -279,7 +329,7 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar } else { - isSelfSigned = 0; + //isSelfSigned = 0; int res = 0; X509_STORE_CTX *cert_ctx = NULL; X509_STORE *cert_store = NULL; @@ -435,15 +485,27 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar result = unique_filename(&unique, TRUE); if(result != CERTSVC_SUCCESS) goto clean_cert_chain_and_pkey; - if((stream = fopen(unique, "w")) == NULL) { + if((stream = fopen(unique, "w+")) == NULL) { free(unique); result = CERTSVC_IO_ERROR; goto clean_cert_chain_and_pkey; } result = PEM_write_PrivateKey(stream, key, NULL, NULL, 0, NULL, NULL); - fclose(stream); if(result == 0) { result = CERTSVC_FAIL; + fclose(stream); + free(unique); + goto clean_cert_chain_and_pkey; + } + + fseek(stream, 0, SEEK_SET); + + readLen = fread(fileBuffer, sizeof(char), 4096, stream); + fclose(stream); + if(readLen <= 0){ + free(unique); + result = CERTSVC_FAIL; + SLOGE("failed to read key file"); goto clean_cert_chain_and_pkey; } wr_res = ssm_write_file(unique, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP); @@ -452,6 +514,8 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar result = CERTSVC_FAIL; goto clean_cert_chain_and_pkey; } + unlink(unique); + bare = bare_filename(unique); if(bare) { pkvalue = g_strdup(bare); @@ -476,7 +540,7 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar if(bare) cvaluev[n++] = g_strdup(bare); free(unique); - for(i = 0; i < nicerts; i++) { + for(i = 0; i < (unsigned int)nicerts; i++) { result = unique_filename(&unique, FALSE); if(result != CERTSVC_SUCCESS) goto clean_cert_chain_and_pkey; @@ -509,57 +573,50 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar } result = CERTSVC_SUCCESS; -#if 1 - SECURE_LOGD("( %s, %s)", path, password); - void* pSymAddr = NULL; - void* pInitAddr = NULL; - typedef int (*InsertPkcs12FuncPointer)(const char*, const char*); - typedef void (*InitAppInfoPointer)(const char*, const char*); + SECURE_LOGD("( %s, %s)", path, password); +#ifndef TIZEN_FEATURE_OSP_DISABLE - InsertPkcs12FuncPointer pInsertPkcs12FuncPointer = NULL; - InitAppInfoPointer pInit = NULL; + typedef int (*InsertPkcs12FuncPointer)(const char*, const char*); + typedef void (*InitAppInfoPointer)(const char*, const char*); - void* dlHandle = dlopen("/usr/lib/osp/libosp-appfw.so", RTLD_LAZY); - if (!dlHandle) - { - LOGD("Failed to open so with reason : %s", dlerror()); - goto free_data; - } + InsertPkcs12FuncPointer pInsertPkcs12FuncPointer = NULL; + InitAppInfoPointer pInit = NULL; - pInsertPkcs12FuncPointer = (InsertPkcs12FuncPointer)dlsym(dlHandle, "InsertPkcs12Content"); - if (dlerror() != NULL) - { - LOGD("Failed to find InsertPkcs12Content symbol : %s", dlerror()); - goto free_data; - } - if(initFlag == 0) - { - pInit = (InitAppInfoPointer)dlsym(dlHandle, "InitWebAppInfo"); - if (dlerror() != NULL) - { - LOGD("Failed to find InitWebAppInfo symbol : %s", dlerror()); - goto free_data; - } + pInsertPkcs12FuncPointer = (InsertPkcs12FuncPointer)dlsym(dlHandle, "InsertPkcs12Content"); + if (dlerror() != NULL) + { + LOGD("Failed to find InsertPkcs12Content symbol : %s", dlerror()); + result = CERTSVC_FAIL; + goto free_data; + } - pInit(appInfo, NULL); - initFlag = 1; - } + if(initFlag == 0) + { + pInit = (InitAppInfoPointer)dlsym(dlHandle, "InitWebAppInfo"); + if (dlerror() != NULL) + { + LOGD("Failed to find InitWebAppInfo symbol : %s", dlerror()); + result = CERTSVC_FAIL; + goto free_data; + } + + pInit(appInfo, NULL); + initFlag = 1; + } - int errCode = pInsertPkcs12FuncPointer(path, password); - if (errCode != 0) - { - LOGD("dlHandle is not able to call function"); - goto free_data; - } - dlclose(dlHandle); + int errCode = pInsertPkcs12FuncPointer(path, password); + if (errCode != 0) + { + LOGD("dlHandle is not able to call function"); + c_certsvc_pkcs12_delete(alias); + result = CERTSVC_FAIL; + goto free_data; + } #endif - free_data: g_free(data); - if(dlHandle){ - dlclose(dlHandle); - } + clean_cert_chain_and_pkey: EVP_PKEY_free(key); X509_free(cert); @@ -571,6 +628,11 @@ int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar free(cvaluev); free_keyfile: g_key_file_free(keyfile); +#ifndef TIZEN_FEATURE_OSP_DISABLE + if(dlHandle){ + dlclose(dlHandle); + } +#endif return result; } @@ -702,6 +764,109 @@ void c_certsvc_pkcs12_private_key_free(char *buffer) { free(buffer); } +static void _delete_from_osp_cert_mgr(const char* path); + +static void +_delete_from_osp_cert_mgr(const char* path) +{ + + typedef int (*RemoveUserCertificatePointer)(unsigned char*, int); + typedef void (*InitAppInfoPointer)(const char*, const char*); + + static int initFlag = 0; + + unsigned char* pCertBuffer = NULL; + int certBufferLen = 0; + const char appInfo[] = "certsvcp12"; + + RemoveUserCertificatePointer pRemoveUserCertificatePointer = NULL; + InitAppInfoPointer pInit = NULL; + void* dlHandle = dlopen("/usr/lib/osp/libosp-appfw.so", RTLD_LAZY); + if (!dlHandle) + { + LOGD("Failed to open so with reason : %s", dlerror()); + goto end_of_func; + } + + pRemoveUserCertificatePointer = (RemoveUserCertificatePointer)dlsym(dlHandle, "RemoveUserCertificate"); + if (dlerror() != NULL) + { + LOGD("Failed to find RemoveUserCertificate symbol : %s", dlerror()); + goto end_of_func; + } + + if(initFlag == 0) + { + pInit = (InitAppInfoPointer)dlsym(dlHandle, "InitWebAppInfo"); + if (dlerror() != NULL) + { + LOGD("Failed to find InitWebAppInfo symbol : %s", dlerror()); + goto end_of_func; + } + + pInit(appInfo, NULL); + initFlag = 1; + } + + int result = certsvc_load_file_to_buffer(path, &pCertBuffer, &certBufferLen); + if (result != 0 ) + { + LOGD("certsvc_load_file_to_buffer Failed."); + goto end_of_func; + } + int errCode = pRemoveUserCertificatePointer(pCertBuffer, certBufferLen); + if (errCode != 0) + { + LOGD("dlHandle is not able to call function"); + goto end_of_func; + } + +end_of_func: + + if(dlHandle){ + dlclose(dlHandle); + } + return; +} + + +int certsvc_load_file_to_buffer(const char* filePath, unsigned char** certBuf, int* length) +{ + int ret = CERT_SVC_ERR_NO_ERROR; + FILE* fp_in = NULL; + unsigned long int fileSize = 0; + + /* get file size */ + if((ret = cert_svc_get_file_size(filePath, &fileSize)) != CERT_SVC_ERR_NO_ERROR) { + SECURE_SLOGE("[ERR][%s] Fail to get file size, [%s]\n", __func__, filePath); + return CERT_SVC_ERR_FILE_IO; + } + /* open file and write to buffer */ + if(!(fp_in = fopen(filePath, "rb"))) { + SECURE_SLOGE("[ERR][%s] Fail to open file, [%s]\n", __func__, filePath); + return CERT_SVC_ERR_FILE_IO; + } + + if(!(*certBuf = (unsigned char*)malloc(sizeof(unsigned char) * (unsigned int)(fileSize + 1)))) { + SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__); + ret = CERT_SVC_ERR_MEMORY_ALLOCATION; + goto err; + } + memset(*certBuf, 0x00, (fileSize + 1)); + if(fread(*certBuf, sizeof(unsigned char), fileSize, fp_in) != fileSize) { + SECURE_SLOGE("[ERR][%s] Fail to read file, [%s]\n", __func__, filePath); + ret = CERT_SVC_ERR_FILE_IO; + goto err; + } + + *length = fileSize; + +err: + if(fp_in != NULL) + fclose(fp_in); + return ret; +} + int c_certsvc_pkcs12_delete(const gchar *alias) { gchar **certs; gsize ncerts; @@ -733,8 +898,12 @@ int c_certsvc_pkcs12_delete(const gchar *alias) { goto data_free; } } + + _delete_from_osp_cert_mgr(certs[0]); for(i = 0; i < ncerts; i++) + { unlink(certs[i]); + } if(pkey != NULL) { if(asprintf(&spkp, "%s/%s", CERTSVC_PKCS12_STORAGE_DIR, pkey) == -1) { result = CERTSVC_BAD_ALLOC; @@ -753,3 +922,25 @@ int c_certsvc_pkcs12_delete(const gchar *alias) { load_certificates_failed: return result; } + + +int cert_svc_get_file_size(const char* filepath, unsigned long int* length) +{ + int ret = CERT_SVC_ERR_NO_ERROR; + FILE* fp_in = NULL; + + if(!(fp_in = fopen(filepath, "r"))) { + SECURE_SLOGE("[ERR][%s] Fail to open file, [%s]\n", __func__, filepath); + ret = CERT_SVC_ERR_FILE_IO; + goto err; + } + + fseek(fp_in, 0L, SEEK_END); + (*length) = ftell(fp_in); + +err: + if(fp_in != NULL) + fclose(fp_in); + + return ret; +} diff --git a/vcore/src/vcore/pkcs12.h b/vcore/src/vcore/pkcs12.h index eca7a7a..c7ae668 100644 --- a/vcore/src/vcore/pkcs12.h +++ b/vcore/src/vcore/pkcs12.h @@ -38,6 +38,9 @@ void c_certsvc_pkcs12_free_certificates(gchar **certs); int c_certsvc_pkcs12_private_key_load(const gchar *alias, char **pkey, gsize *count); void c_certsvc_pkcs12_private_key_free(char *buffer); int c_certsvc_pkcs12_delete(const gchar *alias); +//static void _delete_from_osp_cert_mgr(const char* path); +int certsvc_load_file_to_buffer(const char* filePath, unsigned char** certBuf, int* length); +int cert_svc_get_file_size(const char* filepath, unsigned long int* length); #ifdef __cplusplus }