TEST(atcacert_der_enc_length, atcacert_der_enc_length__short_form) { uint32_t length; uint8_t der_length[8]; size_t der_length_size = sizeof(der_length); int ret = 0; // Smallest shot form length = 0x00; der_length_size = sizeof(der_length); ret = atcacert_der_enc_length(length, der_length, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(1, der_length_size); TEST_ASSERT_EQUAL(length, der_length[0]); // Largest short form length = 0x7F; der_length_size = sizeof(der_length); ret = atcacert_der_enc_length(length, der_length, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(1, der_length_size); TEST_ASSERT_EQUAL(length, der_length[0]); // Size only length = 127; der_length_size = 0; ret = atcacert_der_enc_length(length, NULL, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(1, der_length_size); }
TEST(atcacert_der_enc_length, atcacert_der_enc_length__long_form_2byte) { uint32_t length; uint8_t der_len_min[] = { 0x81, 0x80 }; // 0x80 uint8_t der_len_max[] = { 0x81, 0xFF }; // 0xFF uint8_t der_length[8]; size_t der_length_size = sizeof(der_length); int ret = 0; // Smallest 2-byte long form length = 0x80; der_length_size = sizeof(der_length); ret = atcacert_der_enc_length(length, der_length, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(sizeof(der_len_min), der_length_size); TEST_ASSERT_EQUAL_MEMORY(der_len_min, der_length, sizeof(der_len_min)); // Largest 2-byte long form length = 0xFF; der_length_size = sizeof(der_length); ret = atcacert_der_enc_length(length, der_length, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(sizeof(der_len_max), der_length_size); TEST_ASSERT_EQUAL_MEMORY(der_len_max, der_length, sizeof(der_len_max)); // Size only length = 0xFF; der_length_size = 0; ret = atcacert_der_enc_length(length, NULL, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(sizeof(der_len_max), der_length_size); }
int atcacert_der_adjust_length(uint8_t* der_length, size_t* der_length_size, int delta_length, uint32_t* new_length) { int ret = 0; size_t new_der_len_size = 0; uint32_t old_len = 0; uint32_t new_len = 0; uint8_t new_der_length[5]; ret = atcacert_der_dec_length(der_length, der_length_size, &old_len); if (ret != ATCACERT_E_SUCCESS) return ret; if (delta_length < 0 && (size_t)(-delta_length) > old_len) return ATCACERT_E_ERROR; new_len = old_len + delta_length; if (new_length != NULL) *new_length = new_len; new_der_len_size = sizeof(new_der_length); ret = atcacert_der_enc_length(new_len, new_der_length, &new_der_len_size); if (ret != ATCACERT_E_SUCCESS) return ret; if (*der_length_size != new_der_len_size) return ATCACERT_E_BAD_CERT; memcpy(der_length, new_der_length, new_der_len_size); return 0; }
TEST(atcacert_der_enc_length, atcacert_der_enc_length__bad_params) { uint32_t length; uint8_t der_length[8]; int ret = 0; length = 0x01000000; ret = atcacert_der_enc_length(length, der_length, NULL); TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret); }
TEST(atcacert_der_enc_length, atcacert_der_enc_length__small_buf) { uint32_t length; uint8_t der_length[3]; size_t der_length_size = sizeof(der_length); int ret = 0; length = 0x01000000; der_length_size = sizeof(der_length); ret = atcacert_der_enc_length(length, der_length, &der_length_size); TEST_ASSERT_EQUAL(ATCACERT_E_BUFFER_TOO_SMALL, ret); TEST_ASSERT_EQUAL(5, der_length_size); }
int atcacert_der_enc_integer( const uint8_t* int_data, size_t int_data_size, uint8_t is_unsigned, uint8_t* der_int, size_t* der_int_size) { uint8_t der_length[5]; size_t der_length_size = sizeof(der_length); size_t der_int_size_calc = 0; size_t trim = 0; size_t pad = 0; if (int_data == NULL || der_int_size == NULL || int_data_size <= 0) return ATCACERT_E_BAD_PARAMS; if (!(is_unsigned && (int_data[0] & 0x80))) { // This is not an unsigned value that needs a padding byte, trim any unnecessary bytes. // Trim a byte when the upper 9 bits are all 0s or all 1s. while ( (int_data_size - trim >= 2) && ( ((int_data[trim] == 0x00) && ((int_data[trim + 1] & 0x80) == 0)) || ((int_data[trim] == 0xFF) && ((int_data[trim + 1] & 0x80) != 0)))) trim++; }else // Will be adding extra byte for unsigned padding so it's not interpreted as negative pad = 1; int ret = atcacert_der_enc_length(int_data_size + pad - trim, der_length, &der_length_size); if (ret != ATCACERT_E_SUCCESS) return ret; der_int_size_calc = 1 + der_length_size + int_data_size + pad - trim; if (der_int != NULL && der_int_size_calc > *der_int_size) { *der_int_size = der_int_size_calc; return ATCACERT_E_BUFFER_TOO_SMALL; } *der_int_size = der_int_size_calc; if (der_int == NULL) return ATCACERT_E_SUCCESS; // Caller just wanted the size of the encoded integer der_int[0] = 0x02; // Integer tag memcpy(&der_int[1], der_length, der_length_size); // Integer length if (pad) der_int[der_length_size + 1] = 0; // Unsigned integer value requires padding byte so it's not interpreted as negative memcpy(&der_int[der_length_size + 1 + pad], &int_data[trim], int_data_size - trim); // Integer value return ATCACERT_E_SUCCESS; }
int atcacert_set_signature( const atcacert_def_t* cert_def, uint8_t* cert, size_t* cert_size, size_t max_cert_size, const uint8_t signature[64]) { int ret = 0; uint16_t sig_offset; size_t cur_der_sig_size; size_t new_der_sig_size; size_t old_cert_der_length_size; size_t new_cert_der_length_size; size_t new_cert_length; uint8_t new_cert_der_length[5]; if (cert_def == NULL || cert == NULL || cert_size == NULL || signature == NULL) return ATCACERT_E_BAD_PARAMS; sig_offset = cert_def->std_cert_elements[STDCERT_SIGNATURE].offset; // Non X.509 signatures are treated like normal certificate elements if (cert_def->type != CERTTYPE_X509) return atcacert_set_cert_element(&cert_def->std_cert_elements[STDCERT_SIGNATURE], cert, *cert_size, signature, 64); if (sig_offset >= *cert_size) return ATCACERT_E_ELEM_OUT_OF_BOUNDS; // Signature element is shown as past the end of the certificate // Current size of the signature is from its offset to the end of the cert cur_der_sig_size = *cert_size - sig_offset; // Find the size of buffer available for the new DER signature new_der_sig_size = max_cert_size - sig_offset; // Set the new signature ret = atcacert_der_enc_ecdsa_sig_value(signature, &cert[sig_offset], &new_der_sig_size); if (ret != ATCACERT_E_SUCCESS) { if (ret == ATCACERT_E_BUFFER_TOO_SMALL) *cert_size += (int)new_der_sig_size - (int)cur_der_sig_size; // Report the size needed return ret; } *cert_size += (int)new_der_sig_size - (int)cur_der_sig_size; old_cert_der_length_size = *cert_size - 1; ret = atcacert_der_dec_length(&cert[1], &old_cert_der_length_size, NULL); if (ret != ATCACERT_E_SUCCESS) return ret; if ((1 + old_cert_der_length_size) > *cert_size) return ATCACERT_E_BAD_CERT; new_cert_length = *cert_size - (1 + old_cert_der_length_size); new_cert_der_length_size = sizeof(new_cert_der_length); ret = atcacert_der_enc_length(new_cert_length, new_cert_der_length, &new_cert_der_length_size); if (ret != ATCACERT_E_SUCCESS) return ret; if (old_cert_der_length_size != new_cert_der_length_size) return ATCACERT_E_BAD_CERT; memcpy(&cert[1], new_cert_der_length, new_cert_der_length_size); return ATCACERT_E_SUCCESS; }