Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
cs_der_certs.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // ---------------------------------------------------------------------------- 00016 00017 #include "pv_error_handling.h" 00018 #include "cs_der_certs.h" 00019 #include "cs_der_keys.h" 00020 #include "cs_hash.h" 00021 #include "pal.h" 00022 #include "cs_utils.h" 00023 #include "stdbool.h" 00024 #include "fcc_malloc.h" 00025 00026 00027 static kcm_status_e cs_get_x509_cert_attribute_type(cs_certificate_attribute_type_e cs_attribute_type, palX509Attr_t *attribute_type) 00028 { 00029 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00030 00031 00032 switch (cs_attribute_type) { 00033 case CS_CN_ATTRIBUTE_TYPE: 00034 *attribute_type = PAL_X509_CN_ATTR; 00035 break; 00036 case CS_VALID_TO_ATTRIBUTE_TYPE: 00037 *attribute_type = PAL_X509_VALID_TO; 00038 break; 00039 case CS_VALID_FROM_ATTRIBUTE_TYPE: 00040 *attribute_type = PAL_X509_VALID_FROM; 00041 break; 00042 case CS_OU_ATTRIBUTE_TYPE: 00043 *attribute_type = PAL_X509_OU_ATTR; 00044 break; 00045 case CS_SUBJECT_ATTRIBUTE_TYPE: 00046 *attribute_type = PAL_X509_SUBJECT_ATTR; 00047 break; 00048 case CS_ISSUER_ATTRIBUTE_TYPE: 00049 *attribute_type = PAL_X509_ISSUER_ATTR; 00050 break; 00051 case CS_CERT_ID_ATTR: 00052 *attribute_type = PAL_X509_CERT_ID_ATTR; 00053 break; 00054 default: 00055 SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_CRYPTO_STATUS_INVALID_X509_ATTR, "Invalid cert attribute"); 00056 } 00057 00058 return kcm_status; 00059 } 00060 00061 kcm_status_e cs_is_self_signed_x509_cert(palX509Handle_t x509_cert, bool *is_self_signed) 00062 { 00063 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00064 palStatus_t pal_status = PAL_SUCCESS; 00065 00066 uint8_t *cert_subject = NULL; 00067 uint8_t *cert_issuer = NULL; 00068 size_t subject_size = 0, issuer_size = 0; 00069 00070 //Self-signed certificate is certificate with subject attribute = issuer attribute 00071 //get and check issuer and subject sizes 00072 kcm_status = cs_attr_get_data_size_x509_cert(x509_cert, CS_SUBJECT_ATTRIBUTE_TYPE, &subject_size); 00073 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "get size PAL_X509_SUBJECT_ATTR failed"); 00074 00075 kcm_status = cs_attr_get_data_size_x509_cert(x509_cert, CS_ISSUER_ATTRIBUTE_TYPE, &issuer_size); 00076 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "get size PAL_X509_ISSUER_ATTR failed"); 00077 00078 //If issuer and subject attributes have different length it is not self-signed certificate 00079 if (subject_size != issuer_size) { 00080 *is_self_signed = false; 00081 return KCM_STATUS_SUCCESS; 00082 } 00083 00084 //Get and check attributes values 00085 cert_subject = fcc_malloc(subject_size); 00086 SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_subject == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, exit, "Allocate subject attribute failed"); 00087 00088 pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_SUBJECT_ATTR, cert_subject, subject_size, &subject_size); 00089 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit,"pal_x509CertGetAttribute PAL_X509_SUBJECT_ATTR failed %d ", (int)cs_error_handler(pal_status)); 00090 00091 cert_issuer = fcc_malloc(issuer_size); 00092 SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_subject == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, exit, "Allocate issuer attribute failed"); 00093 00094 pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_ISSUER_ATTR, cert_issuer, issuer_size, &issuer_size); 00095 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertGetAttribute PAL_X509_ISSUER_ATTR failed %d", (int)kcm_status); 00096 00097 if (memcmp(cert_issuer, cert_subject, issuer_size) == 0) { 00098 *is_self_signed = true; 00099 } else { 00100 *is_self_signed = false; 00101 } 00102 00103 exit: 00104 fcc_free(cert_subject); 00105 fcc_free(cert_issuer); 00106 00107 return kcm_status; 00108 } 00109 00110 kcm_status_e cs_create_handle_from_der_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t *x509_cert_handle) 00111 { 00112 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00113 palStatus_t pal_status = PAL_SUCCESS; 00114 00115 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert != NULL && cert_length == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length"); 00116 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert_handler"); 00117 00118 //Allocate and Init certificate handler 00119 pal_status = pal_x509Initiate(x509_cert_handle); 00120 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "pal_x509Initiate failed"); 00121 00122 if (cert != NULL) { 00123 //Parse Certificate. 00124 pal_status = pal_x509CertParse(*x509_cert_handle, cert, cert_length); 00125 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertParse failed"); 00126 } 00127 00128 exit: 00129 if (pal_status != PAL_SUCCESS) { 00130 pal_x509Free(x509_cert_handle); 00131 } 00132 00133 return kcm_status; 00134 } 00135 kcm_status_e cs_add_to_chain_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t x509_chain_handle) 00136 { 00137 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00138 palStatus_t pal_status = PAL_SUCCESS; 00139 00140 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid cert pointer"); 00141 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length"); 00142 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_chain_handle == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_chain_handle"); 00143 00144 //Parse Certificate. 00145 pal_status = pal_x509CertParse(x509_chain_handle, cert, cert_length); 00146 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509CertParse failed"); 00147 00148 return kcm_status; 00149 } 00150 kcm_status_e cs_close_handle_x509_cert(palX509Handle_t *x509_cert_handle) 00151 { 00152 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00153 palStatus_t pal_status = PAL_SUCCESS; 00154 00155 pal_status = pal_x509Free(x509_cert_handle); 00156 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509Free failed"); 00157 00158 return kcm_status; 00159 } 00160 kcm_status_e cs_parse_der_x509_cert(const uint8_t *cert, size_t cert_length) 00161 { 00162 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00163 palStatus_t pal_status = PAL_SUCCESS; 00164 palX509Handle_t x509_cert = NULLPTR; 00165 00166 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid cert pointer"); 00167 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length"); 00168 00169 //Allocate and Init certificate handler 00170 pal_status = pal_x509Initiate(&x509_cert); 00171 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "pal_x509Initiate failed"); 00172 00173 //Parse Certificate. 00174 pal_status = pal_x509CertParse(x509_cert, cert, cert_length); 00175 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertParse failed"); 00176 00177 exit: 00178 pal_x509Free(&x509_cert); 00179 return kcm_status; 00180 } 00181 00182 kcm_status_e cs_verify_x509_cert(palX509Handle_t x509_cert,palX509Handle_t x509_cert_chain) 00183 { 00184 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00185 palStatus_t pal_status = PAL_SUCCESS; 00186 bool is_self_signed = false; 00187 palX509Handle_t x509_ca_cert = NULLPTR; 00188 00189 00190 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid cert handle"); 00191 00192 kcm_status = cs_is_self_signed_x509_cert(x509_cert, &is_self_signed); 00193 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Self signed verification failed"); 00194 00195 if (is_self_signed && x509_cert_chain == NULLPTR) { // Send the certificate itself as trusted chain 00196 x509_ca_cert = x509_cert; 00197 } else { 00198 x509_ca_cert = x509_cert_chain; 00199 } 00200 00201 //Verify certificate using created certificate chain 00202 pal_status = pal_x509CertVerify(x509_cert, x509_ca_cert); 00203 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertVerify failed %" PRIu32 "", pal_status); 00204 00205 exit: 00206 return kcm_status; 00207 } 00208 00209 kcm_status_e cs_attr_get_data_size_x509_cert(palX509Handle_t x509_cert, 00210 cs_certificate_attribute_type_e cs_attribute_type, 00211 size_t *size_of_attribute) 00212 { 00213 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00214 palX509Attr_t attribute_type; 00215 palStatus_t pal_status = PAL_SUCCESS; 00216 uint8_t output_buffer; 00217 00218 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert"); 00219 SA_PV_ERR_RECOVERABLE_RETURN_IF((size_of_attribute == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid size_of_attribute pointer"); 00220 00221 kcm_status = cs_get_x509_cert_attribute_type(cs_attribute_type, &attribute_type); 00222 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_get_x509_cert_attribute_type failed"); 00223 00224 //Get the attribute size 00225 pal_status = pal_x509CertGetAttribute(x509_cert, attribute_type, &output_buffer, 0, size_of_attribute); 00226 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), KCM_STATUS_ERROR, "Attribute size is 0"); 00227 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_ERR_BUFFER_TOO_SMALL ), kcm_status = cs_error_handler(pal_status), "Failed to get attribute size"); 00228 00229 return KCM_STATUS_SUCCESS; 00230 }; 00231 00232 kcm_status_e cs_attr_get_data_x509_cert(palX509Handle_t x509_cert, 00233 cs_certificate_attribute_type_e cs_attribute_type, 00234 uint8_t *attribute_output_buffer, 00235 size_t max_size_of_attribute_output_buffer, 00236 size_t *actual_size_of_attribute_output_buffer) 00237 { 00238 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00239 palX509Attr_t attribute_type; 00240 palStatus_t pal_status = PAL_SUCCESS; 00241 00242 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert"); 00243 SA_PV_ERR_RECOVERABLE_RETURN_IF((attribute_output_buffer == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid output pointer"); 00244 SA_PV_ERR_RECOVERABLE_RETURN_IF((actual_size_of_attribute_output_buffer == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid actual_size_of_output pointer"); 00245 00246 kcm_status = cs_get_x509_cert_attribute_type(cs_attribute_type, &attribute_type); 00247 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_get_x509_cert_attribute_type failed"); 00248 00249 //Get the attribute 00250 pal_status = pal_x509CertGetAttribute(x509_cert, attribute_type, attribute_output_buffer, max_size_of_attribute_output_buffer, actual_size_of_attribute_output_buffer); 00251 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509CertGetAttribute failed"); 00252 00253 return kcm_status; 00254 }; 00255 00256 kcm_status_e cs_x509_cert_verify_signature(palX509Handle_t x509_cert, const unsigned char *hash, size_t hash_size, const unsigned char *signature, size_t signature_size) 00257 { 00258 00259 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00260 palStatus_t pal_status = PAL_SUCCESS; 00261 00262 SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert"); 00263 SA_PV_ERR_RECOVERABLE_RETURN_IF((hash == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid hash pointer"); 00264 SA_PV_ERR_RECOVERABLE_RETURN_IF((hash_size != CS_SHA256_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid hash digest size"); 00265 SA_PV_ERR_RECOVERABLE_RETURN_IF((signature == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid signature pointer"); 00266 SA_PV_ERR_RECOVERABLE_RETURN_IF((signature_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid signature size"); 00267 00268 //Verify signature 00269 pal_status = pal_verifySignature(x509_cert, PAL_SHA256, hash, hash_size, signature, signature_size); 00270 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_verifySignature failed"); 00271 00272 return kcm_status; 00273 } 00274 00275 00276
Generated on Tue Jul 12 2022 19:01:34 by 1.7.2