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_dec_length, atcacert_der_dec_der_length__bad_params) { int ret = 0; const uint8_t der_length[] = { 0x82, 0x01, 0x0 }; size_t der_length_size = sizeof(der_length); uint32_t length = 0; der_length_size = sizeof(der_length); ret = atcacert_der_dec_length(NULL, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret); der_length_size = sizeof(der_length); ret = atcacert_der_dec_length(der_length, NULL, &length); TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret); ret = atcacert_der_dec_length(NULL, NULL, &length); TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret); }
TEST(atcacert_der_dec_length, atcacert_der_dec_der_length__too_large) { int ret = 0; const uint8_t der_length[] = { 0x89, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; // Too large for the return type (64 bit size_t) size_t der_length_size = sizeof(der_length); uint32_t length = 0; ret = atcacert_der_dec_length(der_length, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret); }
TEST(atcacert_der_dec_length, atcacert_der_dec_der_length__indefinite_form) { int ret = 0; const uint8_t der_length[] = { 0x80, 0x01 }; // Indefinite form not supported size_t der_length_size = sizeof(der_length); uint32_t length = 0; ret = atcacert_der_dec_length(der_length, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret); }
TEST(atcacert_der_dec_length, atcacert_der_dec_der_length__not_enough_data) { int ret = 0; const uint8_t der_length[] = { 0x82, 0x01 }; // Encoding indicates more data than is supplied size_t der_length_size = sizeof(der_length); uint32_t length = 0; ret = atcacert_der_dec_length(der_length, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret); }
TEST(atcacert_der_dec_length, atcacert_der_dec_der_length__zero_size) { int ret = 0; const uint8_t der_length[] = { 0x00 }; // Just needed for a valid pointer size_t der_length_size = 0; uint32_t length = 0; ret = atcacert_der_dec_length(der_length, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret); }
TEST(atcacert_der_dec_length, atcacert_der_dec_der_length__good) { int ret = 0; size_t i; const struct atcacert_der_dec_length__good_s tests[] = { { 0x00000000, 1, { 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 0x0000003F, 1, { 0x3F, 0x00, 0x00, 0x00, 0x00 } }, { 0x0000007F, 1, { 0x7F, 0x00, 0x00, 0x00, 0x00 } }, { 0x00000080, 2, { 0x81, 0x80, 0x00, 0x00, 0x00 } }, { 0x00000085, 2, { 0x81, 0x85, 0x00, 0x00, 0x00 } }, { 0x000000FF, 2, { 0x81, 0xFF, 0x00, 0x00, 0x00 } }, { 0x00000100, 3, { 0x82, 0x01, 0x00, 0x00, 0x00 } }, { 0x000055AA, 3, { 0x82, 0x55, 0xAA, 0x00, 0x00 } }, { 0x0000FFFF, 3, { 0x82, 0xFF, 0xFF, 0x00, 0x00 } }, { 0x00010000, 4, { 0x83, 0x01, 0x00, 0x00, 0x00 } }, { 0x0055AA55, 4, { 0x83, 0x55, 0xAA, 0x55, 0x00 } }, { 0x00FFFFFF, 4, { 0x83, 0xFF, 0xFF, 0xFF, 0x00 } }, { 0x01000000, 5, { 0x84, 0x01, 0x00, 0x00, 0x00 } }, { 0x55AA55AA, 5, { 0x84, 0x55, 0xAA, 0x55, 0xAA } }, { 0xFFFFFFFF, 5, { 0x84, 0xFF, 0xFF, 0xFF, 0xFF } }, }; for (i = 0; i < sizeof(tests) / sizeof(struct atcacert_der_dec_length__good_s); i++) { size_t der_length_size = sizeof(tests[i].der_length); uint32_t length = 0; ret = atcacert_der_dec_length(tests[i].der_length, &der_length_size, &length); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(tests[i].der_length_size, der_length_size); TEST_ASSERT_EQUAL(tests[i].length, length); // Size only der_length_size = sizeof(tests[i].der_length); ret = atcacert_der_dec_length(tests[i].der_length, &der_length_size, NULL); TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret); TEST_ASSERT_EQUAL(tests[i].der_length_size, der_length_size); } }
int atcacert_der_dec_integer( const uint8_t* der_int, size_t* der_int_size, uint8_t* int_data, size_t* int_data_size) { int ret = 0; size_t der_length_size = 0; uint32_t int_data_size_calc = 0; if (der_int == NULL || der_int_size == NULL || (int_data != NULL && int_data_size == NULL)) return ATCACERT_E_BAD_PARAMS; if (*der_int_size < 1) return ATCACERT_E_DECODING_ERROR; // No data to decode if (der_int[0] != 0x02) return ATCACERT_E_DECODING_ERROR; // Not an integer tag der_length_size = *der_int_size - 1; ret = atcacert_der_dec_length(&der_int[1], &der_length_size, &int_data_size_calc); if (ret != ATCACERT_E_SUCCESS) return ret; if (*der_int_size < (1 + der_length_size + int_data_size_calc)) return ATCACERT_E_DECODING_ERROR; // Invalid DER integer, not enough data. *der_int_size = (1 + der_length_size + int_data_size_calc); if (int_data == NULL && int_data_size == NULL) return ATCACERT_E_SUCCESS; // Caller doesn't want the actual data, just the der_int_size if (int_data != NULL && *int_data_size < int_data_size_calc) { *int_data_size = int_data_size_calc; return ATCACERT_E_BUFFER_TOO_SMALL; } *int_data_size = int_data_size_calc; if (int_data == NULL) return ATCACERT_E_SUCCESS; // Caller doesn't want the actual data, just the int_data_size memcpy(int_data, &der_int[1 + der_length_size], int_data_size_calc); 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; }
int atcacert_der_dec_ecdsa_sig_value( const uint8_t* der_sig, size_t* der_sig_size, uint8_t raw_sig[64]) { int ret = 0; size_t curr_idx = 0; size_t dec_size = 0; uint32_t bs_length = 0; uint32_t seq_length = 0; size_t r_size = 0; size_t s_size = 0; uint8_t int_data[33]; size_t int_data_size = 0; if (der_sig == NULL || der_sig_size == NULL) return ATCACERT_E_BAD_PARAMS; if (*der_sig_size < 1) return ATCACERT_E_DECODING_ERROR; // No data to decode // signatureValue bit string tag curr_idx = 0; if (der_sig[curr_idx] != 0x03) return ATCACERT_E_DECODING_ERROR; // Unexpected tag value curr_idx++; // signatureValue bit string length dec_size = *der_sig_size - curr_idx; ret = atcacert_der_dec_length(&der_sig[curr_idx], &dec_size, &bs_length); if (ret != ATCACERT_E_SUCCESS) return ret; // Failed to decode length curr_idx += dec_size; if (curr_idx + bs_length > *der_sig_size) return ATCACERT_E_DECODING_ERROR; // Not enough data in buffer to decode the rest // signatureValue bit string spare bits if (curr_idx >= *der_sig_size) return ATCACERT_E_DECODING_ERROR; // No data left if (der_sig[curr_idx] != 0x00) return ATCACERT_E_DECODING_ERROR; // Unexpected spare bits value curr_idx++; // signatureValue bit string value is the DER encoding of ECDSA-Sig-Value // sequence tag if (curr_idx >= *der_sig_size) return ATCACERT_E_DECODING_ERROR; // No data left if (der_sig[curr_idx] != 0x30) return ATCACERT_E_DECODING_ERROR; // Unexpected tag value curr_idx++; // sequence length if (curr_idx >= *der_sig_size) return ATCACERT_E_DECODING_ERROR; // No data left dec_size = *der_sig_size - curr_idx; ret = atcacert_der_dec_length(&der_sig[curr_idx], &dec_size, &seq_length); if (ret != ATCACERT_E_SUCCESS) return ret; // Failed to decode length curr_idx += dec_size; if (curr_idx + seq_length > *der_sig_size) return ATCACERT_E_DECODING_ERROR; // Not enough data in buffer to decode the rest // R integer if (curr_idx >= *der_sig_size) return ATCACERT_E_DECODING_ERROR; // No data left r_size = *der_sig_size - curr_idx; int_data_size = sizeof(int_data); ret = atcacert_der_dec_integer(&der_sig[curr_idx], &r_size, int_data, &int_data_size); if (ret != ATCACERT_E_SUCCESS) return ret; // Failed to decode length curr_idx += r_size; if (raw_sig != NULL) memset(raw_sig, 0, 64); // Zero out the raw sig as the decoded integers may not touch all bytes if (int_data_size <= 32) { if (raw_sig != NULL) memcpy(&raw_sig[32 - int_data_size], &int_data[0], int_data_size); }else if (int_data_size == 33) { if (int_data[0] != 0x00) return ATCACERT_E_DECODING_ERROR; // R integer is too large // DER integer was 0-padded to keep it positive if (raw_sig != NULL) memcpy(&raw_sig[0], &int_data[1], 32); }else return ATCACERT_E_DECODING_ERROR; // R integer is too large // S integer if (curr_idx >= *der_sig_size) return ATCACERT_E_DECODING_ERROR; // No data left s_size = *der_sig_size - curr_idx; int_data_size = sizeof(int_data); ret = atcacert_der_dec_integer(&der_sig[curr_idx], &s_size, int_data, &int_data_size); if (ret != ATCACERT_E_SUCCESS) return ret; // Failed to decode length curr_idx += s_size; if (int_data_size <= 32) { if (raw_sig != NULL) memcpy(&raw_sig[64 - int_data_size], &int_data[0], int_data_size); }else if (int_data_size == 33) { if (int_data[0] != 0x00) return ATCACERT_E_DECODING_ERROR; // S integer is too large // DER integer was 0-padded to keep it positive if (raw_sig != NULL) memcpy(&raw_sig[32], &int_data[1], 32); }else return ATCACERT_E_DECODING_ERROR; // S integer is too large if (seq_length != r_size + s_size) return ATCACERT_E_DECODING_ERROR; // Unexpected extra data in sequence if (bs_length != r_size + s_size + 3) return ATCACERT_E_DECODING_ERROR; // Unexpected extra data in bit string *der_sig_size = curr_idx; return ATCACERT_E_SUCCESS; }