Use better IP parsing in x509 programs

Remove unnecessary duplicated code.
Signed-off-by: Andrzej Kurek <andrzej.kurek@arm.com>
This commit is contained in:
Andrzej Kurek 2023-06-05 17:02:17 -04:00
parent 13230a4ad3
commit cd17ecfe85
5 changed files with 37 additions and 88 deletions

View file

@ -500,6 +500,23 @@ int mbedtls_x509_info_cert_type(char **buf, size_t *size,
int mbedtls_x509_info_key_usage(char **buf, size_t *size, int mbedtls_x509_info_key_usage(char **buf, size_t *size,
unsigned int key_usage); unsigned int key_usage);
/**
* \brief This function parses a CN string as an IP address.
*
* \param cn The CN string to parse. CN string MUST be NUL-terminated.
* \param dst The target buffer to populate with the binary IP address.
* The buffer MUST be 16 bytes to save IPv6, and should be
* 4-byte aligned if the result will be used as struct in_addr.
* e.g. uint32_t dst[4]
*
* \note \cn is parsed as an IPv6 address if string contains ':',
* else \cn is parsed as an IPv4 address.
*
* \return Length of binary IP address; num bytes written to target.
* \return \c 0 on failure to parse CN string as an IP address.
*/
size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst);
#define MBEDTLS_X509_SAFE_SNPRINTF \ #define MBEDTLS_X509_SAFE_SNPRINTF \
do { \ do { \
if (ret < 0 || (size_t) ret >= n) \ if (ret < 0 || (size_t) ret >= n) \

View file

@ -2862,7 +2862,6 @@ static int x509_inet_pton_ipv4(const char *src, void *dst)
#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names #endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names
MBEDTLS_STATIC_TESTABLE
size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst)
{ {
return strchr(cn, ':') == NULL return strchr(cn, ':') == NULL

View file

@ -1,53 +0,0 @@
/**
* \file x509_invasive.h
*
* \brief x509 module: interfaces for invasive testing only.
*
* The interfaces in this file are intended for testing purposes only.
* They SHOULD NOT be made available in library integrations except when
* building the library for testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_X509_INVASIVE_H
#define MBEDTLS_X509_INVASIVE_H
#include "common.h"
#if defined(MBEDTLS_TEST_HOOKS)
/**
* \brief This function parses a CN string as an IP address.
*
* \param cn The CN string to parse. CN string MUST be NUL-terminated.
* \param dst The target buffer to populate with the binary IP address.
* The buffer MUST be 16 bytes to save IPv6, and should be
* 4-byte aligned if the result will be used as struct in_addr.
* e.g. uint32_t dst[4]
*
* \note \cn is parsed as an IPv6 address if string contains ':',
* else \cn is parsed as an IPv4 address.
*
* \return Length of binary IP address; num bytes written to target.
* \return \c 0 on failure to parse CN string as an IP address.
*/
size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst);
#endif /* MBEDTLS_TEST_HOOKS */
#endif /* MBEDTLS_X509_INVASIVE_H */

View file

@ -116,18 +116,6 @@ struct options {
mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */ mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */
} opt; } opt;
static void ip_string_to_bytes(const char *str, uint8_t *bytes, int maxBytes)
{
for (int i = 0; i < maxBytes; i++) {
bytes[i] = (uint8_t) strtoul(str, NULL, 10);
str = strchr(str, '.');
if (str == NULL || *str == '\0') {
break;
}
str++;
}
}
int write_certificate_request(mbedtls_x509write_csr *req, const char *output_file, int write_certificate_request(mbedtls_x509write_csr *req, const char *output_file,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng) void *p_rng)
@ -165,12 +153,13 @@ int main(int argc, char *argv[])
mbedtls_pk_context key; mbedtls_pk_context key;
char buf[1024]; char buf[1024];
int i; int i;
char *p, *q, *r, *r2; char *p, *q, *r, *subtype_value;
mbedtls_x509write_csr req; mbedtls_x509write_csr req;
mbedtls_entropy_context entropy; mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "csr example app"; const char *pers = "csr example app";
mbedtls_x509_san_list *cur, *prev; mbedtls_x509_san_list *cur, *prev;
uint8_t ip[4] = { 0 };
/* /*
* Set to sane values * Set to sane values
@ -231,8 +220,6 @@ usage:
prev = NULL; prev = NULL;
while (q != NULL) { while (q != NULL) {
uint8_t ip[4] = { 0 };
if ((r = strchr(q, ';')) != NULL) { if ((r = strchr(q, ';')) != NULL) {
*r++ = '\0'; *r++ = '\0';
} }
@ -245,8 +232,8 @@ usage:
cur->next = NULL; cur->next = NULL;
if ((r2 = strchr(q, ':')) != NULL) { if ((subtype_value = strchr(q, ':')) != NULL) {
*r2++ = '\0'; *subtype_value++ = '\0';
} }
if (strcmp(q, "URI") == 0) { if (strcmp(q, "URI") == 0) {
@ -254,8 +241,12 @@ usage:
} else if (strcmp(q, "DNS") == 0) { } else if (strcmp(q, "DNS") == 0) {
cur->node.type = MBEDTLS_X509_SAN_DNS_NAME; cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
} else if (strcmp(q, "IP") == 0) { } else if (strcmp(q, "IP") == 0) {
size_t ip_len = 0;
cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS; cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
ip_string_to_bytes(r2, ip, 4); ip_len = mbedtls_x509_crt_parse_cn_inet_pton(subtype_value, ip);
if (ip_len == 0) {
goto exit;
}
} else { } else {
mbedtls_free(cur); mbedtls_free(cur);
goto usage; goto usage;
@ -265,7 +256,7 @@ usage:
cur->node.san.unstructured_name.p = (unsigned char *) ip; cur->node.san.unstructured_name.p = (unsigned char *) ip;
cur->node.san.unstructured_name.len = sizeof(ip); cur->node.san.unstructured_name.len = sizeof(ip);
} else { } else {
q = r2; q = subtype_value;
cur->node.san.unstructured_name.p = (unsigned char *) q; cur->node.san.unstructured_name.p = (unsigned char *) q;
cur->node.san.unstructured_name.len = strlen(q); cur->node.san.unstructured_name.len = strlen(q);
} }

View file

@ -216,18 +216,6 @@ struct options {
int format; /* format */ int format; /* format */
} opt; } opt;
static void ip_string_to_bytes(const char *str, uint8_t *bytes, int maxBytes)
{
for (int i = 0; i < maxBytes; i++) {
bytes[i] = (uint8_t) strtoul(str, NULL, 10);
str = strchr(str, '.');
if (str == NULL || *str == '\0') {
break;
}
str++;
}
}
int write_certificate(mbedtls_x509write_cert *crt, const char *output_file, int write_certificate(mbedtls_x509write_cert *crt, const char *output_file,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng) void *p_rng)
@ -601,8 +589,14 @@ usage:
} else if (strcmp(q, "DNS") == 0) { } else if (strcmp(q, "DNS") == 0) {
cur->node.type = MBEDTLS_X509_SAN_DNS_NAME; cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
} else if (strcmp(q, "IP") == 0) { } else if (strcmp(q, "IP") == 0) {
size_t ip_len = 0;
cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS; cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
ip_string_to_bytes(subtype_value, ip, 4); ip_len = mbedtls_x509_crt_parse_cn_inet_pton(subtype_value, ip);
if (ip_len == 0) {
mbedtls_printf("mbedtls_x509_crt_parse_cn_inet_pton failed to parse %s\n",
subtype_value);
goto exit;
}
cur->node.san.unstructured_name.p = (unsigned char *) ip; cur->node.san.unstructured_name.p = (unsigned char *) ip;
cur->node.san.unstructured_name.len = sizeof(ip); cur->node.san.unstructured_name.len = sizeof(ip);
} else if (strcmp(q, "DN") == 0) { } else if (strcmp(q, "DN") == 0) {
@ -625,8 +619,9 @@ usage:
if (cur->node.type == MBEDTLS_X509_SAN_RFC822_NAME || if (cur->node.type == MBEDTLS_X509_SAN_RFC822_NAME ||
cur->node.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER || cur->node.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER ||
cur->node.type == MBEDTLS_X509_SAN_DNS_NAME) { cur->node.type == MBEDTLS_X509_SAN_DNS_NAME) {
cur->node.san.unstructured_name.p = (unsigned char *) subtype_value; q = subtype_value;
cur->node.san.unstructured_name.len = strlen(subtype_value); cur->node.san.unstructured_name.p = (unsigned char *) q;
cur->node.san.unstructured_name.len = strlen(q);
} }
if (prev == NULL) { if (prev == NULL) {