Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cs_der_certs.c Source File

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_and_csrs.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_check_der_x509_format(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 kcm_status_e  cs_child_cert_params_get(palX509Handle_t x509_cert, cs_child_cert_params_s *params_out)
00276 {
00277     palStatus_t pal_status = PAL_SUCCESS;
00278 
00279     SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert");
00280     SA_PV_ERR_RECOVERABLE_RETURN_IF((params_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer params_out");
00281 
00282     // Retrieve the signature
00283     pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_SIGNATUR_ATTR, params_out->signature, sizeof(params_out->signature), &params_out->signature_actual_size);
00284     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "Failed getting signature");
00285 
00286     // Hash a SHA256 of the To Be Signed part of the X509 certificate
00287     // If we end up using more than on hash type we may retrieve it from x509_cert instead of hard coded PAL_SHA256
00288     pal_status = pal_x509CertGetHTBS(x509_cert, PAL_SHA256, params_out->htbs, sizeof(params_out->htbs), &params_out->htbs_actual_size);
00289     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "Failed Hashing TBS");
00290 
00291     return KCM_STATUS_SUCCESS;
00292 }
00293