blob: b600f456e924617f0d0b79d060d2e080ff4f6617 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +02002 * X.509 common functions for parsing and verification
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker7c6b2c32013-09-16 13:49:26 +020018 */
19/*
20 * The ITU-T X.509 standard defines a certificate format for PKI.
21 *
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +020022 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
23 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
24 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020025 *
26 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
27 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
28 */
29
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_X509_USE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/x509.h"
35#include "mbedtls/asn1.h"
Janos Follath73c616b2019-12-18 15:07:04 +000036#include "mbedtls/error.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/oid.h"
Rich Evans00ab4702015-02-06 13:43:58 +000038
Rich Evans36796df2015-02-12 18:27:14 +000039#include <stdio.h>
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020044#endif
45
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020047
Simon Butcherb5b6af22016-07-13 14:46:18 +010048#if defined(MBEDTLS_HAVE_TIME)
49#include "mbedtls/platform_time.h"
50#endif
Nicholas Wilson512b4ee2017-12-05 12:07:33 +000051#if defined(MBEDTLS_HAVE_TIME_DATE)
Andres Amaya Garcia1abb3682018-08-16 21:42:09 +010052#include "mbedtls/platform_util.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020053#include <time.h>
54#endif
55
Demi Marie Obenour690b8c92022-12-04 04:24:22 -050056#define CHECK(code) \
57 do { \
58 if ((ret = (code)) != 0) { \
59 return ret; \
60 } \
61 } while (0)
62
Hanno Becker1eeca412018-10-15 12:01:35 +010063#define CHECK_RANGE(min, max, val) \
Demi Marie Obenour690b8c92022-12-04 04:24:22 -050064 do { \
65 if ((val) < (min) || (val) > (max)) { \
66 return ret; \
Hanno Becker1eeca412018-10-15 12:01:35 +010067 } \
Gilles Peskine449bd832023-01-11 14:50:10 +010068 } while (0)
Rich Evans7d5a55a2015-02-13 11:48:02 +000069
Paul Bakker7c6b2c32013-09-16 13:49:26 +020070/*
71 * CertificateSerialNumber ::= INTEGER
72 */
Gilles Peskine449bd832023-01-11 14:50:10 +010073int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
74 mbedtls_x509_buf *serial)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020075{
Janos Follath865b3eb2019-12-16 11:46:15 +000076 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020077
Gilles Peskine449bd832023-01-11 14:50:10 +010078 if ((end - *p) < 1) {
79 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
80 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
81 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +020082
Gilles Peskine449bd832023-01-11 14:50:10 +010083 if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
84 **p != MBEDTLS_ASN1_INTEGER) {
85 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
86 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
87 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +020088
89 serial->tag = *(*p)++;
90
Gilles Peskine449bd832023-01-11 14:50:10 +010091 if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
92 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
93 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +020094
95 serial->p = *p;
96 *p += serial->len;
97
Gilles Peskine449bd832023-01-11 14:50:10 +010098 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020099}
100
101/* Get an algorithm identifier without parameters (eg for signatures)
102 *
103 * AlgorithmIdentifier ::= SEQUENCE {
104 * algorithm OBJECT IDENTIFIER,
105 * parameters ANY DEFINED BY algorithm OPTIONAL }
106 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100107int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
108 mbedtls_x509_buf *alg)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200109{
Janos Follath865b3eb2019-12-16 11:46:15 +0000110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200111
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
113 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
114 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200117}
118
119/*
Antonin Décimo36e89b52019-01-23 15:24:37 +0100120 * Parse an algorithm identifier with (optional) parameters
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100121 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100122int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
123 mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100124{
Janos Follath865b3eb2019-12-16 11:46:15 +0000125 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100126
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
128 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
129 }
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 return 0;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100132}
133
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200134/*
135 * Convert md type to string
136 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200138{
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 switch (md_alg) {
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100140#if defined(MBEDTLS_MD_CAN_MD5)
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 case MBEDTLS_MD_MD5:
142 return "MD5";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200143#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100144#if defined(MBEDTLS_MD_CAN_SHA1)
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 case MBEDTLS_MD_SHA1:
146 return "SHA1";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200147#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100148#if defined(MBEDTLS_MD_CAN_SHA224)
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 case MBEDTLS_MD_SHA224:
150 return "SHA224";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200151#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100152#if defined(MBEDTLS_MD_CAN_SHA256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 case MBEDTLS_MD_SHA256:
154 return "SHA256";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200155#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100156#if defined(MBEDTLS_MD_CAN_SHA384)
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 case MBEDTLS_MD_SHA384:
158 return "SHA384";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200159#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100160#if defined(MBEDTLS_MD_CAN_SHA512)
Gilles Peskine449bd832023-01-11 14:50:10 +0100161 case MBEDTLS_MD_SHA512:
162 return "SHA512";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200163#endif
Manuel Pégourié-Gonnard49e67f82023-03-16 11:39:20 +0100164#if defined(MBEDTLS_MD_CAN_RIPEMD160)
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 case MBEDTLS_MD_RIPEMD160:
166 return "RIPEMD160";
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200167#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 case MBEDTLS_MD_NONE:
169 return NULL;
170 default:
171 return NULL;
Przemek Stekiel6230d0d2022-06-27 11:19:04 +0200172 }
173}
174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100176/*
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100177 * HashAlgorithm ::= AlgorithmIdentifier
178 *
179 * AlgorithmIdentifier ::= SEQUENCE {
180 * algorithm OBJECT IDENTIFIER,
181 * parameters ANY DEFINED BY algorithm OPTIONAL }
182 *
183 * For HashAlgorithm, parameters MUST be NULL or absent.
184 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100185static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100186{
Janos Follath865b3eb2019-12-16 11:46:15 +0000187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100188 unsigned char *p;
189 const unsigned char *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_x509_buf md_oid;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100191 size_t len;
192
193 /* Make sure we got a SEQUENCE and setup bounds */
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
195 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
196 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
197 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100198
Andrzej Kurekfeaebc52020-07-16 04:37:41 -0400199 p = alg->p;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100200 end = p + alg->len;
201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 if (p >= end) {
203 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
204 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
205 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100206
207 /* Parse md_oid */
208 md_oid.tag = *p;
209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
211 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
212 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100213
214 md_oid.p = p;
215 p += md_oid.len;
216
217 /* Get md_alg from md_oid */
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
219 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
220 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100221
222 /* Make sure params is absent of NULL */
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 if (p == end) {
224 return 0;
225 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
228 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
229 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (p != end) {
232 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
233 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
234 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 return 0;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100237}
238
239/*
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100240 * RSASSA-PSS-params ::= SEQUENCE {
241 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
242 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
243 * saltLength [2] INTEGER DEFAULT 20,
244 * trailerField [3] INTEGER DEFAULT 1 }
245 * -- Note that the tags in this Sequence are explicit.
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200246 *
247 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
248 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
Tom Cosgrove1797b052022-12-04 17:19:59 +0000249 * option. Enforce this at parsing time.
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100250 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100251int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
252 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
253 int *salt_len)
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100254{
Janos Follath865b3eb2019-12-16 11:46:15 +0000255 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100256 unsigned char *p;
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100257 const unsigned char *end, *end2;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100258 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 mbedtls_x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100260
261 /* First set everything to defaults */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 *md_alg = MBEDTLS_MD_SHA1;
263 *mgf_md = MBEDTLS_MD_SHA1;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100264 *salt_len = 20;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100265
266 /* Make sure params is a SEQUENCE and setup bounds */
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
268 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
269 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
270 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100271
272 p = (unsigned char *) params->p;
273 end = p + params->len;
274
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 if (p == end) {
276 return 0;
277 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100278
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100279 /*
280 * HashAlgorithm
281 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
283 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
284 0)) == 0) {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100285 end2 = p + len;
286
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100287 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
289 return ret;
290 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
293 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
294 }
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 if (p != end2) {
297 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
298 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
299 }
300 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
301 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100302 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if (p == end) {
305 return 0;
306 }
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100307
308 /*
309 * MaskGenAlgorithm
310 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
312 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
313 1)) == 0) {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100314 end2 = p + len;
315
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100316 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
318 return ret;
319 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100320
321 /* Only MFG1 is recognised for now */
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
323 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
324 MBEDTLS_ERR_OID_NOT_FOUND);
325 }
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100326
327 /* Parse HashAlgorithm */
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
329 return ret;
330 }
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100331
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 if (p != end2) {
333 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
334 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
335 }
336 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
337 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100338 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100339
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 if (p == end) {
341 return 0;
342 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100343
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100344 /*
345 * salt_len
346 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
348 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
349 2)) == 0) {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100350 end2 = p + len;
351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
353 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
354 }
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100355
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 if (p != end2) {
357 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
358 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
359 }
360 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
361 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100362 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100363
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 if (p == end) {
365 return 0;
366 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100367
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100368 /*
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200369 * trailer_field (if present, must be 1)
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100370 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
372 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
373 3)) == 0) {
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200374 int trailer_field;
375
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100376 end2 = p + len;
377
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
379 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
380 }
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100381
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 if (p != end2) {
383 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
384 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
385 }
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 if (trailer_field != 1) {
388 return MBEDTLS_ERR_X509_INVALID_ALG;
389 }
390 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
391 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100392 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (p != end) {
395 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
396 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
397 }
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 return 0;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100400}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100402
403/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200404 * AttributeTypeAndValue ::= SEQUENCE {
405 * type AttributeType,
406 * value AttributeValue }
407 *
408 * AttributeType ::= OBJECT IDENTIFIER
409 *
410 * AttributeValue ::= ANY DEFINED BY AttributeType
411 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100412static int x509_get_attr_type_value(unsigned char **p,
413 const unsigned char *end,
414 mbedtls_x509_name *cur)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415{
Janos Follath865b3eb2019-12-16 11:46:15 +0000416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200417 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 mbedtls_x509_buf *oid;
419 mbedtls_x509_buf *val;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200420
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
422 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
423 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
424 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200425
Hanno Becker12f62fb2019-02-12 17:22:36 +0000426 end = *p + len;
427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428 if ((end - *p) < 1) {
429 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
430 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
431 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200432
433 oid = &cur->oid;
434 oid->tag = **p;
435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
437 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
438 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200439
440 oid->p = *p;
441 *p += oid->len;
442
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 if ((end - *p) < 1) {
444 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
445 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
446 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
450 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 **p != MBEDTLS_ASN1_BIT_STRING) {
452 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
453 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
454 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200455
456 val = &cur->val;
457 val->tag = *(*p)++;
458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
460 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
461 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200462
463 val->p = *p;
464 *p += val->len;
465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 if (*p != end) {
467 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
468 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Hanno Becker12f62fb2019-02-12 17:22:36 +0000469 }
470
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200471 cur->next = NULL;
472
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200474}
475
476/*
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000477 * Name ::= CHOICE { -- only one possibility for now --
478 * rdnSequence RDNSequence }
479 *
480 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
481 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200482 * RelativeDistinguishedName ::=
483 * SET OF AttributeTypeAndValue
484 *
485 * AttributeTypeAndValue ::= SEQUENCE {
486 * type AttributeType,
487 * value AttributeValue }
488 *
489 * AttributeType ::= OBJECT IDENTIFIER
490 *
491 * AttributeValue ::= ANY DEFINED BY AttributeType
Manuel Pégourié-Gonnard5d861852014-10-17 12:41:41 +0200492 *
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000493 * The data structure is optimized for the common case where each RDN has only
494 * one element, which is represented as a list of AttributeTypeAndValue.
495 * For the general case we still use a flat list, but we mark elements of the
496 * same set so that they are "merged" together in the functions that consume
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 * this list, eg mbedtls_x509_dn_gets().
David Horstmanned794832022-10-04 18:12:06 +0100498 *
David Horstmann11307a12022-10-17 18:10:23 +0100499 * On success, this function may allocate a linked list starting at cur->next
David Horstmanned794832022-10-04 18:12:06 +0100500 * that must later be free'd by the caller using mbedtls_free(). In error
501 * cases, this function frees all allocated memory internally and the caller
502 * has no freeing responsibilities.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200503 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100504int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
505 mbedtls_x509_name *cur)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200506{
Janos Follath865b3eb2019-12-16 11:46:15 +0000507 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard5d861852014-10-17 12:41:41 +0200508 size_t set_len;
509 const unsigned char *end_set;
David Horstmanned794832022-10-04 18:12:06 +0100510 mbedtls_x509_name *head = cur;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200511
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100512 /* don't use recursion, we'd risk stack overflow if not optimized */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 while (1) {
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100514 /*
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000515 * parse SET
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100516 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
518 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
519 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
David Horstmanned794832022-10-04 18:12:06 +0100520 goto error;
521 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200522
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100523 end_set = *p + set_len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200524
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 while (1) {
526 if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
David Horstmanned794832022-10-04 18:12:06 +0100527 goto error;
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200529
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 if (*p == end_set) {
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000531 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 }
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000533
Manuel Pégourié-Gonnardeecb43c2015-05-12 12:56:41 +0200534 /* Mark this item as being no the only one in a set */
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000535 cur->next_merged = 1;
536
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 if (cur->next == NULL) {
David Horstmanned794832022-10-04 18:12:06 +0100540 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
541 goto error;
542 }
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000543
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000544 cur = cur->next;
545 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200546
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100547 /*
548 * continue until end of SEQUENCE is reached
549 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 if (*p == end) {
551 return 0;
552 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200553
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 if (cur->next == NULL) {
David Horstmanned794832022-10-04 18:12:06 +0100557 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
558 goto error;
559 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200560
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100561 cur = cur->next;
562 }
David Horstmanned794832022-10-04 18:12:06 +0100563
564error:
David Horstmanned794832022-10-04 18:12:06 +0100565 /* Skip the first element as we did not allocate it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 mbedtls_asn1_free_named_data_list_shallow(head->next);
Glenn Straussa4b40412022-06-26 19:32:09 -0400567 head->next = NULL;
David Horstmanned794832022-10-04 18:12:06 +0100568
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200570}
571
Gilles Peskine449bd832023-01-11 14:50:10 +0100572static int x509_parse_int(unsigned char **p, size_t n, int *res)
Janos Follath87c98072017-02-03 12:36:59 +0000573{
Rich Evans7d5a55a2015-02-13 11:48:02 +0000574 *res = 0;
Janos Follath87c98072017-02-03 12:36:59 +0000575
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 for (; n > 0; --n) {
577 if ((**p < '0') || (**p > '9')) {
578 return MBEDTLS_ERR_X509_INVALID_DATE;
579 }
Janos Follath87c98072017-02-03 12:36:59 +0000580
Rich Evans7d5a55a2015-02-13 11:48:02 +0000581 *res *= 10;
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 *res += (*(*p)++ - '0');
Rich Evans7d5a55a2015-02-13 11:48:02 +0000583 }
Janos Follath87c98072017-02-03 12:36:59 +0000584
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 return 0;
Rich Evans7d5a55a2015-02-13 11:48:02 +0000586}
587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588static int x509_date_is_valid(const mbedtls_x509_time *t)
Andres AG4b76aec2016-09-23 13:16:02 +0100589{
590 int ret = MBEDTLS_ERR_X509_INVALID_DATE;
Andres Amaya Garcia735b37e2016-11-21 15:38:02 +0000591 int month_len;
Andres AG4b76aec2016-09-23 13:16:02 +0100592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 CHECK_RANGE(0, 9999, t->year);
594 CHECK_RANGE(0, 23, t->hour);
595 CHECK_RANGE(0, 59, t->min);
596 CHECK_RANGE(0, 59, t->sec);
Andres AG4b76aec2016-09-23 13:16:02 +0100597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 switch (t->mon) {
Andres AG4b76aec2016-09-23 13:16:02 +0100599 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
Andres Amaya Garcia735b37e2016-11-21 15:38:02 +0000600 month_len = 31;
Andres AG4b76aec2016-09-23 13:16:02 +0100601 break;
602 case 4: case 6: case 9: case 11:
Andres Amaya Garcia735b37e2016-11-21 15:38:02 +0000603 month_len = 30;
Andres AG4b76aec2016-09-23 13:16:02 +0100604 break;
605 case 2:
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 if ((!(t->year % 4) && t->year % 100) ||
607 !(t->year % 400)) {
Andres Amaya Garcia735b37e2016-11-21 15:38:02 +0000608 month_len = 29;
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 } else {
Andres Amaya Garcia735b37e2016-11-21 15:38:02 +0000610 month_len = 28;
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 }
Andres AG4b76aec2016-09-23 13:16:02 +0100612 break;
613 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 return ret;
Andres AG4b76aec2016-09-23 13:16:02 +0100615 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 CHECK_RANGE(1, month_len, t->day);
Andres AG4b76aec2016-09-23 13:16:02 +0100617
Gilles Peskine449bd832023-01-11 14:50:10 +0100618 return 0;
Andres AG4b76aec2016-09-23 13:16:02 +0100619}
620
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200621/*
Janos Follath87c98072017-02-03 12:36:59 +0000622 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
623 * field.
624 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100625static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen,
626 mbedtls_x509_time *tm)
Janos Follath87c98072017-02-03 12:36:59 +0000627{
Janos Follath865b3eb2019-12-16 11:46:15 +0000628 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath87c98072017-02-03 12:36:59 +0000629
630 /*
631 * Minimum length is 10 or 12 depending on yearlen
632 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 if (len < yearlen + 8) {
634 return MBEDTLS_ERR_X509_INVALID_DATE;
635 }
Janos Follath87c98072017-02-03 12:36:59 +0000636 len -= yearlen + 8;
637
638 /*
639 * Parse year, month, day, hour, minute
640 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 CHECK(x509_parse_int(p, yearlen, &tm->year));
642 if (2 == yearlen) {
643 if (tm->year < 50) {
Hanno Becker61937d42017-04-26 15:01:23 +0100644 tm->year += 100;
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 }
Janos Follath87c98072017-02-03 12:36:59 +0000646
Hanno Becker61937d42017-04-26 15:01:23 +0100647 tm->year += 1900;
Janos Follath87c98072017-02-03 12:36:59 +0000648 }
649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 CHECK(x509_parse_int(p, 2, &tm->mon));
651 CHECK(x509_parse_int(p, 2, &tm->day));
652 CHECK(x509_parse_int(p, 2, &tm->hour));
653 CHECK(x509_parse_int(p, 2, &tm->min));
Janos Follath87c98072017-02-03 12:36:59 +0000654
655 /*
656 * Parse seconds if present
657 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 if (len >= 2) {
659 CHECK(x509_parse_int(p, 2, &tm->sec));
Janos Follath87c98072017-02-03 12:36:59 +0000660 len -= 2;
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 } else {
662 return MBEDTLS_ERR_X509_INVALID_DATE;
Janos Follath87c98072017-02-03 12:36:59 +0000663 }
Janos Follath87c98072017-02-03 12:36:59 +0000664
665 /*
666 * Parse trailing 'Z' if present
667 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 if (1 == len && 'Z' == **p) {
Janos Follath87c98072017-02-03 12:36:59 +0000669 (*p)++;
670 len--;
671 }
672
673 /*
674 * We should have parsed all characters at this point
675 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 if (0 != len) {
677 return MBEDTLS_ERR_X509_INVALID_DATE;
678 }
Janos Follath87c98072017-02-03 12:36:59 +0000679
Gilles Peskine449bd832023-01-11 14:50:10 +0100680 CHECK(x509_date_is_valid(tm));
Janos Follath87c98072017-02-03 12:36:59 +0000681
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 return 0;
Janos Follath87c98072017-02-03 12:36:59 +0000683}
684
685/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200686 * Time ::= CHOICE {
687 * utcTime UTCTime,
688 * generalTime GeneralizedTime }
689 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100690int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
691 mbedtls_x509_time *tm)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200692{
Janos Follath865b3eb2019-12-16 11:46:15 +0000693 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath87c98072017-02-03 12:36:59 +0000694 size_t len, year_len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200695 unsigned char tag;
696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 if ((end - *p) < 1) {
698 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
699 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
700 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200701
702 tag = **p;
703
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 if (tag == MBEDTLS_ASN1_UTC_TIME) {
Janos Follath87c98072017-02-03 12:36:59 +0000705 year_len = 2;
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
Janos Follath87c98072017-02-03 12:36:59 +0000707 year_len = 4;
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 } else {
709 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
710 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
711 }
Janos Follath87c98072017-02-03 12:36:59 +0000712
713 (*p)++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 ret = mbedtls_asn1_get_len(p, end, &len);
Janos Follath87c98072017-02-03 12:36:59 +0000715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 if (ret != 0) {
717 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
718 }
Janos Follath87c98072017-02-03 12:36:59 +0000719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 return x509_parse_time(p, len, year_len, tm);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200721}
722
Gilles Peskine449bd832023-01-11 14:50:10 +0100723int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200724{
Janos Follath865b3eb2019-12-16 11:46:15 +0000725 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200726 size_t len;
Andres AG4bdbe092016-09-19 16:58:45 +0100727 int tag_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 if ((end - *p) < 1) {
730 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
731 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
732 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200733
Andres AG4bdbe092016-09-19 16:58:45 +0100734 tag_type = **p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
737 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
738 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200739
Andres AG4bdbe092016-09-19 16:58:45 +0100740 sig->tag = tag_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200741 sig->len = len;
742 sig->p = *p;
743
744 *p += len;
745
Gilles Peskine449bd832023-01-11 14:50:10 +0100746 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200747}
748
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100749/*
750 * Get signature algorithm from alg OID and optional parameters
751 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100752int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
753 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
754 void **sig_opts)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200755{
Janos Follath865b3eb2019-12-16 11:46:15 +0000756 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 if (*sig_opts != NULL) {
759 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
760 }
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200761
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
763 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
764 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100767 if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_pk_rsassa_pss_options *pss_opts;
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100769
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
771 if (pss_opts == NULL) {
772 return MBEDTLS_ERR_X509_ALLOC_FAILED;
773 }
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200774
Gilles Peskine449bd832023-01-11 14:50:10 +0100775 ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
776 md_alg,
777 &pss_opts->mgf1_hash_id,
778 &pss_opts->expected_salt_len);
779 if (ret != 0) {
780 mbedtls_free(pss_opts);
781 return ret;
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200782 }
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100783
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200784 *sig_opts = (void *) pss_opts;
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 } else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100787 {
788 /* Make sure parameters are absent or NULL */
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
790 sig_params->len != 0) {
791 return MBEDTLS_ERR_X509_INVALID_ALG;
792 }
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100793 }
794
Gilles Peskine449bd832023-01-11 14:50:10 +0100795 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200796}
797
798/*
799 * X.509 Extensions (No parsing of extensions, pointer should
Brian J Murray1903fb32016-11-06 04:45:15 -0800800 * be either manually updated or extensions should be parsed!)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200801 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100802int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
803 mbedtls_x509_buf *ext, int tag)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200804{
Janos Follath865b3eb2019-12-16 11:46:15 +0000805 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200806 size_t len;
807
Hanno Becker3cddba82019-02-11 14:33:36 +0000808 /* Extension structure use EXPLICIT tagging. That is, the actual
809 * `Extensions` structure is wrapped by a tag-length pair using
810 * the respective context-specific tag. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100811 ret = mbedtls_asn1_get_tag(p, end, &ext->len,
812 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
813 if (ret != 0) {
814 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
815 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200816
Hanno Becker6ccfb182019-02-12 11:52:10 +0000817 ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
818 ext->p = *p;
819 end = *p + ext->len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200820
821 /*
822 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200823 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100824 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
825 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
826 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
827 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200828
Gilles Peskine449bd832023-01-11 14:50:10 +0100829 if (end != *p + len) {
830 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
831 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
832 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200833
Gilles Peskine449bd832023-01-11 14:50:10 +0100834 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200835}
836
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200837/*
838 * Store the name in printable form into buf; no more
839 * than size characters will be written
840 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100841int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200842{
Janos Follath865b3eb2019-12-16 11:46:15 +0000843 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Werner Lewisb33dacd2022-05-20 12:48:46 +0100844 size_t i, j, n;
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000845 unsigned char c, merge = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 const mbedtls_x509_name *name;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200847 const char *short_name = NULL;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200849
Gilles Peskine449bd832023-01-11 14:50:10 +0100850 memset(s, 0, sizeof(s));
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200851
852 name = dn;
853 p = buf;
854 n = size;
855
Gilles Peskine449bd832023-01-11 14:50:10 +0100856 while (name != NULL) {
857 if (!name->oid.p) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200858 name = name->next;
859 continue;
860 }
861
Gilles Peskine449bd832023-01-11 14:50:10 +0100862 if (name != dn) {
863 ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200864 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200865 }
866
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200868
Gilles Peskine449bd832023-01-11 14:50:10 +0100869 if (ret == 0) {
870 ret = mbedtls_snprintf(p, n, "%s=", short_name);
871 } else {
872 ret = mbedtls_snprintf(p, n, "\?\?=");
873 }
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200874 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200875
Gilles Peskine449bd832023-01-11 14:50:10 +0100876 for (i = 0, j = 0; i < name->val.len; i++, j++) {
877 if (j >= sizeof(s) - 1) {
878 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
879 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200880
881 c = name->val.p[i];
Werner Lewisb33dacd2022-05-20 12:48:46 +0100882 // Special characters requiring escaping, RFC 1779
Gilles Peskine449bd832023-01-11 14:50:10 +0100883 if (c && strchr(",=+<>#;\"\\", c)) {
884 if (j + 1 >= sizeof(s) - 1) {
885 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
886 }
Werner Lewisb33dacd2022-05-20 12:48:46 +0100887 s[j++] = '\\';
888 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100889 if (c < 32 || c >= 127) {
890 s[j] = '?';
891 } else {
892 s[j] = c;
893 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200894 }
Werner Lewisb33dacd2022-05-20 12:48:46 +0100895 s[j] = '\0';
Gilles Peskine449bd832023-01-11 14:50:10 +0100896 ret = mbedtls_snprintf(p, n, "%s", s);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200897 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000898
899 merge = name->next_merged;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200900 name = name->next;
901 }
902
Gilles Peskine449bd832023-01-11 14:50:10 +0100903 return (int) (size - n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200904}
905
906/*
907 * Store the serial in printable form into buf; no more
908 * than size characters will be written
909 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100910int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200911{
Janos Follath865b3eb2019-12-16 11:46:15 +0000912 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200913 size_t i, n, nr;
914 char *p;
915
916 p = buf;
917 n = size;
918
Gilles Peskine449bd832023-01-11 14:50:10 +0100919 nr = (serial->len <= 32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200920 ? serial->len : 28;
921
Gilles Peskine449bd832023-01-11 14:50:10 +0100922 for (i = 0; i < nr; i++) {
923 if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200924 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200926
Gilles Peskine449bd832023-01-11 14:50:10 +0100927 ret = mbedtls_snprintf(p, n, "%02X%s",
928 serial->p[i], (i < nr - 1) ? ":" : "");
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200929 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200930 }
931
Gilles Peskine449bd832023-01-11 14:50:10 +0100932 if (nr != serial->len) {
933 ret = mbedtls_snprintf(p, n, "....");
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200934 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200935 }
936
Gilles Peskine449bd832023-01-11 14:50:10 +0100937 return (int) (size - n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200938}
939
Hanno Becker612a2f12020-10-09 09:19:39 +0100940#if !defined(MBEDTLS_X509_REMOVE_INFO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200941/*
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200942 * Helper for writing signature algorithms
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100943 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100944int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
945 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
946 const void *sig_opts)
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100947{
Janos Follath865b3eb2019-12-16 11:46:15 +0000948 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100949 char *p = buf;
950 size_t n = size;
951 const char *desc = NULL;
952
Gilles Peskine449bd832023-01-11 14:50:10 +0100953 ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
954 if (ret != 0) {
955 ret = mbedtls_snprintf(p, n, "???");
956 } else {
957 ret = mbedtls_snprintf(p, n, "%s", desc);
958 }
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200959 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100962 if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 const mbedtls_pk_rsassa_pss_options *pss_opts;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100966
Gilles Peskine449bd832023-01-11 14:50:10 +0100967 const char *name = md_type_to_string(md_alg);
968 const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100969
Gilles Peskine449bd832023-01-11 14:50:10 +0100970 ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
971 name ? name : "???",
972 mgf_name ? mgf_name : "???",
973 (unsigned int) pss_opts->expected_salt_len);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200974 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100975 }
976#else
977 ((void) pk_alg);
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200978 ((void) md_alg);
979 ((void) sig_opts);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100981
Gilles Peskine449bd832023-01-11 14:50:10 +0100982 return (int) (size - n);
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100983}
Hanno Becker612a2f12020-10-09 09:19:39 +0100984#endif /* MBEDTLS_X509_REMOVE_INFO */
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100985
986/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200987 * Helper for writing "RSA key size", "EC key size", etc
988 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100989int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200990{
991 char *p = buf;
Manuel Pégourié-Gonnardfb317c52015-06-18 16:25:56 +0200992 size_t n = buf_size;
Janos Follath865b3eb2019-12-16 11:46:15 +0000993 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200994
Gilles Peskine449bd832023-01-11 14:50:10 +0100995 ret = mbedtls_snprintf(p, n, "%s key size", name);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200996 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200997
Gilles Peskine449bd832023-01-11 14:50:10 +0100998 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200999}
1000
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +02001001#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +02001002/*
1003 * Set the time structure to the current time.
1004 * Return 0 on success, non-zero on failure.
1005 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001006static int x509_get_current_time(mbedtls_x509_time *now)
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001007{
Nicholas Wilson512b4ee2017-12-05 12:07:33 +00001008 struct tm *lt, tm_buf;
SimonBd5800b72016-04-26 07:43:27 +01001009 mbedtls_time_t tt;
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +02001010 int ret = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001011
Gilles Peskine449bd832023-01-11 14:50:10 +01001012 tt = mbedtls_time(NULL);
1013 lt = mbedtls_platform_gmtime_r(&tt, &tm_buf);
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +02001014
Gilles Peskine449bd832023-01-11 14:50:10 +01001015 if (lt == NULL) {
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +02001016 ret = -1;
Gilles Peskine449bd832023-01-11 14:50:10 +01001017 } else {
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +02001018 now->year = lt->tm_year + 1900;
1019 now->mon = lt->tm_mon + 1;
1020 now->day = lt->tm_mday;
1021 now->hour = lt->tm_hour;
1022 now->min = lt->tm_min;
1023 now->sec = lt->tm_sec;
1024 }
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +02001025
Gilles Peskine449bd832023-01-11 14:50:10 +01001026 return ret;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001027}
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001028
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001029/*
1030 * Return 0 if before <= after, 1 otherwise
1031 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001032static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after)
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001033{
Gilles Peskine449bd832023-01-11 14:50:10 +01001034 if (before->year > after->year) {
1035 return 1;
1036 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001037
Gilles Peskine449bd832023-01-11 14:50:10 +01001038 if (before->year == after->year &&
1039 before->mon > after->mon) {
1040 return 1;
1041 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001042
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 if (before->year == after->year &&
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001044 before->mon == after->mon &&
Gilles Peskine449bd832023-01-11 14:50:10 +01001045 before->day > after->day) {
1046 return 1;
1047 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001048
Gilles Peskine449bd832023-01-11 14:50:10 +01001049 if (before->year == after->year &&
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001050 before->mon == after->mon &&
1051 before->day == after->day &&
Gilles Peskine449bd832023-01-11 14:50:10 +01001052 before->hour > after->hour) {
1053 return 1;
1054 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 if (before->year == after->year &&
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001057 before->mon == after->mon &&
1058 before->day == after->day &&
1059 before->hour == after->hour &&
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 before->min > after->min) {
1061 return 1;
1062 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001063
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 if (before->year == after->year &&
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001065 before->mon == after->mon &&
1066 before->day == after->day &&
1067 before->hour == after->hour &&
1068 before->min == after->min &&
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 before->sec > after->sec) {
1070 return 1;
1071 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001072
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001074}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001075
Gilles Peskine449bd832023-01-11 14:50:10 +01001076int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001077{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 mbedtls_x509_time now;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001079
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 if (x509_get_current_time(&now) != 0) {
1081 return 1;
1082 }
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001083
Gilles Peskine449bd832023-01-11 14:50:10 +01001084 return x509_check_time(&now, to);
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001085}
1086
Gilles Peskine449bd832023-01-11 14:50:10 +01001087int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001088{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 mbedtls_x509_time now;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 if (x509_get_current_time(&now) != 0) {
1092 return 1;
1093 }
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001094
Gilles Peskine449bd832023-01-11 14:50:10 +01001095 return x509_check_time(from, &now);
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001096}
1097
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +02001098#else /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001099
Gilles Peskine449bd832023-01-11 14:50:10 +01001100int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001101{
1102 ((void) to);
Gilles Peskine449bd832023-01-11 14:50:10 +01001103 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001104}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001107{
1108 ((void) from);
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 return 0;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001110}
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +02001111#endif /* MBEDTLS_HAVE_TIME_DATE */
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001112
1113/* Common functions for parsing CRT and CSR. */
1114#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
1115/*
1116 * OtherName ::= SEQUENCE {
1117 * type-id OBJECT IDENTIFIER,
1118 * value [0] EXPLICIT ANY DEFINED BY type-id }
1119 *
1120 * HardwareModuleName ::= SEQUENCE {
1121 * hwType OBJECT IDENTIFIER,
1122 * hwSerialNum OCTET STRING }
1123 *
1124 * NOTE: we currently only parse and use otherName of type HwModuleName,
1125 * as defined in RFC 4108.
1126 */
1127static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
1128 mbedtls_x509_san_other_name *other_name)
1129{
1130 int ret = 0;
1131 size_t len;
1132 unsigned char *p = subject_alt_name->p;
1133 const unsigned char *end = p + subject_alt_name->len;
1134 mbedtls_x509_buf cur_oid;
1135
1136 if ((subject_alt_name->tag &
1137 (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
1138 (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
1139 /*
1140 * The given subject alternative name is not of type "othername".
1141 */
1142 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1143 }
1144
1145 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1146 MBEDTLS_ASN1_OID)) != 0) {
1147 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1148 }
1149
1150 cur_oid.tag = MBEDTLS_ASN1_OID;
1151 cur_oid.p = p;
1152 cur_oid.len = len;
1153
1154 /*
1155 * Only HwModuleName is currently supported.
1156 */
1157 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
1158 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1159 }
1160
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001161 p += len;
1162 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1163 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
1164 0) {
1165 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1166 }
1167
Hanno Beckerdae916b2019-09-13 14:21:13 +01001168 if (end != p + len) {
1169 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1170 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1171 }
1172
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001173 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1174 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1175 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1176 }
1177
Hanno Beckerdae916b2019-09-13 14:21:13 +01001178 if (end != p + len) {
1179 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1180 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1181 }
1182
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001183 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
1184 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1185 }
1186
1187 other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
1188 other_name->value.hardware_module_name.oid.p = p;
1189 other_name->value.hardware_module_name.oid.len = len;
1190
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001191 p += len;
1192 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1193 MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1194 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1195 }
1196
1197 other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
1198 other_name->value.hardware_module_name.val.p = p;
1199 other_name->value.hardware_module_name.val.len = len;
1200 p += len;
1201 if (p != end) {
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001202 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1203 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1204 }
1205 return 0;
1206}
1207
Przemek Stekiel21903ec2023-02-21 08:32:37 +01001208/* Check mbedtls_x509_get_subject_alt_name for detailed description.
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001209 *
Przemek Stekiel21903ec2023-02-21 08:32:37 +01001210 * In some cases while parsing subject alternative names the sequence tag is optional
1211 * (e.g. CertSerialNumber). This function is designed to handle such case.
Przemek Stekiel725688b2023-04-04 22:49:44 +02001212 */
Przemek Stekiel21903ec2023-02-21 08:32:37 +01001213int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
1214 const unsigned char *end,
1215 mbedtls_x509_sequence *subject_alt_name)
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001216{
1217 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Przemek Stekiel21903ec2023-02-21 08:32:37 +01001218 size_t tag_len;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001219 mbedtls_asn1_sequence *cur = subject_alt_name;
1220
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001221 while (*p < end) {
Andrzej Kurek154a6052023-04-30 14:11:49 -04001222 mbedtls_x509_subject_alternative_name tmp_san_name;
Hanno Beckerae8f8c42019-09-13 12:24:56 +01001223 mbedtls_x509_buf tmp_san_buf;
Andrzej Kurek154a6052023-04-30 14:11:49 -04001224 memset(&tmp_san_name, 0, sizeof(tmp_san_name));
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001225
Hanno Beckerae8f8c42019-09-13 12:24:56 +01001226 tmp_san_buf.tag = **p;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001227 (*p)++;
Hanno Beckerae8f8c42019-09-13 12:24:56 +01001228
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001229 if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
1230 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1231 }
1232
Hanno Beckerae8f8c42019-09-13 12:24:56 +01001233 tmp_san_buf.p = *p;
1234 tmp_san_buf.len = tag_len;
1235
1236 if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001237 MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
1238 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1239 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
1240 }
1241
1242 /*
Andrzej Kurek154a6052023-04-30 14:11:49 -04001243 * Check that the SAN is structured correctly by parsing it.
1244 * The SAN structure is discarded afterwards.
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001245 */
Andrzej Kurek154a6052023-04-30 14:11:49 -04001246 ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001247 /*
1248 * In case the extension is malformed, return an error,
1249 * and clear the allocated sequences.
1250 */
1251 if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1252 mbedtls_asn1_sequence_free(subject_alt_name->next);
1253 subject_alt_name->next = NULL;
1254 return ret;
1255 }
1256
Andrzej Kurek154a6052023-04-30 14:11:49 -04001257 mbedtls_x509_free_subject_alt_name(&tmp_san_name);
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001258 /* Allocate and assign next pointer */
1259 if (cur->buf.p != NULL) {
1260 if (cur->next != NULL) {
1261 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1262 }
1263
1264 cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
1265
1266 if (cur->next == NULL) {
1267 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1268 MBEDTLS_ERR_ASN1_ALLOC_FAILED);
1269 }
1270
1271 cur = cur->next;
1272 }
1273
Hanno Beckerae8f8c42019-09-13 12:24:56 +01001274 cur->buf = tmp_san_buf;
1275 *p += tmp_san_buf.len;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001276 }
1277
1278 /* Set final sequence entry's next pointer to NULL */
1279 cur->next = NULL;
1280
1281 if (*p != end) {
1282 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1283 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1284 }
1285
1286 return 0;
1287}
1288
Przemek Stekiel21903ec2023-02-21 08:32:37 +01001289/*
1290 * SubjectAltName ::= GeneralNames
1291 *
1292 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1293 *
1294 * GeneralName ::= CHOICE {
1295 * otherName [0] OtherName,
1296 * rfc822Name [1] IA5String,
1297 * dNSName [2] IA5String,
1298 * x400Address [3] ORAddress,
1299 * directoryName [4] Name,
1300 * ediPartyName [5] EDIPartyName,
1301 * uniformResourceIdentifier [6] IA5String,
1302 * iPAddress [7] OCTET STRING,
1303 * registeredID [8] OBJECT IDENTIFIER }
1304 *
1305 * OtherName ::= SEQUENCE {
1306 * type-id OBJECT IDENTIFIER,
1307 * value [0] EXPLICIT ANY DEFINED BY type-id }
1308 *
1309 * EDIPartyName ::= SEQUENCE {
1310 * nameAssigner [0] DirectoryString OPTIONAL,
1311 * partyName [1] DirectoryString }
1312 *
1313 * We list all types, but use the following GeneralName types from RFC 5280:
1314 * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
1315 * of type "otherName", as defined in RFC 4108.
1316 */
1317int mbedtls_x509_get_subject_alt_name(unsigned char **p,
1318 const unsigned char *end,
1319 mbedtls_x509_sequence *subject_alt_name)
1320{
1321 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1322 size_t len;
1323
1324 /* Get main sequence tag */
1325 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
1326 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1327 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1328 }
1329
1330 if (*p + len != end) {
1331 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1332 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1333 }
1334
1335 return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
1336}
1337
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001338int mbedtls_x509_get_ns_cert_type(unsigned char **p,
1339 const unsigned char *end,
1340 unsigned char *ns_cert_type)
1341{
1342 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1343 mbedtls_x509_bitstring bs = { 0, 0, NULL };
1344
1345 if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1346 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1347 }
1348
Przemek Stekiel32e20912023-01-25 14:26:15 +01001349 /* A bitstring with no flags set is still technically valid, as it will mean
1350 that the certificate has no designated purpose at the time of creation. */
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001351 if (bs.len == 0) {
1352 *ns_cert_type = 0;
1353 return 0;
1354 }
1355
1356 if (bs.len != 1) {
1357 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1358 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
1359 }
1360
1361 /* Get actual bitstring */
1362 *ns_cert_type = *bs.p;
1363 return 0;
1364}
1365
1366int mbedtls_x509_get_key_usage(unsigned char **p,
1367 const unsigned char *end,
1368 unsigned int *key_usage)
1369{
1370 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1371 size_t i;
1372 mbedtls_x509_bitstring bs = { 0, 0, NULL };
1373
1374 if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1375 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1376 }
1377
Przemek Stekiel32e20912023-01-25 14:26:15 +01001378 /* A bitstring with no flags set is still technically valid, as it will mean
1379 that the certificate has no designated purpose at the time of creation. */
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001380 if (bs.len == 0) {
1381 *key_usage = 0;
1382 return 0;
1383 }
1384
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001385 /* Get actual bitstring */
1386 *key_usage = 0;
1387 for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
1388 *key_usage |= (unsigned int) bs.p[i] << (8*i);
1389 }
1390
1391 return 0;
1392}
1393
1394int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
1395 mbedtls_x509_subject_alternative_name *san)
1396{
1397 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1398 switch (san_buf->tag &
1399 (MBEDTLS_ASN1_TAG_CLASS_MASK |
1400 MBEDTLS_ASN1_TAG_VALUE_MASK)) {
1401 /*
1402 * otherName
1403 */
1404 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
1405 {
1406 mbedtls_x509_san_other_name other_name;
1407
1408 ret = x509_get_other_name(san_buf, &other_name);
1409 if (ret != 0) {
1410 return ret;
1411 }
1412
1413 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1414 san->type = MBEDTLS_X509_SAN_OTHER_NAME;
1415 memcpy(&san->san.other_name,
1416 &other_name, sizeof(other_name));
1417
1418 }
1419 break;
Andrzej Kurek7a05fab2023-02-13 10:03:07 -05001420 /*
1421 * uniformResourceIdentifier
1422 */
1423 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
1424 {
1425 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1426 san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001427
Andrzej Kurek7a05fab2023-02-13 10:03:07 -05001428 memcpy(&san->san.unstructured_name,
1429 san_buf, sizeof(*san_buf));
1430
1431 }
1432 break;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001433 /*
1434 * dNSName
1435 */
1436 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
1437 {
1438 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1439 san->type = MBEDTLS_X509_SAN_DNS_NAME;
1440
1441 memcpy(&san->san.unstructured_name,
1442 san_buf, sizeof(*san_buf));
Przemek Stekielecee12f2023-02-09 14:43:49 +01001443 }
1444 break;
Przemek Stekiel0ab5b932023-05-29 16:30:50 +02001445 /*
1446 * IP address
1447 */
1448 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):
1449 {
1450 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1451 san->type = MBEDTLS_X509_SAN_IP_ADDRESS;
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001452 // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1453 if (san_buf->len == 4 || san_buf->len == 16) {
1454 memcpy(&san->san.unstructured_name,
1455 san_buf, sizeof(*san_buf));
1456 } else {
1457 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1458 }
Przemek Stekiel0ab5b932023-05-29 16:30:50 +02001459 }
1460 break;
Przemek Stekielecee12f2023-02-09 14:43:49 +01001461 /*
Andrzej Kurek154a6052023-04-30 14:11:49 -04001462 * rfc822Name
Przemek Stekielecee12f2023-02-09 14:43:49 +01001463 */
1464 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
1465 {
1466 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1467 san->type = MBEDTLS_X509_SAN_RFC822_NAME;
1468 memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001469 }
1470 break;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001471 /*
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001472 * directoryName
1473 */
1474 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):
1475 {
1476 size_t name_len;
1477 unsigned char *p = san_buf->p;
1478 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1479 san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
1480
1481 ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,
1482 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1483
1484 if (ret != 0) {
Andrzej Kurekbf8ccd82023-02-13 07:13:30 -05001485 return ret;
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001486 }
1487
1488 if ((ret = mbedtls_x509_get_name(&p, p + name_len,
1489 &san->san.directory_name)) != 0) {
Andrzej Kurekbf8ccd82023-02-13 07:13:30 -05001490 return ret;
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001491 }
1492 }
1493 break;
1494 /*
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001495 * Type not supported
1496 */
1497 default:
1498 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1499 }
1500 return 0;
1501}
1502
Andrzej Kurekd40c2b62023-02-13 07:01:59 -05001503void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)
1504{
1505 if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
1506 mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);
1507 }
1508}
1509
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001510#if !defined(MBEDTLS_X509_REMOVE_INFO)
1511int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
1512 const mbedtls_x509_sequence
1513 *subject_alt_name,
1514 const char *prefix)
1515{
1516 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1517 size_t i;
1518 size_t n = *size;
1519 char *p = *buf;
1520 const mbedtls_x509_sequence *cur = subject_alt_name;
1521 mbedtls_x509_subject_alternative_name san;
1522 int parse_ret;
1523
1524 while (cur != NULL) {
1525 memset(&san, 0, sizeof(san));
1526 parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
1527 if (parse_ret != 0) {
1528 if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1529 ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
1530 MBEDTLS_X509_SAFE_SNPRINTF;
1531 } else {
1532 ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix);
1533 MBEDTLS_X509_SAFE_SNPRINTF;
1534 }
1535 cur = cur->next;
1536 continue;
1537 }
1538
1539 switch (san.type) {
1540 /*
1541 * otherName
1542 */
1543 case MBEDTLS_X509_SAN_OTHER_NAME:
1544 {
1545 mbedtls_x509_san_other_name *other_name = &san.san.other_name;
1546
1547 ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix);
1548 MBEDTLS_X509_SAFE_SNPRINTF;
1549
1550 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
1551 &other_name->value.hardware_module_name.oid) != 0) {
1552 ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix);
1553 MBEDTLS_X509_SAFE_SNPRINTF;
1554 ret =
1555 mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix);
1556 MBEDTLS_X509_SAFE_SNPRINTF;
1557
1558 ret = mbedtls_oid_get_numeric_string(p,
1559 n,
1560 &other_name->value.hardware_module_name.oid);
1561 MBEDTLS_X509_SAFE_SNPRINTF;
1562
1563 ret =
1564 mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix);
1565 MBEDTLS_X509_SAFE_SNPRINTF;
1566
1567 for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
1568 ret = mbedtls_snprintf(p,
1569 n,
1570 "%02X",
1571 other_name->value.hardware_module_name.val.p[i]);
1572 MBEDTLS_X509_SAFE_SNPRINTF;
1573 }
1574 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
1575 }
1576 break;
Andrzej Kurek7a05fab2023-02-13 10:03:07 -05001577 /*
1578 * uniformResourceIdentifier
1579 */
1580 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
1581 {
1582 ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix);
1583 MBEDTLS_X509_SAFE_SNPRINTF;
1584 if (san.san.unstructured_name.len >= n) {
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001585 if (n > 0) {
1586 *p = '\0';
1587 }
Andrzej Kurek7a05fab2023-02-13 10:03:07 -05001588 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1589 }
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001590
Andrzej Kurek7a05fab2023-02-13 10:03:07 -05001591 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1592 p += san.san.unstructured_name.len;
1593 n -= san.san.unstructured_name.len;
1594 }
1595 break;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001596 /*
1597 * dNSName
Przemek Stekiel5b9e4162023-02-15 12:56:37 +01001598 * RFC822 Name
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001599 */
1600 case MBEDTLS_X509_SAN_DNS_NAME:
Przemek Stekiel5b9e4162023-02-15 12:56:37 +01001601 case MBEDTLS_X509_SAN_RFC822_NAME:
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001602 {
Przemek Stekiel82d250d2023-02-15 15:00:50 +01001603 const char *dns_name = "dNSName";
1604 const char *rfc822_name = "rfc822Name";
Przemek Stekiel5b9e4162023-02-15 12:56:37 +01001605
Przemek Stekiel82d250d2023-02-15 15:00:50 +01001606 ret = mbedtls_snprintf(p, n,
1607 "\n%s %s : ",
1608 prefix,
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001609 san.type ==
1610 MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001611 MBEDTLS_X509_SAFE_SNPRINTF;
1612 if (san.san.unstructured_name.len >= n) {
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001613 if (n > 0) {
1614 *p = '\0';
1615 }
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001616 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1617 }
1618
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001619 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1620 p += san.san.unstructured_name.len;
1621 n -= san.san.unstructured_name.len;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001622 }
1623 break;
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001624 /*
1625 * iPAddress
1626 */
1627 case MBEDTLS_X509_SAN_IP_ADDRESS:
1628 {
1629 ret = mbedtls_snprintf(p, n, "\n%s %s : ",
1630 prefix, "iPAddress");
1631 MBEDTLS_X509_SAFE_SNPRINTF;
1632 if (san.san.unstructured_name.len >= n) {
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001633 if (n > 0) {
1634 *p = '\0';
1635 }
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001636 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1637 }
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001638
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001639 unsigned char *ip = san.san.unstructured_name.p;
1640 // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1641 if (san.san.unstructured_name.len == 4) {
Przemek Stekiel4d3fc212023-06-06 11:40:32 +02001642 ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1643 MBEDTLS_X509_SAFE_SNPRINTF;
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001644 } else if (san.san.unstructured_name.len == 16) {
Przemek Stekiel4d3fc212023-06-06 11:40:32 +02001645 ret = mbedtls_snprintf(p, n,
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001646 "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X",
1647 ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
Przemek Stekiel4d3fc212023-06-06 11:40:32 +02001648 ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001649 ip[14], ip[15]);
Przemek Stekiel4d3fc212023-06-06 11:40:32 +02001650 MBEDTLS_X509_SAFE_SNPRINTF;
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001651 } else {
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001652 if (n > 0) {
1653 *p = '\0';
1654 }
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001655 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1656 }
Przemek Stekiel093c97d2023-06-02 10:11:32 +02001657 }
1658 break;
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001659 /*
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001660 * directoryName
1661 */
1662 case MBEDTLS_X509_SAN_DIRECTORY_NAME:
1663 {
1664 ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix);
Andrzej Kurek5f0c6e82023-02-27 16:03:41 -05001665 if (ret < 0 || (size_t) ret >= n) {
1666 mbedtls_x509_free_subject_alt_name(&san);
1667 }
1668
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001669 MBEDTLS_X509_SAFE_SNPRINTF;
1670 ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);
Andrzej Kurekd40c2b62023-02-13 07:01:59 -05001671
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001672 if (ret < 0) {
Andrzej Kurek5f0c6e82023-02-27 16:03:41 -05001673 mbedtls_x509_free_subject_alt_name(&san);
Przemek Stekiel01cb6eb2023-06-05 16:38:13 +02001674 if (n > 0) {
1675 *p = '\0';
1676 }
Andrzej Kureke12b01d2023-01-10 06:47:38 -05001677 return ret;
1678 }
1679
1680 p += ret;
1681 n -= ret;
1682 }
1683 break;
1684 /*
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001685 * Type not supported, skip item.
1686 */
1687 default:
1688 ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
1689 MBEDTLS_X509_SAFE_SNPRINTF;
1690 break;
1691 }
1692
Andrzej Kurekd40c2b62023-02-13 07:01:59 -05001693 /* So far memory is freed only in the case of directoryName
Andrzej Kurek5f0c6e82023-02-27 16:03:41 -05001694 * parsing succeeding, as mbedtls_x509_get_name allocates memory. */
Andrzej Kurekd40c2b62023-02-13 07:01:59 -05001695 mbedtls_x509_free_subject_alt_name(&san);
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001696 cur = cur->next;
1697 }
1698
1699 *p = '\0';
1700
1701 *size = n;
1702 *buf = p;
1703
1704 return 0;
1705}
1706
Demi Marie Obenour690b8c92022-12-04 04:24:22 -05001707#define PRINT_ITEM(i) \
1708 do { \
1709 ret = mbedtls_snprintf(p, n, "%s" i, sep); \
1710 MBEDTLS_X509_SAFE_SNPRINTF; \
1711 sep = ", "; \
1712 } while (0)
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001713
Demi Marie Obenour690b8c92022-12-04 04:24:22 -05001714#define CERT_TYPE(type, name) \
1715 do { \
1716 if (ns_cert_type & (type)) { \
1717 PRINT_ITEM(name); \
1718 } \
1719 } while (0)
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001720
1721int mbedtls_x509_info_cert_type(char **buf, size_t *size,
1722 unsigned char ns_cert_type)
1723{
1724 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1725 size_t n = *size;
1726 char *p = *buf;
1727 const char *sep = "";
1728
1729 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client");
1730 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server");
1731 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email");
1732 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing");
1733 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved");
1734 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA");
1735 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA");
1736 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA");
1737
1738 *size = n;
1739 *buf = p;
1740
1741 return 0;
1742}
1743
Demi Marie Obenour690b8c92022-12-04 04:24:22 -05001744#define KEY_USAGE(code, name) \
1745 do { \
1746 if ((key_usage) & (code)) { \
1747 PRINT_ITEM(name); \
1748 } \
1749 } while (0)
Przemek Stekielcf6ff0f2023-01-17 10:26:40 +01001750
1751int mbedtls_x509_info_key_usage(char **buf, size_t *size,
1752 unsigned int key_usage)
1753{
1754 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1755 size_t n = *size;
1756 char *p = *buf;
1757 const char *sep = "";
1758
1759 KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature");
1760 KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation");
1761 KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment");
1762 KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment");
1763 KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement");
1764 KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign");
1765 KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign");
1766 KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only");
1767 KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only");
1768
1769 *size = n;
1770 *buf = p;
1771
1772 return 0;
1773}
1774#endif /* MBEDTLS_X509_REMOVE_INFO */
1775#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776#endif /* MBEDTLS_X509_USE_C */