mirror of
https://github.com/cuberite/polarssl.git
synced 2025-09-28 07:51:36 -04:00
Merge pull request #9413 from sezrab/split_numeric_string_conversions_oid-development
Split numeric string conversions out of the OID module
This commit is contained in:
commit
b268d270ed
@ -0,0 +1,4 @@
|
||||
Changes
|
||||
* Functions regarding numeric string conversions for OIDs have been moved
|
||||
from the OID module and now reside in X.509 module. This helps to reduce
|
||||
the code size as these functions are not commonly used outside of X.509.
|
@ -492,6 +492,38 @@ size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst);
|
||||
p += (size_t) ret; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \brief Translate an ASN.1 OID into its numeric representation
|
||||
* (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
|
||||
*
|
||||
* \param buf buffer to put representation in
|
||||
* \param size size of the buffer
|
||||
* \param oid OID to translate
|
||||
*
|
||||
* \return Length of the string written (excluding final NULL) or
|
||||
* MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error
|
||||
*/
|
||||
int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);
|
||||
|
||||
/**
|
||||
* \brief Translate a string containing a dotted-decimal
|
||||
* representation of an ASN.1 OID into its encoded form
|
||||
* (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D").
|
||||
* On success, this function allocates oid->buf from the
|
||||
* heap. It must be freed by the caller using mbedtls_free().
|
||||
*
|
||||
* \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID
|
||||
* \param oid_str string representation of the OID to parse
|
||||
* \param size length of the OID string, not including any null terminator
|
||||
*
|
||||
* \return 0 if successful
|
||||
* \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not
|
||||
* represent a valid OID
|
||||
* \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to
|
||||
* allocate oid->buf
|
||||
*/
|
||||
int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -805,6 +805,75 @@ static char nibble_to_hex_digit(int i)
|
||||
return (i < 10) ? (i + '0') : (i - 10 + 'A');
|
||||
}
|
||||
|
||||
/* Return the x.y.z.... style numeric string for the given OID */
|
||||
int mbedtls_oid_get_numeric_string(char *buf, size_t size,
|
||||
const mbedtls_asn1_buf *oid)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
char *p = buf;
|
||||
size_t n = size;
|
||||
unsigned int value = 0;
|
||||
|
||||
if (size > INT_MAX) {
|
||||
/* Avoid overflow computing return value */
|
||||
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
if (oid->len <= 0) {
|
||||
/* OID must not be empty */
|
||||
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < oid->len; i++) {
|
||||
/* Prevent overflow in value. */
|
||||
if (value > (UINT_MAX >> 7)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
if ((value == 0) && ((oid->p[i]) == 0x80)) {
|
||||
/* Overlong encoding is not allowed */
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
|
||||
value <<= 7;
|
||||
value |= oid->p[i] & 0x7F;
|
||||
|
||||
if (!(oid->p[i] & 0x80)) {
|
||||
/* Last byte */
|
||||
if (n == size) {
|
||||
int component1;
|
||||
unsigned int component2;
|
||||
/* First subidentifier contains first two OID components */
|
||||
if (value >= 80) {
|
||||
component1 = '2';
|
||||
component2 = value - 80;
|
||||
} else if (value >= 40) {
|
||||
component1 = '1';
|
||||
component2 = value - 40;
|
||||
} else {
|
||||
component1 = '0';
|
||||
component2 = value;
|
||||
}
|
||||
ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
|
||||
} else {
|
||||
ret = mbedtls_snprintf(p, n, ".%u", value);
|
||||
}
|
||||
if (ret < 2 || (size_t) ret >= n) {
|
||||
return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
|
||||
}
|
||||
n -= (size_t) ret;
|
||||
p += ret;
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (value != 0) {
|
||||
/* Unterminated subidentifier */
|
||||
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
|
||||
}
|
||||
|
||||
return (int) (size - n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the name in printable form into buf; no more
|
||||
* than size characters will be written
|
||||
|
@ -278,6 +278,182 @@ error:
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
|
||||
static int oid_parse_number(unsigned int *num, const char **p, const char *bound)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
|
||||
*num = 0;
|
||||
|
||||
while (*p < bound && **p >= '0' && **p <= '9') {
|
||||
ret = 0;
|
||||
if (*num > (UINT_MAX / 10)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
*num *= 10;
|
||||
*num += **p - '0';
|
||||
(*p)++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t oid_subidentifier_num_bytes(unsigned int value)
|
||||
{
|
||||
size_t num_bytes = 0;
|
||||
|
||||
do {
|
||||
value >>= 7;
|
||||
num_bytes++;
|
||||
} while (value != 0);
|
||||
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
static int oid_subidentifier_encode_into(unsigned char **p,
|
||||
unsigned char *bound,
|
||||
unsigned int value)
|
||||
{
|
||||
size_t num_bytes = oid_subidentifier_num_bytes(value);
|
||||
|
||||
if ((size_t) (bound - *p) < num_bytes) {
|
||||
return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
|
||||
}
|
||||
(*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);
|
||||
value >>= 7;
|
||||
|
||||
for (size_t i = 2; i <= num_bytes; i++) {
|
||||
(*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);
|
||||
value >>= 7;
|
||||
}
|
||||
*p += num_bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the OID for the given x.y.z.... style numeric string */
|
||||
int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,
|
||||
const char *oid_str, size_t size)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
const char *str_ptr = oid_str;
|
||||
const char *str_bound = oid_str + size;
|
||||
unsigned int val = 0;
|
||||
unsigned int component1, component2;
|
||||
size_t encoded_len;
|
||||
unsigned char *resized_mem;
|
||||
|
||||
/* Count the number of dots to get a worst-case allocation size. */
|
||||
size_t num_dots = 0;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (oid_str[i] == '.') {
|
||||
num_dots++;
|
||||
}
|
||||
}
|
||||
/* Allocate maximum possible required memory:
|
||||
* There are (num_dots + 1) integer components, but the first 2 share the
|
||||
* same subidentifier, so we only need num_dots subidentifiers maximum. */
|
||||
if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
/* Each byte can store 7 bits, calculate number of bytes for a
|
||||
* subidentifier:
|
||||
*
|
||||
* bytes = ceil(subidentifer_size * 8 / 7)
|
||||
*/
|
||||
size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)
|
||||
+ 1;
|
||||
size_t max_possible_bytes = num_dots * bytes_per_subidentifier;
|
||||
oid->p = mbedtls_calloc(max_possible_bytes, 1);
|
||||
if (oid->p == NULL) {
|
||||
return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
|
||||
}
|
||||
unsigned char *out_ptr = oid->p;
|
||||
unsigned char *out_bound = oid->p + max_possible_bytes;
|
||||
|
||||
ret = oid_parse_number(&component1, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (component1 > 2) {
|
||||
/* First component can't be > 2 */
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr >= str_bound || *str_ptr != '.') {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
str_ptr++;
|
||||
|
||||
ret = oid_parse_number(&component2, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if ((component1 < 2) && (component2 > 39)) {
|
||||
/* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr < str_bound) {
|
||||
if (*str_ptr == '.') {
|
||||
str_ptr++;
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (component2 > (UINT_MAX - (component1 * 40))) {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
ret = oid_subidentifier_encode_into(&out_ptr, out_bound,
|
||||
(component1 * 40) + component2);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (str_ptr < str_bound) {
|
||||
ret = oid_parse_number(&val, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr < str_bound) {
|
||||
if (*str_ptr == '.') {
|
||||
str_ptr++;
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
encoded_len = (size_t) (out_ptr - oid->p);
|
||||
resized_mem = mbedtls_calloc(encoded_len, 1);
|
||||
if (resized_mem == NULL) {
|
||||
ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
|
||||
goto error;
|
||||
}
|
||||
memcpy(resized_mem, oid->p, encoded_len);
|
||||
mbedtls_free(oid->p);
|
||||
oid->p = resized_mem;
|
||||
oid->len = encoded_len;
|
||||
|
||||
oid->tag = MBEDTLS_ASN1_OID;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mbedtls_free(oid->p);
|
||||
oid->p = NULL;
|
||||
oid->len = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
|
@ -3439,3 +3439,52 @@ x509_crt_parse_authoritykeyid:"../framework/data_files/authorityKeyId_subjectKey
|
||||
X509 CRT parse Authority Key Id - Wrong Issuer sequence
|
||||
depends_on:PSA_WANT_ALG_MD5:MBEDTLS_RSA_C
|
||||
x509_crt_parse_authoritykeyid:"../framework/data_files/clusterfuzz-testcase-minimized-fuzz_x509crt-6666050834661376.crt.der":"":"":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS+MBEDTLS_ERR_ASN1_OUT_OF_DATA
|
||||
|
||||
OID get numeric string - hardware module name
|
||||
oid_get_numeric_string:"2B06010505070804":0:"1.3.6.1.5.5.7.8.4"
|
||||
|
||||
OID get numeric string - multi-byte subidentifier
|
||||
oid_get_numeric_string:"29903C":0:"1.1.2108"
|
||||
|
||||
OID get numeric string - second component greater than 39
|
||||
oid_get_numeric_string:"81010000863A00":0:"2.49.0.0.826.0"
|
||||
|
||||
OID get numeric string - multi-byte first subidentifier
|
||||
oid_get_numeric_string:"8837":0:"2.999"
|
||||
|
||||
OID get numeric string - second subidentifier not terminated
|
||||
oid_get_numeric_string:"0081":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - empty oid buffer
|
||||
oid_get_numeric_string:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - no final / all bytes have top bit set
|
||||
oid_get_numeric_string:"818181":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - 0.39
|
||||
oid_get_numeric_string:"27":0:"0.39"
|
||||
|
||||
OID get numeric string - 1.0
|
||||
oid_get_numeric_string:"28":0:"1.0"
|
||||
|
||||
OID get numeric string - 1.39
|
||||
oid_get_numeric_string:"4f":0:"1.39"
|
||||
|
||||
OID get numeric string - 2.0
|
||||
oid_get_numeric_string:"50":0:"2.0"
|
||||
|
||||
OID get numeric string - 1 byte first subidentifier beyond 2.39
|
||||
oid_get_numeric_string:"7f":0:"2.47"
|
||||
|
||||
# Encodes the number 0x0400000000 as a subidentifier which overflows 32-bits
|
||||
OID get numeric string - 32-bit overflow
|
||||
oid_get_numeric_string:"C080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - 32-bit overflow, second subidentifier
|
||||
oid_get_numeric_string:"2BC080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - overlong encoding
|
||||
oid_get_numeric_string:"8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - overlong encoding, second subidentifier
|
||||
oid_get_numeric_string:"2B8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "mbedtls/base64.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
#include "mbedtls/asn1write.h"
|
||||
#include "string.h"
|
||||
|
||||
#if MBEDTLS_X509_MAX_INTERMEDIATE_CA > 19
|
||||
@ -1747,3 +1749,27 @@ exit:
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_X509_USE_C */
|
||||
void oid_get_numeric_string(data_t *oid, int error_ret, char *result_str)
|
||||
{
|
||||
char buf[256];
|
||||
mbedtls_asn1_buf input_oid = { 0, 0, NULL };
|
||||
int ret;
|
||||
|
||||
input_oid.tag = MBEDTLS_ASN1_OID;
|
||||
/* Test that an empty OID is not dereferenced */
|
||||
input_oid.p = oid->len ? oid->x : (void *) 1;
|
||||
input_oid.len = oid->len;
|
||||
|
||||
ret = mbedtls_oid_get_numeric_string(buf, sizeof(buf), &input_oid);
|
||||
|
||||
if (error_ret == 0) {
|
||||
TEST_EQUAL(ret, strlen(result_str));
|
||||
TEST_ASSERT(ret >= 3);
|
||||
TEST_EQUAL(strcmp(buf, result_str), 0);
|
||||
} else {
|
||||
TEST_EQUAL(ret, error_ret);
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
@ -268,3 +268,52 @@ x509_set_serial_check:
|
||||
|
||||
Check max extension length
|
||||
x509_set_extension_length_check:
|
||||
|
||||
OID from numeric string - hardware module name
|
||||
oid_from_numeric_string:"1.3.6.1.5.5.7.8.4":0:"2B06010505070804"
|
||||
|
||||
OID from numeric string - multi-byte subidentifier
|
||||
oid_from_numeric_string:"1.1.2108":0:"29903C"
|
||||
|
||||
OID from numeric string - second component greater than 39
|
||||
oid_from_numeric_string:"2.49.0.0.826.0":0:"81010000863A00"
|
||||
|
||||
OID from numeric string - multi-byte first subidentifier
|
||||
oid_from_numeric_string:"2.999":0:"8837"
|
||||
|
||||
OID from numeric string - empty string input
|
||||
oid_from_numeric_string:"":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component not a number
|
||||
oid_from_numeric_string:"abc.1.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - second component not a number
|
||||
oid_from_numeric_string:"1.abc.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component too large
|
||||
oid_from_numeric_string:"3.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component < 2, second > 39
|
||||
oid_from_numeric_string:"1.40":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - third component not a number
|
||||
oid_from_numeric_string:"1.2.abc":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between first and second
|
||||
oid_from_numeric_string:"1/2.3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between second and third
|
||||
oid_from_numeric_string:"1.2/3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between third and fourth
|
||||
oid_from_numeric_string:"1.2.3/4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - OID greater than max length (129 components)
|
||||
oid_from_numeric_string:"1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - OID with maximum subidentifier
|
||||
oid_from_numeric_string:"2.4294967215":0:"8FFFFFFF7F"
|
||||
|
||||
OID from numeric string - OID with overflowing subidentifier
|
||||
oid_from_numeric_string:"2.4294967216":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "mbedtls/pem.h"
|
||||
#include "mbedtls/oid.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
#include "mbedtls/asn1write.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/psa_util.h"
|
||||
@ -761,3 +762,29 @@ void x509_set_extension_length_check()
|
||||
TEST_ASSERT(MBEDTLS_ERR_X509_BAD_INPUT_DATA == ret);
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_X509_USE_C */
|
||||
void oid_from_numeric_string(char *oid_str, int error_ret,
|
||||
data_t *exp_oid_buf)
|
||||
{
|
||||
mbedtls_asn1_buf oid = { 0, 0, NULL };
|
||||
mbedtls_asn1_buf exp_oid = { 0, 0, NULL };
|
||||
int ret;
|
||||
|
||||
exp_oid.tag = MBEDTLS_ASN1_OID;
|
||||
exp_oid.p = exp_oid_buf->x;
|
||||
exp_oid.len = exp_oid_buf->len;
|
||||
|
||||
ret = mbedtls_oid_from_numeric_string(&oid, oid_str, strlen(oid_str));
|
||||
|
||||
if (error_ret == 0) {
|
||||
TEST_EQUAL(oid.len, exp_oid.len);
|
||||
TEST_ASSERT(memcmp(oid.p, exp_oid.p, oid.len) == 0);
|
||||
mbedtls_free(oid.p);
|
||||
oid.p = NULL;
|
||||
oid.len = 0;
|
||||
} else {
|
||||
TEST_EQUAL(ret, error_ret);
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
@ -482,38 +482,6 @@ typedef struct mbedtls_oid_descriptor_t {
|
||||
#endif
|
||||
} mbedtls_oid_descriptor_t;
|
||||
|
||||
/**
|
||||
* \brief Translate an ASN.1 OID into its numeric representation
|
||||
* (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
|
||||
*
|
||||
* \param buf buffer to put representation in
|
||||
* \param size size of the buffer
|
||||
* \param oid OID to translate
|
||||
*
|
||||
* \return Length of the string written (excluding final NULL) or
|
||||
* MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error
|
||||
*/
|
||||
int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);
|
||||
|
||||
/**
|
||||
* \brief Translate a string containing a dotted-decimal
|
||||
* representation of an ASN.1 OID into its encoded form
|
||||
* (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D").
|
||||
* On success, this function allocates oid->buf from the
|
||||
* heap. It must be freed by the caller using mbedtls_free().
|
||||
*
|
||||
* \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID
|
||||
* \param oid_str string representation of the OID to parse
|
||||
* \param size length of the OID string, not including any null terminator
|
||||
*
|
||||
* \return 0 if successful
|
||||
* \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not
|
||||
* represent a valid OID
|
||||
* \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to
|
||||
* allocate oid->buf
|
||||
*/
|
||||
int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);
|
||||
|
||||
/**
|
||||
* \brief Translate an X.509 extension OID into local values
|
||||
*
|
||||
|
@ -918,249 +918,4 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg,
|
||||
cipher_alg)
|
||||
#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */
|
||||
|
||||
/* Return the x.y.z.... style numeric string for the given OID */
|
||||
int mbedtls_oid_get_numeric_string(char *buf, size_t size,
|
||||
const mbedtls_asn1_buf *oid)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
char *p = buf;
|
||||
size_t n = size;
|
||||
unsigned int value = 0;
|
||||
|
||||
if (size > INT_MAX) {
|
||||
/* Avoid overflow computing return value */
|
||||
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
if (oid->len <= 0) {
|
||||
/* OID must not be empty */
|
||||
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < oid->len; i++) {
|
||||
/* Prevent overflow in value. */
|
||||
if (value > (UINT_MAX >> 7)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
if ((value == 0) && ((oid->p[i]) == 0x80)) {
|
||||
/* Overlong encoding is not allowed */
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
|
||||
value <<= 7;
|
||||
value |= oid->p[i] & 0x7F;
|
||||
|
||||
if (!(oid->p[i] & 0x80)) {
|
||||
/* Last byte */
|
||||
if (n == size) {
|
||||
int component1;
|
||||
unsigned int component2;
|
||||
/* First subidentifier contains first two OID components */
|
||||
if (value >= 80) {
|
||||
component1 = '2';
|
||||
component2 = value - 80;
|
||||
} else if (value >= 40) {
|
||||
component1 = '1';
|
||||
component2 = value - 40;
|
||||
} else {
|
||||
component1 = '0';
|
||||
component2 = value;
|
||||
}
|
||||
ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
|
||||
} else {
|
||||
ret = mbedtls_snprintf(p, n, ".%u", value);
|
||||
}
|
||||
if (ret < 2 || (size_t) ret >= n) {
|
||||
return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
|
||||
}
|
||||
n -= (size_t) ret;
|
||||
p += ret;
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (value != 0) {
|
||||
/* Unterminated subidentifier */
|
||||
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
|
||||
}
|
||||
|
||||
return (int) (size - n);
|
||||
}
|
||||
|
||||
static int oid_parse_number(unsigned int *num, const char **p, const char *bound)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
|
||||
*num = 0;
|
||||
|
||||
while (*p < bound && **p >= '0' && **p <= '9') {
|
||||
ret = 0;
|
||||
if (*num > (UINT_MAX / 10)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
*num *= 10;
|
||||
*num += **p - '0';
|
||||
(*p)++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t oid_subidentifier_num_bytes(unsigned int value)
|
||||
{
|
||||
size_t num_bytes = 0;
|
||||
|
||||
do {
|
||||
value >>= 7;
|
||||
num_bytes++;
|
||||
} while (value != 0);
|
||||
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
static int oid_subidentifier_encode_into(unsigned char **p,
|
||||
unsigned char *bound,
|
||||
unsigned int value)
|
||||
{
|
||||
size_t num_bytes = oid_subidentifier_num_bytes(value);
|
||||
|
||||
if ((size_t) (bound - *p) < num_bytes) {
|
||||
return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
|
||||
}
|
||||
(*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);
|
||||
value >>= 7;
|
||||
|
||||
for (size_t i = 2; i <= num_bytes; i++) {
|
||||
(*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);
|
||||
value >>= 7;
|
||||
}
|
||||
*p += num_bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the OID for the given x.y.z.... style numeric string */
|
||||
int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,
|
||||
const char *oid_str, size_t size)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
const char *str_ptr = oid_str;
|
||||
const char *str_bound = oid_str + size;
|
||||
unsigned int val = 0;
|
||||
unsigned int component1, component2;
|
||||
size_t encoded_len;
|
||||
unsigned char *resized_mem;
|
||||
|
||||
/* Count the number of dots to get a worst-case allocation size. */
|
||||
size_t num_dots = 0;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (oid_str[i] == '.') {
|
||||
num_dots++;
|
||||
}
|
||||
}
|
||||
/* Allocate maximum possible required memory:
|
||||
* There are (num_dots + 1) integer components, but the first 2 share the
|
||||
* same subidentifier, so we only need num_dots subidentifiers maximum. */
|
||||
if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {
|
||||
return MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
}
|
||||
/* Each byte can store 7 bits, calculate number of bytes for a
|
||||
* subidentifier:
|
||||
*
|
||||
* bytes = ceil(subidentifer_size * 8 / 7)
|
||||
*/
|
||||
size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)
|
||||
+ 1;
|
||||
size_t max_possible_bytes = num_dots * bytes_per_subidentifier;
|
||||
oid->p = mbedtls_calloc(max_possible_bytes, 1);
|
||||
if (oid->p == NULL) {
|
||||
return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
|
||||
}
|
||||
unsigned char *out_ptr = oid->p;
|
||||
unsigned char *out_bound = oid->p + max_possible_bytes;
|
||||
|
||||
ret = oid_parse_number(&component1, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (component1 > 2) {
|
||||
/* First component can't be > 2 */
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr >= str_bound || *str_ptr != '.') {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
str_ptr++;
|
||||
|
||||
ret = oid_parse_number(&component2, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if ((component1 < 2) && (component2 > 39)) {
|
||||
/* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr < str_bound) {
|
||||
if (*str_ptr == '.') {
|
||||
str_ptr++;
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (component2 > (UINT_MAX - (component1 * 40))) {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
ret = oid_subidentifier_encode_into(&out_ptr, out_bound,
|
||||
(component1 * 40) + component2);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (str_ptr < str_bound) {
|
||||
ret = oid_parse_number(&val, &str_ptr, str_bound);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
if (str_ptr < str_bound) {
|
||||
if (*str_ptr == '.') {
|
||||
str_ptr++;
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
encoded_len = (size_t) (out_ptr - oid->p);
|
||||
resized_mem = mbedtls_calloc(encoded_len, 1);
|
||||
if (resized_mem == NULL) {
|
||||
ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
|
||||
goto error;
|
||||
}
|
||||
memcpy(resized_mem, oid->p, encoded_len);
|
||||
mbedtls_free(oid->p);
|
||||
oid->p = resized_mem;
|
||||
oid->len = encoded_len;
|
||||
|
||||
oid->tag = MBEDTLS_ASN1_OID;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mbedtls_free(oid->p);
|
||||
oid->p = NULL;
|
||||
oid->len = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_OID_C */
|
||||
|
@ -105,103 +105,6 @@ oid_get_md_alg_id:"2b24030201":MBEDTLS_MD_RIPEMD160
|
||||
OID hash id - invalid oid
|
||||
oid_get_md_alg_id:"2B864886f70d0204":-1
|
||||
|
||||
OID get numeric string - hardware module name
|
||||
oid_get_numeric_string:"2B06010505070804":0:"1.3.6.1.5.5.7.8.4"
|
||||
|
||||
OID get numeric string - multi-byte subidentifier
|
||||
oid_get_numeric_string:"29903C":0:"1.1.2108"
|
||||
|
||||
OID get numeric string - second component greater than 39
|
||||
oid_get_numeric_string:"81010000863A00":0:"2.49.0.0.826.0"
|
||||
|
||||
OID get numeric string - multi-byte first subidentifier
|
||||
oid_get_numeric_string:"8837":0:"2.999"
|
||||
|
||||
OID get numeric string - second subidentifier not terminated
|
||||
oid_get_numeric_string:"0081":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - empty oid buffer
|
||||
oid_get_numeric_string:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - no final / all bytes have top bit set
|
||||
oid_get_numeric_string:"818181":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
|
||||
|
||||
OID get numeric string - 0.39
|
||||
oid_get_numeric_string:"27":0:"0.39"
|
||||
|
||||
OID get numeric string - 1.0
|
||||
oid_get_numeric_string:"28":0:"1.0"
|
||||
|
||||
OID get numeric string - 1.39
|
||||
oid_get_numeric_string:"4f":0:"1.39"
|
||||
|
||||
OID get numeric string - 2.0
|
||||
oid_get_numeric_string:"50":0:"2.0"
|
||||
|
||||
OID get numeric string - 1 byte first subidentifier beyond 2.39
|
||||
oid_get_numeric_string:"7f":0:"2.47"
|
||||
|
||||
# Encodes the number 0x0400000000 as a subidentifier which overflows 32-bits
|
||||
OID get numeric string - 32-bit overflow
|
||||
oid_get_numeric_string:"C080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - 32-bit overflow, second subidentifier
|
||||
oid_get_numeric_string:"2BC080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - overlong encoding
|
||||
oid_get_numeric_string:"8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID get numeric string - overlong encoding, second subidentifier
|
||||
oid_get_numeric_string:"2B8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - hardware module name
|
||||
oid_from_numeric_string:"1.3.6.1.5.5.7.8.4":0:"2B06010505070804"
|
||||
|
||||
OID from numeric string - multi-byte subidentifier
|
||||
oid_from_numeric_string:"1.1.2108":0:"29903C"
|
||||
|
||||
OID from numeric string - second component greater than 39
|
||||
oid_from_numeric_string:"2.49.0.0.826.0":0:"81010000863A00"
|
||||
|
||||
OID from numeric string - multi-byte first subidentifier
|
||||
oid_from_numeric_string:"2.999":0:"8837"
|
||||
|
||||
OID from numeric string - empty string input
|
||||
oid_from_numeric_string:"":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component not a number
|
||||
oid_from_numeric_string:"abc.1.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - second component not a number
|
||||
oid_from_numeric_string:"1.abc.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component too large
|
||||
oid_from_numeric_string:"3.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - first component < 2, second > 39
|
||||
oid_from_numeric_string:"1.40":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - third component not a number
|
||||
oid_from_numeric_string:"1.2.abc":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between first and second
|
||||
oid_from_numeric_string:"1/2.3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between second and third
|
||||
oid_from_numeric_string:"1.2/3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - non-'.' separator between third and fourth
|
||||
oid_from_numeric_string:"1.2.3/4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - OID greater than max length (129 components)
|
||||
oid_from_numeric_string:"1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
OID from numeric string - OID with maximum subidentifier
|
||||
oid_from_numeric_string:"2.4294967215":0:"8FFFFFFF7F"
|
||||
|
||||
OID from numeric string - OID with overflowing subidentifier
|
||||
oid_from_numeric_string:"2.4294967216":MBEDTLS_ERR_ASN1_INVALID_DATA:""
|
||||
|
||||
mbedtls_oid_get_md_hmac - RIPEMD160
|
||||
depends_on:PSA_WANT_ALG_RIPEMD160
|
||||
mbedtls_oid_get_md_hmac:"2B06010505080104":MBEDTLS_MD_RIPEMD160
|
||||
|
@ -118,53 +118,3 @@ void mbedtls_oid_get_md_hmac(data_t *oid, int exp_md_id)
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void oid_get_numeric_string(data_t *oid, int error_ret, char *result_str)
|
||||
{
|
||||
char buf[256];
|
||||
mbedtls_asn1_buf input_oid = { 0, 0, NULL };
|
||||
int ret;
|
||||
|
||||
input_oid.tag = MBEDTLS_ASN1_OID;
|
||||
/* Test that an empty OID is not dereferenced */
|
||||
input_oid.p = oid->len ? oid->x : (void *) 1;
|
||||
input_oid.len = oid->len;
|
||||
|
||||
ret = mbedtls_oid_get_numeric_string(buf, sizeof(buf), &input_oid);
|
||||
|
||||
if (error_ret == 0) {
|
||||
TEST_EQUAL(ret, strlen(result_str));
|
||||
TEST_ASSERT(ret >= 3);
|
||||
TEST_EQUAL(strcmp(buf, result_str), 0);
|
||||
} else {
|
||||
TEST_EQUAL(ret, error_ret);
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void oid_from_numeric_string(char *oid_str, int error_ret,
|
||||
data_t *exp_oid_buf)
|
||||
{
|
||||
mbedtls_asn1_buf oid = { 0, 0, NULL };
|
||||
mbedtls_asn1_buf exp_oid = { 0, 0, NULL };
|
||||
int ret;
|
||||
|
||||
exp_oid.tag = MBEDTLS_ASN1_OID;
|
||||
exp_oid.p = exp_oid_buf->x;
|
||||
exp_oid.len = exp_oid_buf->len;
|
||||
|
||||
ret = mbedtls_oid_from_numeric_string(&oid, oid_str, strlen(oid_str));
|
||||
|
||||
if (error_ret == 0) {
|
||||
TEST_EQUAL(oid.len, exp_oid.len);
|
||||
TEST_ASSERT(memcmp(oid.p, exp_oid.p, oid.len) == 0);
|
||||
mbedtls_free(oid.p);
|
||||
oid.p = NULL;
|
||||
oid.len = 0;
|
||||
} else {
|
||||
TEST_EQUAL(ret, error_ret);
|
||||
}
|
||||
}
|
||||
/* END_CASE */
|
||||
|
Loading…
x
Reference in New Issue
Block a user