From a4f18a700dfa7da29b38393eb161f0db2b5717a2 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 12 Jan 2022 21:11:54 -0800 Subject: [PATCH 1/2] Add KMC Crypto Service ICV Authentication Interface Implementation --- include/crypto_error.h | 4 + .../create_sadb.sql | 4 +- ...db_jpl_unit_test_security_associations.sql | 8 +- ...hy_interface_kmc_crypto_service.template.c | 244 +++++++++++++++++- src/src_main/crypto_tc.c | 3 + src/src_mysql/sadb_routine_mariadb.template.c | 7 + util/src_util/ut_kmc_crypto_aes_cmac.c | 137 ++++++++++ 7 files changed, 393 insertions(+), 14 deletions(-) create mode 100644 util/src_util/ut_kmc_crypto_aes_cmac.c diff --git a/include/crypto_error.h b/include/crypto_error.h index 1a8d6cac..e9ee0a40 100644 --- a/include/crypto_error.h +++ b/include/crypto_error.h @@ -42,6 +42,10 @@ #define CRYPTOGRAHPY_KMC_CRYPTO_JSON_PARSE_ERROR 506 #define CRYPTOGRAHPY_KMC_CIPHER_TEXT_NOT_FOUND_IN_JSON_RESPONSE 507 #define CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_GENERIC_FAILURE 508 +#define CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_AUTHENTICATION_ERROR 509 +#define CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_MAC_VALIDATION_ERROR 510 +#define CRYPTOGRAHPY_KMC_ICV_NOT_FOUND_IN_JSON_RESPONSE 511 + #define CRYPTO_LIB_SUCCESS (0) diff --git a/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql index 5b0cf5af..635147ad 100644 --- a/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql +++ b/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -7,8 +7,8 @@ USE sadb; CREATE TABLE security_associations ( spi INT NOT NULL - ,ekid VARCHAR(20) CHARACTER SET utf8 NOT NULL DEFAULT '0' -- 'EG, for KMC Crypto KeyRef, 'kmc/test/KEY0', for libgcrypt '130' - ,akid VARCHAR(20) CHARACTER SET utf8 NOT NULL DEFAULT '0' -- Same as ekid + ,ekid VARCHAR(100) CHARACTER SET utf8 NOT NULL DEFAULT '0' -- 'EG, for KMC Crypto KeyRef, 'kmc/test/KEY0', for libgcrypt '130' + ,akid VARCHAR(100) CHARACTER SET utf8 NOT NULL DEFAULT '0' -- Same as ekid ,sa_state SMALLINT NOT NULL DEFAULT 0 ,tfvn TINYINT NOT NULL ,scid SMALLINT NOT NULL diff --git a/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql b/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql index dc8fa454..fb730d7a 100644 --- a/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql +++ b/src/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql @@ -1,5 +1,6 @@ USE sadb; +-- SCID 44 (MMT) Security Associations AES/GCM/NoPadding -- -- SA 1 - OPERATIONAL; ENC + AUTH - ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-0 INSERT INTO security_associations (spi,ekid,sa_state,ecs,est,ast,shivf_len,stmacf_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) VALUES (1,'kmc/test/key130',3,X'01',1,1,12,16,X'000000000000000000000001',19,X'00000000000000000000000000000000000000',1,5,0,0,44,0,0); @@ -14,4 +15,9 @@ VALUES (3,'kmc/test/key130',3,X'01',1,0,12,0,X'000000000000000000000001',19,X'00 -- SA 4 - OPERATIONAL; AUTH Only - ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-3 INSERT INTO security_associations (spi,ekid,sa_state,ecs,est,ast,shivf_len,stmacf_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) -VALUES (4,'kmc/test/key130',3,X'01',0,1,12,16,X'000000000000000000000001',1024,X'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',1,5,0,0,44,3,0); \ No newline at end of file +VALUES (4,'kmc/test/key130',3,X'01',0,1,12,16,X'000000000000000000000001',1024,X'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',1,5,0,0,44,3,0); + +-- SCID 44 (MMT) Security Associations HMAC Authentication Only -- +-- SA 5 - OPERATIONAL; AUTH Only - ARCW:5; None/AESCMAC ; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-7 +INSERT INTO security_associations (spi,ekid,sa_state,ecs,est,ast,shivf_len,stmacf_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (5,'kmc/test/nist_cmac_90',3,X'00',0,1,0,16,X'000000000000000000000001',1024,X'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',1,5,0,0,44,7,0); diff --git a/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c b/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c index d538d5ca..b20d7b2a 100644 --- a/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c +++ b/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c @@ -92,12 +92,14 @@ static const char* encrypt_endpoint = "encrypt?keyRef=%s&transformation=%s&iv=%s static const char* encrypt_offset_endpoint = "encrypt?keyRef=%s&transformation=%s&iv=%s&encryptOffset=%s"; static const char* decrypt_endpoint = "decrypt?metadata=keyLength:%s,keyRef:%s,cipherTransformation:%s,initialVector:%s,cryptoAlgorithm:%s,metadataType:EncryptionMetadata"; static const char* decrypt_offset_endpoint = "decrypt?metadata=keyLength:%s,keyRef:%s,cipherTransformation:%s,initialVector:%s,cryptoAlgorithm:%s,metadataType:EncryptionMetadata,encryptOffset:%s"; +static const char* icv_create_endpoint = "icv-create?keyRef=%s"; // Supported KMC Cipher Transformation Strings static const char* AES_GCM_TRANSFORMATION="AES/GCM/NoPadding"; static const char* AES_CRYPTO_ALGORITHM="AES"; //static const char* AES_CBC_TRANSFORMATION="AES/CBC/PKCS5Padding"; -//static const char* AES_CMAC_TRANSFORMATION="AESCMAC"; +// static const char* AES_CMAC_TRANSFORMATION="AESCMAC"; +// static const char* HMAC_SHA256="HmacSHA256"; //static const char* AES_DES_CMAC_TRANSFORMATION="DESedeCMAC"; @@ -247,22 +249,216 @@ static int32_t cryptography_authenticate(uint8_t* data_out, size_t len_data_out, uint8_t* aad, uint32_t aad_len, uint8_t ecs, uint8_t acs) { - data_out = data_out; + int32_t status = CRYPTO_LIB_SUCCESS; + + // Unneeded vars for current implementation len_data_out = len_data_out; - data_in = data_in; - len_data_in = len_data_in; key = key; len_key = len_key; - sa_ptr = sa_ptr; iv = iv; iv_len = iv_len; - mac = mac; - mac_size = mac_size; - aad = aad; - aad_len = aad_len; ecs = ecs; acs = acs; - return CRYPTO_LIB_SUCCESS; + + curl_easy_reset(curl); + configure_curl_connect_opts(curl); + + // Base64 URL encode IV for KMC REST Encrypt + // Not needed for CMAC/HMAC (only supported auth ciphers now) +// char* iv_base64 = (char*)calloc(1,iv_len*4); +// base64urlEncode(iv,iv_len,iv_base64,NULL); + + uint8_t* auth_payload = aad; + size_t auth_payload_len = aad_len; + + // Need to copy the data over, since authentication won't change/move the data directly + if(data_out != NULL){ + memcpy(data_out, data_in, len_data_in); + }else{ + return CRYPTO_LIB_ERR_NULL_BUFFER; + } + + // Prepare the Authentication Endpoint URI for KMC Crypto Service + int len_auth_endpoint = strlen(icv_create_endpoint)+strlen(sa_ptr->ek_ref); + char* auth_endpoint_final = (char*) malloc(len_auth_endpoint); + snprintf(auth_endpoint_final,len_auth_endpoint,icv_create_endpoint,sa_ptr->ek_ref); + + char* auth_uri = (char*) malloc(strlen(kmc_root_uri)+len_auth_endpoint); + auth_uri[0] = '\0'; + strcat(auth_uri, kmc_root_uri); + strcat(auth_uri, auth_endpoint_final); + +#ifdef DEBUG + printf("Authentication URI: %s\n",auth_uri); +#endif + curl_easy_setopt(curl, CURLOPT_URL, auth_uri); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers_list); + + memory_write* chunk_write = (memory_write*) calloc(1,MEMORY_WRITE_SIZE); + memory_read* chunk_read = (memory_read*) calloc(1,MEMORY_READ_SIZE);; + /* Configure CURL for POST */ + curl_easy_setopt(curl, CURLOPT_POST, 1L); + /* send all data to this function */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl, CURLOPT_READDATA, chunk_read); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, chunk_write); + + /* size of the POST data */ + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) auth_payload_len); + /* binary data */ + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, auth_payload); + +#ifdef DEBUG + printf("Authentication Payload Length: %ld\n",auth_payload_len); + printf("Data to Authenticate: \n"); + for (uint32_t i=0; i < auth_payload_len; i++) + { + printf("%02x ", auth_payload[i]); + } + printf("\n"); +#endif + + CURLcode res; + res = curl_easy_perform(curl); + + if(res != CURLE_OK) // This is not return code, this is successful response! + { + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_AUTHENTICATION_ERROR; + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + return status; + } + +#ifdef DEBUG + printf("\ncURL Authenticate Response:\n\t %s\n",chunk_write->response); +#endif + + /* JSON Response Handling */ + + // Parse the JSON string response + jsmn_parser p; + jsmntok_t t[64]; /* We expect no more than 64 JSON tokens */ + jsmn_init(&p); + int parse_result = jsmn_parse(&p, chunk_write->response, strlen(chunk_write->response), t, 64); // "chunk->response" is the char array holding the json content + + // Find the 'integrityCheckValue' token + if (parse_result < 0) { + status = CRYPTOGRAHPY_KMC_CRYPTO_JSON_PARSE_ERROR; + printf("Failed to parse JSON: %d\n", parse_result); + return status; + } + + int json_idx = 0; + uint8_t icvtext_found = CRYPTO_FALSE; + char* icv_base64 = NULL; + for (json_idx = 1; json_idx < parse_result; json_idx++) + { + if (jsoneq(chunk_write->response, &t[json_idx], "metadata") == 0) + { + /* We may use strndup() to fetch string value */ +#ifdef DEBUG + printf("Json metadata: %.*s\n", t[json_idx + 1].end - t[json_idx + 1].start, + chunk_write->response + t[json_idx + 1].start); +#endif + // search through metadata string for base64 ICV end idx: + // Format: "integrityCheckValue:xQgnkVrrQj8FRALV3DxnVg==,keyRef:kmc/test/nist_cmac_90,cryptoAlgorithm:AESCMAC,metadataType:IntegrityCheckMetadata" + uint32_t len_metadata = t[json_idx + 1].end - t[json_idx + 1].start; + char* metadata = malloc(len_metadata+1); + char* metadata_end = &metadata[len_metadata]; + memcpy(metadata,chunk_write->response + t[json_idx + 1].start, len_metadata); + + char* key = ""; + size_t colon_idx; + size_t comma_idx; + while(CRYPTO_TRUE) + { + colon_idx = strcspn(metadata,":"); + comma_idx = strcspn(metadata,","); + key = malloc(colon_idx+1); + strncpy(key,metadata,colon_idx); + key[colon_idx]='\0'; +#ifdef DEBUG + printf("Found key in metadata: %s\n",key); +#endif + if(strcmp(key,"integrityCheckValue")==0){ + break; // key found! + } + if(strcmp(key,"integrityCheckValue")!=0){ + metadata += comma_idx+1; + if(metadata >= metadata_end) + { + status = CRYPTOGRAHPY_KMC_ICV_NOT_FOUND_IN_JSON_RESPONSE; + return status; + } + } + } + + metadata += colon_idx+1; + comma_idx = strcspn(metadata,","); + icv_base64 = malloc(comma_idx+1); + strncpy(icv_base64,metadata,comma_idx); + icv_base64[comma_idx] = '\0'; +#ifdef DEBUG + printf("Parsed integrityCheckValue: %s\n",icv_base64); +#endif + json_idx++; + icvtext_found = CRYPTO_TRUE; + continue; + } + + if (jsoneq(chunk_write->response, &t[json_idx], "httpCode") == 0) + { + /* We may use strndup() to fetch string value */ +#ifdef DEBUG + printf("httpCode: %.*s\n", t[json_idx + 1].end - t[json_idx + 1].start, + chunk_write->response + t[json_idx + 1].start); +#endif + uint32_t len_httpcode = t[json_idx + 1].end - t[json_idx + 1].start; + char* http_code_str = malloc(len_httpcode+1); + memcpy(http_code_str,chunk_write->response + t[json_idx + 1].start, len_httpcode); + http_code_str[len_httpcode] = '\0'; + int http_code = atoi(http_code_str); +#ifdef DEBUG + printf("Parsed http code: %d\n",http_code); +#endif + if(http_code != 200) + { + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_GENERIC_FAILURE; + fprintf(stderr,"KMC Crypto Failure Response:\n%s\n",chunk_write->response); + return status; + } + json_idx++; + continue; + } + + } + if(icvtext_found == CRYPTO_FALSE){ + status = CRYPTOGRAHPY_KMC_ICV_NOT_FOUND_IN_JSON_RESPONSE; + return status; + } + + /* JSON Response Handling End */ + + uint8_t* icv_decoded = malloc((mac_size)*2 + 1); + size_t icv_decoded_len = 0; + base64Decode(icv_base64,strlen(icv_base64),icv_decoded, &icv_decoded_len); +#ifdef DEBUG + printf("Mac size: %d\n",mac_size); + printf("Decoded ICV Length: %ld\n",icv_decoded_len); + printf("Decoded ICV Text: \n"); + for (uint32_t i=0; i < icv_decoded_len; i++) + { + printf("%02x ", icv_decoded[i]); + } + printf("\n"); +#endif + + memcpy(mac,icv_decoded, mac_size); + return status; } static int32_t cryptography_validate_authentication(uint8_t* data_out, size_t len_data_out, uint8_t* data_in, size_t len_data_in, @@ -455,8 +651,34 @@ static int32_t cryptography_aead_encrypt(uint8_t* data_out, size_t len_data_out, #endif json_idx++; ciphertext_found = CRYPTO_TRUE; - break; + continue; } + + if (jsoneq(chunk_write->response, &t[json_idx], "httpCode") == 0) + { + /* We may use strndup() to fetch string value */ +#ifdef DEBUG + printf("httpCode: %.*s\n", t[json_idx + 1].end - t[json_idx + 1].start, + chunk_write->response + t[json_idx + 1].start); +#endif + uint32_t len_httpcode = t[json_idx + 1].end - t[json_idx + 1].start; + char* http_code_str = malloc(len_httpcode+1); + memcpy(http_code_str,chunk_write->response + t[json_idx + 1].start, len_httpcode); + http_code_str[len_httpcode] = '\0'; + int http_code = atoi(http_code_str); +#ifdef DEBUG + printf("Parsed http code: %d\n",http_code); +#endif + if(http_code != 200) + { + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_GENERIC_FAILURE; + fprintf(stderr,"KMC Crypto Failure Response:\n%s\n",chunk_write->response); + return status; + } + json_idx++; + continue; + } + } if(ciphertext_found == CRYPTO_FALSE){ status = CRYPTOGRAHPY_KMC_CIPHER_TEXT_NOT_FOUND_IN_JSON_RESPONSE; diff --git a/src/src_main/crypto_tc.c b/src/src_main/crypto_tc.c index 1a41e325..9cfba9d0 100644 --- a/src/src_main/crypto_tc.c +++ b/src/src_main/crypto_tc.c @@ -434,6 +434,9 @@ int32_t Crypto_TC_ApplySecurity(const uint8_t *p_in_frame, const uint16_t in_fra { aad_len += tf_payload_len; } +#ifdef TC_DEBUG + printf("Calculated AAD Length: %d\n",aad_len); +#endif if (sa_ptr->abm_len < aad_len) { return CRYPTO_LIB_ERR_ABM_TOO_SHORT_FOR_AAD; diff --git a/src/src_mysql/sadb_routine_mariadb.template.c b/src/src_mysql/sadb_routine_mariadb.template.c index dacda773..9c181fe2 100644 --- a/src/src_mysql/sadb_routine_mariadb.template.c +++ b/src/src_mysql/sadb_routine_mariadb.template.c @@ -282,6 +282,13 @@ static int32_t parse_sa_from_mysql_query(char *query, SecurityAssociation_t **se return status; } + int num_rows = mysql_num_rows(result); + if(num_rows == 0) // No rows returned in query!! + { + status = finish_with_error(con, SADB_QUERY_EMPTY_RESULTS); + return status; + } + int num_fields = mysql_num_fields(result); MYSQL_ROW row; diff --git a/util/src_util/ut_kmc_crypto_aes_cmac.c b/util/src_util/ut_kmc_crypto_aes_cmac.c new file mode 100644 index 00000000..614dedab --- /dev/null +++ b/util/src_util/ut_kmc_crypto_aes_cmac.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. + All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, + including, but not limited to, any warranty that the software will conform to specifications, any implied warranties + of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the + documentation will conform to the program, or any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or + consequential damages, arising out of, resulting from, or in any way connected with the software or its + documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained + from, or arose out of the results of, or use of, the software, documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ + +/** + * Unit Tests that make use of TC_ApplySecurity/TC_ProcessSecurity function on the data with KMC Crypto Service/MariaDB Functionality Enabled. + **/ +#include "crypto.h" +#include "crypto_error.h" +#include "sadb_routine.h" +#include "utest.h" + +#include "crypto.h" +#include "shared_util.h" +#include + +/** + * @brief Unit Test: Nominal Encryption with KMC Crypto Service && JPL Unit Test MariaDB + **/ +UTEST(KMC_CRYPTO, HAPPY_PATH_APPLY_SEC_CMAC_AUTH_ONLY) +{ + // Setup & Initialize CryptoLib + Crypto_Config_CryptoLib(SADB_TYPE_MARIADB, CRYPTOGRAPHY_TYPE_KMCCRYPTO, CRYPTO_TC_CREATE_FECF_TRUE, TC_PROCESS_SDLS_PDUS_FALSE, TC_NO_PUS_HDR, + TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, + TC_CHECK_FECF_TRUE, 0x3F); + Crypto_Config_MariaDB("sadb_user", "sadb_password", "localhost","sadb", 3306, CRYPTO_FALSE, NULL, NULL, NULL, NULL); + Crypto_Config_Kmc_Crypto_Service("https", "asec-cmdenc-srv1.jpl.nasa.gov", 8443, "crypto-service", "/home/isaleh/git/KMC/CryptoLib-IbraheemYSaleh/util/etc/local-test-cert.pem", "PEM","/home/isaleh/git/KMC/CryptoLib-IbraheemYSaleh/util/etc/local-test-key.pem",NULL,"/home/isaleh/git/KMC/CryptoLib-IbraheemYSaleh/util/etc/ammos-ca-bundle.crt", NULL, NULL, CRYPTO_FALSE); + Crypto_Config_Add_Gvcid_Managed_Parameter(0, 0x002C, 7, TC_HAS_FECF, TC_NO_SEGMENT_HDRS); + int32_t status = Crypto_Init(); + + char *raw_tc_jpl_mmt_scid44_vcid1= "202c1c08000001bb40"; + char *raw_tc_jpl_mmt_scid44_vcid1_expect = NULL; + int raw_tc_jpl_mmt_scid44_vcid1_expect_len = 0; + + hex_conversion(raw_tc_jpl_mmt_scid44_vcid1, &raw_tc_jpl_mmt_scid44_vcid1_expect, &raw_tc_jpl_mmt_scid44_vcid1_expect_len); + + uint8_t *ptr_enc_frame = NULL; + uint16_t enc_frame_len = 0; + + ASSERT_EQ(CRYPTO_LIB_SUCCESS, status); + + printf("Frame before encryption:\n"); + for (int i=0; itc_pdu_len; i++) + { + printf("%02x ", tc_processed_frame->tc_pdu[i]); + } + printf("\n"); + + ASSERT_EQ(0x00,tc_processed_frame->tc_pdu[0]); + ASSERT_EQ( 0x01,tc_processed_frame->tc_pdu[1]); + + Crypto_Shutdown(); + free(enc_tc_jpl_mmt_scid44_vcid1_expect); + free(ptr_enc_frame); + ASSERT_EQ(CRYPTO_LIB_SUCCESS, status); +} + +UTEST_MAIN(); From 51a672529e18a2aa53b7b6c564482097d254b4f8 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 12 Jan 2022 21:36:24 -0800 Subject: [PATCH 2/2] Implement KMC Crypto Service cryptography_validate_authentication function --- ...hy_interface_kmc_crypto_service.template.c | 152 ++++++++++++++++-- 1 file changed, 141 insertions(+), 11 deletions(-) diff --git a/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c b/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c index b20d7b2a..219bef5b 100644 --- a/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c +++ b/src/src_cryptography/src_kmc_crypto_service/cryptography_interface_kmc_crypto_service.template.c @@ -93,12 +93,13 @@ static const char* encrypt_offset_endpoint = "encrypt?keyRef=%s&transformation=% static const char* decrypt_endpoint = "decrypt?metadata=keyLength:%s,keyRef:%s,cipherTransformation:%s,initialVector:%s,cryptoAlgorithm:%s,metadataType:EncryptionMetadata"; static const char* decrypt_offset_endpoint = "decrypt?metadata=keyLength:%s,keyRef:%s,cipherTransformation:%s,initialVector:%s,cryptoAlgorithm:%s,metadataType:EncryptionMetadata,encryptOffset:%s"; static const char* icv_create_endpoint = "icv-create?keyRef=%s"; +static const char* icv_verify_endpoint = "icv-verify?metadata=integrityCheckValue:%s,keyRef:%s,cryptoAlgorithm:%s,metadataType:IntegrityCheckMetadata"; // Supported KMC Cipher Transformation Strings static const char* AES_GCM_TRANSFORMATION="AES/GCM/NoPadding"; static const char* AES_CRYPTO_ALGORITHM="AES"; //static const char* AES_CBC_TRANSFORMATION="AES/CBC/PKCS5Padding"; -// static const char* AES_CMAC_TRANSFORMATION="AESCMAC"; +static const char* AES_CMAC_TRANSFORMATION="AESCMAC"; // static const char* HMAC_SHA256="HmacSHA256"; //static const char* AES_DES_CMAC_TRANSFORMATION="DESedeCMAC"; @@ -251,7 +252,7 @@ static int32_t cryptography_authenticate(uint8_t* data_out, size_t len_data_out, { int32_t status = CRYPTO_LIB_SUCCESS; - // Unneeded vars for current implementation + // Unneeded cryptography interface vars for current implementation len_data_out = len_data_out; key = key; len_key = len_key; @@ -469,22 +470,151 @@ static int32_t cryptography_validate_authentication(uint8_t* data_out, size_t le uint8_t* aad, uint32_t aad_len, uint8_t ecs, uint8_t acs) { - data_out = data_out; + int32_t status = CRYPTO_LIB_SUCCESS; + + // Unneeded cryptography interface vars for current implementation len_data_out = len_data_out; - data_in = data_in; - len_data_in = len_data_in; key = key; len_key = len_key; - sa_ptr = sa_ptr; iv = iv; iv_len = iv_len; - mac = mac; - mac_size = mac_size; - aad = aad; - aad_len = aad_len; ecs = ecs; acs = acs; - return CRYPTO_LIB_SUCCESS; + + + // Need to copy the data over, since authentication won't change/move the data directly + if(data_out != NULL){ + memcpy(data_out, data_in, len_data_in); + }else{ + return CRYPTO_LIB_ERR_NULL_BUFFER; + } + + curl_easy_reset(curl); + configure_curl_connect_opts(curl); + + uint8_t* auth_payload = aad; + size_t auth_payload_len = aad_len; + + // Base64 URL encode MAC for KMC REST Encrypt + char* mac_base64 = (char*)calloc(1,mac_size*4); + base64urlEncode(mac,mac_size,mac_base64,NULL); +#ifdef DEBUG + printf("MAC Base64 URL Encoded: %s\n",mac_base64); +#endif + + // Prepare the Authentication Endpoint URI for KMC Crypto Service + int len_auth_endpoint = strlen(icv_verify_endpoint)+strlen(mac_base64)+strlen(sa_ptr->ek_ref)+strlen(AES_CMAC_TRANSFORMATION); + char* auth_endpoint_final = (char*) malloc(len_auth_endpoint); + snprintf(auth_endpoint_final,len_auth_endpoint,icv_verify_endpoint,mac_base64,sa_ptr->ek_ref,AES_CMAC_TRANSFORMATION); + + char* auth_uri = (char*) malloc(strlen(kmc_root_uri)+len_auth_endpoint); + auth_uri[0] = '\0'; + strcat(auth_uri, kmc_root_uri); + strcat(auth_uri, auth_endpoint_final); + +#ifdef DEBUG + printf("Authentication Verification URI: %s\n",auth_uri); +#endif + + curl_easy_setopt(curl, CURLOPT_URL, auth_uri); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers_list); + + memory_write* chunk_write = (memory_write*) calloc(1,MEMORY_WRITE_SIZE); + memory_read* chunk_read = (memory_read*) calloc(1,MEMORY_READ_SIZE);; + /* Configure CURL for POST */ + curl_easy_setopt(curl, CURLOPT_POST, 1L); + /* send all data to this function */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl, CURLOPT_READDATA, chunk_read); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, chunk_write); + + /* size of the POST data */ + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) auth_payload_len); + /* binary data */ + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, auth_payload); + +#ifdef DEBUG + printf("Authentication Payload Length: %ld\n",auth_payload_len); + printf("Data to Authenticate: \n"); + for (uint32_t i=0; i < auth_payload_len; i++) + { + printf("%02x ", auth_payload[i]); + } + printf("\n"); +#endif + + CURLcode res; + res = curl_easy_perform(curl); + + if(res != CURLE_OK) // This is not return code, this is successful response! + { + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_AUTHENTICATION_ERROR; + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + return status; + } + +#ifdef DEBUG + printf("\ncURL Authenticate Response:\n\t %s\n",chunk_write->response); +#endif + + /* JSON Response Handling */ + + // Parse the JSON string response + jsmn_parser p; + jsmntok_t t[64]; /* We expect no more than 64 JSON tokens */ + jsmn_init(&p); + int parse_result = jsmn_parse(&p, chunk_write->response, strlen(chunk_write->response), t, 64); // "chunk->response" is the char array holding the json content + + if (parse_result < 0) { + status = CRYPTOGRAHPY_KMC_CRYPTO_JSON_PARSE_ERROR; + printf("Failed to parse JSON: %d\n", parse_result); + return status; + } + + int json_idx = 0; + uint8_t http_status_found = CRYPTO_FALSE; + for (json_idx = 1; json_idx < parse_result; json_idx++) + { + if (jsoneq(chunk_write->response, &t[json_idx], "httpCode") == 0) + { + /* We may use strndup() to fetch string value */ +#ifdef DEBUG + printf("httpCode: %.*s\n", t[json_idx + 1].end - t[json_idx + 1].start, + chunk_write->response + t[json_idx + 1].start); +#endif + uint32_t len_httpcode = t[json_idx + 1].end - t[json_idx + 1].start; + char* http_code_str = malloc(len_httpcode+1); + memcpy(http_code_str,chunk_write->response + t[json_idx + 1].start, len_httpcode); + http_code_str[len_httpcode] = '\0'; + int http_code = atoi(http_code_str); +#ifdef DEBUG + printf("Parsed http code: %d\n",http_code); +#endif + if(http_code != 200) + { + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_MAC_VALIDATION_ERROR; + fprintf(stderr,"KMC Crypto Failure Response:\n%s\n",chunk_write->response); + return status; + } + json_idx++; + break; + } + + } + if(http_status_found == CRYPTO_FALSE){ + status = CRYPTOGRAHPY_KMC_CRYPTO_SERVICE_GENERIC_FAILURE; + fprintf(stderr,"KMC Crypto Failure Response:\n%s\n",chunk_write->response); + return status; + } + + /* JSON Response Handling End */ + + return status; } static int32_t cryptography_aead_encrypt(uint8_t* data_out, size_t len_data_out, uint8_t* data_in, size_t len_data_in,