x509write.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * X.509 internal, common functions for writing
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. #include "common.h"
  8. #if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C)
  9. #include "mbedtls/x509_crt.h"
  10. #include "x509_internal.h"
  11. #include "mbedtls/asn1write.h"
  12. #include "mbedtls/error.h"
  13. #include "mbedtls/oid.h"
  14. #include "mbedtls/platform.h"
  15. #include "mbedtls/platform_util.h"
  16. #include <string.h>
  17. #include <stdint.h>
  18. #if defined(MBEDTLS_PEM_WRITE_C)
  19. #include "mbedtls/pem.h"
  20. #endif /* MBEDTLS_PEM_WRITE_C */
  21. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  22. #include "psa/crypto.h"
  23. #include "mbedtls/psa_util.h"
  24. #include "md_psa.h"
  25. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  26. #define CHECK_OVERFLOW_ADD(a, b) \
  27. do \
  28. { \
  29. if (a > SIZE_MAX - (b)) \
  30. { \
  31. return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \
  32. } \
  33. a += b; \
  34. } while (0)
  35. int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,
  36. const mbedtls_x509_san_list *san_list)
  37. {
  38. int ret = 0;
  39. const mbedtls_x509_san_list *cur;
  40. unsigned char *buf;
  41. unsigned char *p;
  42. size_t len;
  43. size_t buflen = 0;
  44. /* Determine the maximum size of the SubjectAltName list */
  45. for (cur = san_list; cur != NULL; cur = cur->next) {
  46. /* Calculate size of the required buffer */
  47. switch (cur->node.type) {
  48. case MBEDTLS_X509_SAN_DNS_NAME:
  49. case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
  50. case MBEDTLS_X509_SAN_IP_ADDRESS:
  51. case MBEDTLS_X509_SAN_RFC822_NAME:
  52. /* length of value for each name entry,
  53. * maximum 4 bytes for the length field,
  54. * 1 byte for the tag/type.
  55. */
  56. CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len);
  57. CHECK_OVERFLOW_ADD(buflen, 4 + 1);
  58. break;
  59. case MBEDTLS_X509_SAN_DIRECTORY_NAME:
  60. {
  61. const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name;
  62. while (chunk != NULL) {
  63. // Max 4 bytes for length, +1 for tag,
  64. // additional 4 max for length, +1 for tag.
  65. // See x509_write_name for more information.
  66. CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1);
  67. CHECK_OVERFLOW_ADD(buflen, chunk->oid.len);
  68. CHECK_OVERFLOW_ADD(buflen, chunk->val.len);
  69. chunk = chunk->next;
  70. }
  71. CHECK_OVERFLOW_ADD(buflen, 4 + 1);
  72. break;
  73. }
  74. default:
  75. /* Not supported - return. */
  76. return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
  77. }
  78. }
  79. /* Add the extra length field and tag */
  80. CHECK_OVERFLOW_ADD(buflen, 4 + 1);
  81. /* Allocate buffer */
  82. buf = mbedtls_calloc(1, buflen);
  83. if (buf == NULL) {
  84. return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
  85. }
  86. p = buf + buflen;
  87. /* Write ASN.1-based structure */
  88. cur = san_list;
  89. len = 0;
  90. while (cur != NULL) {
  91. size_t single_san_len = 0;
  92. switch (cur->node.type) {
  93. case MBEDTLS_X509_SAN_DNS_NAME:
  94. case MBEDTLS_X509_SAN_RFC822_NAME:
  95. case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
  96. case MBEDTLS_X509_SAN_IP_ADDRESS:
  97. {
  98. const unsigned char *unstructured_name =
  99. (const unsigned char *) cur->node.san.unstructured_name.p;
  100. size_t unstructured_name_len = cur->node.san.unstructured_name.len;
  101. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
  102. mbedtls_asn1_write_raw_buffer(
  103. &p, buf,
  104. unstructured_name, unstructured_name_len));
  105. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len(
  106. &p, buf, unstructured_name_len));
  107. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
  108. mbedtls_asn1_write_tag(
  109. &p, buf,
  110. MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));
  111. }
  112. break;
  113. case MBEDTLS_X509_SAN_DIRECTORY_NAME:
  114. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
  115. mbedtls_x509_write_names(&p, buf,
  116. (mbedtls_asn1_named_data *) &
  117. cur->node
  118. .san.directory_name));
  119. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
  120. mbedtls_asn1_write_len(&p, buf, single_san_len));
  121. MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
  122. mbedtls_asn1_write_tag(&p, buf,
  123. MBEDTLS_ASN1_CONTEXT_SPECIFIC |
  124. MBEDTLS_ASN1_CONSTRUCTED |
  125. MBEDTLS_X509_SAN_DIRECTORY_NAME));
  126. break;
  127. default:
  128. /* Error out on an unsupported SAN */
  129. ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
  130. goto cleanup;
  131. }
  132. cur = cur->next;
  133. /* check for overflow */
  134. if (len > SIZE_MAX - single_san_len) {
  135. ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
  136. goto cleanup;
  137. }
  138. len += single_san_len;
  139. }
  140. MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
  141. MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
  142. mbedtls_asn1_write_tag(&p, buf,
  143. MBEDTLS_ASN1_CONSTRUCTED |
  144. MBEDTLS_ASN1_SEQUENCE));
  145. ret = mbedtls_x509_set_extension(extensions,
  146. MBEDTLS_OID_SUBJECT_ALT_NAME,
  147. MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
  148. 0,
  149. buf + buflen - len, len);
  150. /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list
  151. * was incorrectly calculated and memory is corrupted. */
  152. if (p < buf) {
  153. ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
  154. }
  155. cleanup:
  156. mbedtls_free(buf);
  157. return ret;
  158. }
  159. #endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */