|
| 1 | +diff --git a/Middleware/ARM/mbedtls/library/x509_crt.c b/Middleware/ARM/mbedtls/library/x509_crt.c |
| 2 | +index c8654445dd..7b90a4858f 100644 |
| 3 | +--- a/Middleware/ARM/mbedtls/library/x509_crt.c |
| 4 | ++++ b/Middleware/ARM/mbedtls/library/x509_crt.c |
| 5 | +@@ -2996,9 +2996,258 @@ static int x509_crt_check_cn( const mbedtls_x509_buf *name, |
| 6 | + return( -1 ); |
| 7 | + } |
| 8 | + |
| 9 | ++#ifdef MBEDTLS_CUSTOM_SAN_IP_VERIF |
| 10 | ++ /* Use whether or not AF_INET6 is defined to indicate whether or not to use |
| 11 | ++ * the platform inet_pton() or a local implementation (below). The local |
| 12 | ++ * implementation may be used even in cases where the platform provides |
| 13 | ++ * inet_pton(), e.g. when there are different includes required and/or the |
| 14 | ++ * platform implementation requires dependencies on additional libraries. |
| 15 | ++ * Specifically, Windows requires custom includes and additional link |
| 16 | ++ * dependencies, and Solaris requires additional link dependencies. |
| 17 | ++ * Also, as a coarse heuristic, use the local implementation if the compiler |
| 18 | ++ * does not support __has_include(), or if the definition of AF_INET6 is not |
| 19 | ++ * provided by headers included (or not) via __has_include() above. |
| 20 | ++ * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names |
| 21 | ++ * despite having a platform that has inet_pton. */ |
| 22 | ++#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names |
| 23 | ++/* Definition located further below to possibly reduce compiler inlining */ |
| 24 | ++static int x509_inet_pton_ipv4(const char *src, void *dst); |
| 25 | ++ |
| 26 | ++#define li_cton(c, n) \ |
| 27 | ++ (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) |
| 28 | ++ |
| 29 | ++static int x509_inet_pton_ipv6(const char *src, void *dst) |
| 30 | ++{ |
| 31 | ++ const unsigned char *p = (const unsigned char *) src; |
| 32 | ++ int nonzero_groups = 0, num_digits, zero_group_start = -1; |
| 33 | ++ uint16_t addr[8]; |
| 34 | ++ do { |
| 35 | ++ /* note: allows excess leading 0's, e.g. 1:0002:3:... */ |
| 36 | ++ uint16_t group = num_digits = 0; |
| 37 | ++ for (uint8_t digit; num_digits < 4; num_digits++) { |
| 38 | ++ if (li_cton(*p, digit) == 0) { |
| 39 | ++ break; |
| 40 | ++ } |
| 41 | ++ group = (group << 4) | digit; |
| 42 | ++ p++; |
| 43 | ++ } |
| 44 | ++ if (num_digits != 0) { |
| 45 | ++ MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); |
| 46 | ++ nonzero_groups++; |
| 47 | ++ if (*p == '\0') { |
| 48 | ++ break; |
| 49 | ++ } else if (*p == '.') { |
| 50 | ++ /* Don't accept IPv4 too early or late */ |
| 51 | ++ if ((nonzero_groups == 0 && zero_group_start == -1) || |
| 52 | ++ nonzero_groups >= 7) { |
| 53 | ++ break; |
| 54 | ++ } |
| 55 | ++ |
| 56 | ++ /* Walk back to prior ':', then parse as IPv4-mapped */ |
| 57 | ++ int steps = 4; |
| 58 | ++ do { |
| 59 | ++ p--; |
| 60 | ++ steps--; |
| 61 | ++ } while (*p != ':' && steps > 0); |
| 62 | ++ |
| 63 | ++ if (*p != ':') { |
| 64 | ++ break; |
| 65 | ++ } |
| 66 | ++ p++; |
| 67 | ++ nonzero_groups--; |
| 68 | ++ if (x509_inet_pton_ipv4((const char *) p, |
| 69 | ++ addr + nonzero_groups) != 0) { |
| 70 | ++ break; |
| 71 | ++ } |
| 72 | ++ |
| 73 | ++ nonzero_groups += 2; |
| 74 | ++ p = (const unsigned char *) ""; |
| 75 | ++ break; |
| 76 | ++ } else if (*p != ':') { |
| 77 | ++ return -1; |
| 78 | ++ } |
| 79 | ++ } else { |
| 80 | ++ /* Don't accept a second zero group or an invalid delimiter */ |
| 81 | ++ if (zero_group_start != -1 || *p != ':') { |
| 82 | ++ return -1; |
| 83 | ++ } |
| 84 | ++ zero_group_start = nonzero_groups; |
| 85 | ++ |
| 86 | ++ /* Accept a zero group at start, but it has to be a double colon */ |
| 87 | ++ if (zero_group_start == 0 && *++p != ':') { |
| 88 | ++ return -1; |
| 89 | ++ } |
| 90 | ++ |
| 91 | ++ if (p[1] == '\0') { |
| 92 | ++ ++p; |
| 93 | ++ break; |
| 94 | ++ } |
| 95 | ++ } |
| 96 | ++ ++p; |
| 97 | ++ } while (nonzero_groups < 8); |
| 98 | ++ |
| 99 | ++ if (*p != '\0') { |
| 100 | ++ return -1; |
| 101 | ++ } |
| 102 | ++ |
| 103 | ++ if (zero_group_start != -1) { |
| 104 | ++ if (nonzero_groups > 6) { |
| 105 | ++ return -1; |
| 106 | ++ } |
| 107 | ++ int zero_groups = 8 - nonzero_groups; |
| 108 | ++ int groups_after_zero = nonzero_groups - zero_group_start; |
| 109 | ++ |
| 110 | ++ /* Move the non-zero part to after the zeroes */ |
| 111 | ++ if (groups_after_zero) { |
| 112 | ++ memmove(addr + zero_group_start + zero_groups, |
| 113 | ++ addr + zero_group_start, |
| 114 | ++ groups_after_zero * sizeof(*addr)); |
| 115 | ++ } |
| 116 | ++ memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); |
| 117 | ++ } else { |
| 118 | ++ if (nonzero_groups != 8) { |
| 119 | ++ return -1; |
| 120 | ++ } |
| 121 | ++ } |
| 122 | ++ memcpy(dst, addr, sizeof(addr)); |
| 123 | ++ return 0; |
| 124 | ++} |
| 125 | ++ |
| 126 | ++static int x509_inet_pton_ipv4(const char *src, void *dst) |
| 127 | ++{ |
| 128 | ++ const unsigned char *p = (const unsigned char *) src; |
| 129 | ++ uint8_t *res = (uint8_t *) dst; |
| 130 | ++ uint8_t digit, num_digits = 0; |
| 131 | ++ uint8_t num_octets = 0; |
| 132 | ++ uint16_t octet; |
| 133 | ++ |
| 134 | ++ do { |
| 135 | ++ octet = num_digits = 0; |
| 136 | ++ do { |
| 137 | ++ digit = *p - '0'; |
| 138 | ++ if (digit > 9) { |
| 139 | ++ break; |
| 140 | ++ } |
| 141 | ++ |
| 142 | ++ /* Don't allow leading zeroes. These might mean octal format, |
| 143 | ++ * which this implementation does not support. */ |
| 144 | ++ if (octet == 0 && num_digits > 0) { |
| 145 | ++ return -1; |
| 146 | ++ } |
| 147 | ++ |
| 148 | ++ octet = octet * 10 + digit; |
| 149 | ++ num_digits++; |
| 150 | ++ p++; |
| 151 | ++ } while (num_digits < 3); |
| 152 | ++ |
| 153 | ++ if (octet >= 256 || num_digits > 3 || num_digits == 0) { |
| 154 | ++ return -1; |
| 155 | ++ } |
| 156 | ++ *res++ = (uint8_t) octet; |
| 157 | ++ num_octets++; |
| 158 | ++ } while (num_octets < 4 && *p++ == '.'); |
| 159 | ++ return num_octets == 4 && *p == '\0' ? 0 : -1; |
| 160 | ++} |
| 161 | ++ |
| 162 | ++#else |
| 163 | ++ |
| 164 | ++static int x509_inet_pton_ipv6(const char *src, void *dst) |
| 165 | ++{ |
| 166 | ++ return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; |
| 167 | ++} |
| 168 | ++ |
| 169 | ++static int x509_inet_pton_ipv4(const char *src, void *dst) |
| 170 | ++{ |
| 171 | ++ return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; |
| 172 | ++} |
| 173 | ++ |
| 174 | ++#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names |
| 175 | ++ |
| 176 | ++size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) |
| 177 | ++{ |
| 178 | ++ return strchr(cn, ':') == NULL |
| 179 | ++ ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 |
| 180 | ++ : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; |
| 181 | ++} |
| 182 | ++ |
| 183 | ++static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, |
| 184 | ++ const char *cn, size_t cn_len) |
| 185 | ++{ |
| 186 | ++ uint32_t ip[4]; |
| 187 | ++ cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); |
| 188 | ++ if (cn_len == 0) { |
| 189 | ++ return -1; |
| 190 | ++ } |
| 191 | ++ |
| 192 | ++ for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { |
| 193 | ++ const unsigned char san_type = (unsigned char) cur->buf.tag & |
| 194 | ++ MBEDTLS_ASN1_TAG_VALUE_MASK; |
| 195 | ++ if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && |
| 196 | ++ cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { |
| 197 | ++ return 0; |
| 198 | ++ } |
| 199 | ++ } |
| 200 | ++ |
| 201 | ++ return -1; |
| 202 | ++} |
| 203 | ++ |
| 204 | ++static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, |
| 205 | ++ const char *cn, size_t cn_len) |
| 206 | ++{ |
| 207 | ++ for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { |
| 208 | ++ const unsigned char san_type = (unsigned char) cur->buf.tag & |
| 209 | ++ MBEDTLS_ASN1_TAG_VALUE_MASK; |
| 210 | ++ if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && |
| 211 | ++ cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { |
| 212 | ++ return 0; |
| 213 | ++ } |
| 214 | ++ } |
| 215 | ++ |
| 216 | ++ return -1; |
| 217 | ++} |
| 218 | ++ |
| 219 | + /* |
| 220 | + * Check for SAN match, see RFC 5280 Section 4.2.1.6 |
| 221 | + */ |
| 222 | ++ |
| 223 | ++static int x509_crt_check_san(const mbedtls_x509_sequence *san, |
| 224 | ++ const char *cn, size_t cn_len) |
| 225 | ++{ |
| 226 | ++ int san_ip = 0; |
| 227 | ++ int san_uri = 0; |
| 228 | ++ /* Prioritize DNS name over other subtypes due to popularity */ |
| 229 | ++ for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { |
| 230 | ++ switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { |
| 231 | ++ case MBEDTLS_X509_SAN_DNS_NAME: |
| 232 | ++ if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { |
| 233 | ++ return 0; |
| 234 | ++ } |
| 235 | ++ break; |
| 236 | ++ case MBEDTLS_X509_SAN_IP_ADDRESS: |
| 237 | ++ san_ip = 1; |
| 238 | ++ break; |
| 239 | ++ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: |
| 240 | ++ san_uri = 1; |
| 241 | ++ break; |
| 242 | ++ /* (We may handle other types here later.) */ |
| 243 | ++ default: /* Unrecognized type */ |
| 244 | ++ break; |
| 245 | ++ } |
| 246 | ++ } |
| 247 | ++ if (san_ip) { |
| 248 | ++ if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { |
| 249 | ++ return 0; |
| 250 | ++ } |
| 251 | ++ } |
| 252 | ++ if (san_uri) { |
| 253 | ++ if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { |
| 254 | ++ return 0; |
| 255 | ++ } |
| 256 | ++ } |
| 257 | ++ |
| 258 | ++ return -1; |
| 259 | ++} |
| 260 | ++#else |
| 261 | + static int x509_crt_check_san( const mbedtls_x509_buf *name, |
| 262 | + const char *cn, size_t cn_len ) |
| 263 | + { |
| 264 | +@@ -3014,6 +3263,7 @@ static int x509_crt_check_san( const mbedtls_x509_buf *name, |
| 265 | + /* Unrecognized type */ |
| 266 | + return( -1 ); |
| 267 | + } |
| 268 | ++#endif /* MBEDTLS_CUSTOM_SAN_IP_VERIF */ |
| 269 | + |
| 270 | + /* |
| 271 | + * Verify the requested CN - only call this if cn is not NULL! |
0 commit comments