RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * X.509 common functions for parsing and verification
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kevman 0:38ceb79fef03 5 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 6 *
kevman 0:38ceb79fef03 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kevman 0:38ceb79fef03 8 * not use this file except in compliance with the License.
kevman 0:38ceb79fef03 9 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 12 *
kevman 0:38ceb79fef03 13 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kevman 0:38ceb79fef03 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 16 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 17 * limitations under the License.
kevman 0:38ceb79fef03 18 *
kevman 0:38ceb79fef03 19 * This file is part of mbed TLS (https://tls.mbed.org)
kevman 0:38ceb79fef03 20 */
kevman 0:38ceb79fef03 21 /*
kevman 0:38ceb79fef03 22 * The ITU-T X.509 standard defines a certificate format for PKI.
kevman 0:38ceb79fef03 23 *
kevman 0:38ceb79fef03 24 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
kevman 0:38ceb79fef03 25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
kevman 0:38ceb79fef03 26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
kevman 0:38ceb79fef03 27 *
kevman 0:38ceb79fef03 28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
kevman 0:38ceb79fef03 29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
kevman 0:38ceb79fef03 30 */
kevman 0:38ceb79fef03 31
kevman 0:38ceb79fef03 32 #if !defined(MBEDTLS_CONFIG_FILE)
kevman 0:38ceb79fef03 33 #include "mbedtls/config.h"
kevman 0:38ceb79fef03 34 #else
kevman 0:38ceb79fef03 35 #include MBEDTLS_CONFIG_FILE
kevman 0:38ceb79fef03 36 #endif
kevman 0:38ceb79fef03 37
kevman 0:38ceb79fef03 38 #if defined(MBEDTLS_X509_USE_C)
kevman 0:38ceb79fef03 39
kevman 0:38ceb79fef03 40 #include "mbedtls/x509.h"
kevman 0:38ceb79fef03 41 #include "mbedtls/asn1.h"
kevman 0:38ceb79fef03 42 #include "mbedtls/oid.h"
kevman 0:38ceb79fef03 43
kevman 0:38ceb79fef03 44 #include <stdio.h>
kevman 0:38ceb79fef03 45 #include <string.h>
kevman 0:38ceb79fef03 46
kevman 0:38ceb79fef03 47 #if defined(MBEDTLS_PEM_PARSE_C)
kevman 0:38ceb79fef03 48 #include "mbedtls/pem.h"
kevman 0:38ceb79fef03 49 #endif
kevman 0:38ceb79fef03 50
kevman 0:38ceb79fef03 51 #if defined(MBEDTLS_PLATFORM_C)
kevman 0:38ceb79fef03 52 #include "mbedtls/platform.h"
kevman 0:38ceb79fef03 53 #else
kevman 0:38ceb79fef03 54 #include <stdio.h>
kevman 0:38ceb79fef03 55 #include <stdlib.h>
kevman 0:38ceb79fef03 56 #define mbedtls_free free
kevman 0:38ceb79fef03 57 #define mbedtls_calloc calloc
kevman 0:38ceb79fef03 58 #define mbedtls_printf printf
kevman 0:38ceb79fef03 59 #define mbedtls_snprintf snprintf
kevman 0:38ceb79fef03 60 #endif
kevman 0:38ceb79fef03 61
kevman 0:38ceb79fef03 62 #if defined(MBEDTLS_HAVE_TIME)
kevman 0:38ceb79fef03 63 #include "mbedtls/platform_time.h"
kevman 0:38ceb79fef03 64 #endif
kevman 0:38ceb79fef03 65 #if defined(MBEDTLS_HAVE_TIME_DATE)
kevman 0:38ceb79fef03 66 #include "mbedtls/platform_util.h"
kevman 0:38ceb79fef03 67 #include <time.h>
kevman 0:38ceb79fef03 68 #endif
kevman 0:38ceb79fef03 69
kevman 0:38ceb79fef03 70 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
kevman 0:38ceb79fef03 71 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
kevman 0:38ceb79fef03 72
kevman 0:38ceb79fef03 73 /*
kevman 0:38ceb79fef03 74 * CertificateSerialNumber ::= INTEGER
kevman 0:38ceb79fef03 75 */
kevman 0:38ceb79fef03 76 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 77 mbedtls_x509_buf *serial )
kevman 0:38ceb79fef03 78 {
kevman 0:38ceb79fef03 79 int ret;
kevman 0:38ceb79fef03 80
kevman 0:38ceb79fef03 81 if( ( end - *p ) < 1 )
kevman 0:38ceb79fef03 82 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
kevman 0:38ceb79fef03 83 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 84
kevman 0:38ceb79fef03 85 if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
kevman 0:38ceb79fef03 86 **p != MBEDTLS_ASN1_INTEGER )
kevman 0:38ceb79fef03 87 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
kevman 0:38ceb79fef03 88 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kevman 0:38ceb79fef03 89
kevman 0:38ceb79fef03 90 serial->tag = *(*p)++;
kevman 0:38ceb79fef03 91
kevman 0:38ceb79fef03 92 if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
kevman 0:38ceb79fef03 93 return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
kevman 0:38ceb79fef03 94
kevman 0:38ceb79fef03 95 serial->p = *p;
kevman 0:38ceb79fef03 96 *p += serial->len;
kevman 0:38ceb79fef03 97
kevman 0:38ceb79fef03 98 return( 0 );
kevman 0:38ceb79fef03 99 }
kevman 0:38ceb79fef03 100
kevman 0:38ceb79fef03 101 /* Get an algorithm identifier without parameters (eg for signatures)
kevman 0:38ceb79fef03 102 *
kevman 0:38ceb79fef03 103 * AlgorithmIdentifier ::= SEQUENCE {
kevman 0:38ceb79fef03 104 * algorithm OBJECT IDENTIFIER,
kevman 0:38ceb79fef03 105 * parameters ANY DEFINED BY algorithm OPTIONAL }
kevman 0:38ceb79fef03 106 */
kevman 0:38ceb79fef03 107 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 108 mbedtls_x509_buf *alg )
kevman 0:38ceb79fef03 109 {
kevman 0:38ceb79fef03 110 int ret;
kevman 0:38ceb79fef03 111
kevman 0:38ceb79fef03 112 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
kevman 0:38ceb79fef03 113 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 114
kevman 0:38ceb79fef03 115 return( 0 );
kevman 0:38ceb79fef03 116 }
kevman 0:38ceb79fef03 117
kevman 0:38ceb79fef03 118 /*
kevman 0:38ceb79fef03 119 * Parse an algorithm identifier with (optional) paramaters
kevman 0:38ceb79fef03 120 */
kevman 0:38ceb79fef03 121 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 122 mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
kevman 0:38ceb79fef03 123 {
kevman 0:38ceb79fef03 124 int ret;
kevman 0:38ceb79fef03 125
kevman 0:38ceb79fef03 126 if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
kevman 0:38ceb79fef03 127 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 128
kevman 0:38ceb79fef03 129 return( 0 );
kevman 0:38ceb79fef03 130 }
kevman 0:38ceb79fef03 131
kevman 0:38ceb79fef03 132 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
kevman 0:38ceb79fef03 133 /*
kevman 0:38ceb79fef03 134 * HashAlgorithm ::= AlgorithmIdentifier
kevman 0:38ceb79fef03 135 *
kevman 0:38ceb79fef03 136 * AlgorithmIdentifier ::= SEQUENCE {
kevman 0:38ceb79fef03 137 * algorithm OBJECT IDENTIFIER,
kevman 0:38ceb79fef03 138 * parameters ANY DEFINED BY algorithm OPTIONAL }
kevman 0:38ceb79fef03 139 *
kevman 0:38ceb79fef03 140 * For HashAlgorithm, parameters MUST be NULL or absent.
kevman 0:38ceb79fef03 141 */
kevman 0:38ceb79fef03 142 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
kevman 0:38ceb79fef03 143 {
kevman 0:38ceb79fef03 144 int ret;
kevman 0:38ceb79fef03 145 unsigned char *p;
kevman 0:38ceb79fef03 146 const unsigned char *end;
kevman 0:38ceb79fef03 147 mbedtls_x509_buf md_oid;
kevman 0:38ceb79fef03 148 size_t len;
kevman 0:38ceb79fef03 149
kevman 0:38ceb79fef03 150 /* Make sure we got a SEQUENCE and setup bounds */
kevman 0:38ceb79fef03 151 if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
kevman 0:38ceb79fef03 152 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 153 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kevman 0:38ceb79fef03 154
kevman 0:38ceb79fef03 155 p = (unsigned char *) alg->p;
kevman 0:38ceb79fef03 156 end = p + alg->len;
kevman 0:38ceb79fef03 157
kevman 0:38ceb79fef03 158 if( p >= end )
kevman 0:38ceb79fef03 159 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 160 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 161
kevman 0:38ceb79fef03 162 /* Parse md_oid */
kevman 0:38ceb79fef03 163 md_oid.tag = *p;
kevman 0:38ceb79fef03 164
kevman 0:38ceb79fef03 165 if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
kevman 0:38ceb79fef03 166 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 167
kevman 0:38ceb79fef03 168 md_oid.p = p;
kevman 0:38ceb79fef03 169 p += md_oid.len;
kevman 0:38ceb79fef03 170
kevman 0:38ceb79fef03 171 /* Get md_alg from md_oid */
kevman 0:38ceb79fef03 172 if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
kevman 0:38ceb79fef03 173 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 174
kevman 0:38ceb79fef03 175 /* Make sure params is absent of NULL */
kevman 0:38ceb79fef03 176 if( p == end )
kevman 0:38ceb79fef03 177 return( 0 );
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
kevman 0:38ceb79fef03 180 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 181
kevman 0:38ceb79fef03 182 if( p != end )
kevman 0:38ceb79fef03 183 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 184 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 return( 0 );
kevman 0:38ceb79fef03 187 }
kevman 0:38ceb79fef03 188
kevman 0:38ceb79fef03 189 /*
kevman 0:38ceb79fef03 190 * RSASSA-PSS-params ::= SEQUENCE {
kevman 0:38ceb79fef03 191 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
kevman 0:38ceb79fef03 192 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
kevman 0:38ceb79fef03 193 * saltLength [2] INTEGER DEFAULT 20,
kevman 0:38ceb79fef03 194 * trailerField [3] INTEGER DEFAULT 1 }
kevman 0:38ceb79fef03 195 * -- Note that the tags in this Sequence are explicit.
kevman 0:38ceb79fef03 196 *
kevman 0:38ceb79fef03 197 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
kevman 0:38ceb79fef03 198 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
kevman 0:38ceb79fef03 199 * option. Enfore this at parsing time.
kevman 0:38ceb79fef03 200 */
kevman 0:38ceb79fef03 201 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
kevman 0:38ceb79fef03 202 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
kevman 0:38ceb79fef03 203 int *salt_len )
kevman 0:38ceb79fef03 204 {
kevman 0:38ceb79fef03 205 int ret;
kevman 0:38ceb79fef03 206 unsigned char *p;
kevman 0:38ceb79fef03 207 const unsigned char *end, *end2;
kevman 0:38ceb79fef03 208 size_t len;
kevman 0:38ceb79fef03 209 mbedtls_x509_buf alg_id, alg_params;
kevman 0:38ceb79fef03 210
kevman 0:38ceb79fef03 211 /* First set everything to defaults */
kevman 0:38ceb79fef03 212 *md_alg = MBEDTLS_MD_SHA1;
kevman 0:38ceb79fef03 213 *mgf_md = MBEDTLS_MD_SHA1;
kevman 0:38ceb79fef03 214 *salt_len = 20;
kevman 0:38ceb79fef03 215
kevman 0:38ceb79fef03 216 /* Make sure params is a SEQUENCE and setup bounds */
kevman 0:38ceb79fef03 217 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
kevman 0:38ceb79fef03 218 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 219 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kevman 0:38ceb79fef03 220
kevman 0:38ceb79fef03 221 p = (unsigned char *) params->p;
kevman 0:38ceb79fef03 222 end = p + params->len;
kevman 0:38ceb79fef03 223
kevman 0:38ceb79fef03 224 if( p == end )
kevman 0:38ceb79fef03 225 return( 0 );
kevman 0:38ceb79fef03 226
kevman 0:38ceb79fef03 227 /*
kevman 0:38ceb79fef03 228 * HashAlgorithm
kevman 0:38ceb79fef03 229 */
kevman 0:38ceb79fef03 230 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kevman 0:38ceb79fef03 231 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
kevman 0:38ceb79fef03 232 {
kevman 0:38ceb79fef03 233 end2 = p + len;
kevman 0:38ceb79fef03 234
kevman 0:38ceb79fef03 235 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
kevman 0:38ceb79fef03 236 if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
kevman 0:38ceb79fef03 237 return( ret );
kevman 0:38ceb79fef03 238
kevman 0:38ceb79fef03 239 if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
kevman 0:38ceb79fef03 240 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 241
kevman 0:38ceb79fef03 242 if( p != end2 )
kevman 0:38ceb79fef03 243 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 244 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 245 }
kevman 0:38ceb79fef03 246 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kevman 0:38ceb79fef03 247 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 248
kevman 0:38ceb79fef03 249 if( p == end )
kevman 0:38ceb79fef03 250 return( 0 );
kevman 0:38ceb79fef03 251
kevman 0:38ceb79fef03 252 /*
kevman 0:38ceb79fef03 253 * MaskGenAlgorithm
kevman 0:38ceb79fef03 254 */
kevman 0:38ceb79fef03 255 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kevman 0:38ceb79fef03 256 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
kevman 0:38ceb79fef03 257 {
kevman 0:38ceb79fef03 258 end2 = p + len;
kevman 0:38ceb79fef03 259
kevman 0:38ceb79fef03 260 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
kevman 0:38ceb79fef03 261 if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
kevman 0:38ceb79fef03 262 return( ret );
kevman 0:38ceb79fef03 263
kevman 0:38ceb79fef03 264 /* Only MFG1 is recognised for now */
kevman 0:38ceb79fef03 265 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
kevman 0:38ceb79fef03 266 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
kevman 0:38ceb79fef03 267 MBEDTLS_ERR_OID_NOT_FOUND );
kevman 0:38ceb79fef03 268
kevman 0:38ceb79fef03 269 /* Parse HashAlgorithm */
kevman 0:38ceb79fef03 270 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
kevman 0:38ceb79fef03 271 return( ret );
kevman 0:38ceb79fef03 272
kevman 0:38ceb79fef03 273 if( p != end2 )
kevman 0:38ceb79fef03 274 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 275 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 276 }
kevman 0:38ceb79fef03 277 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kevman 0:38ceb79fef03 278 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 279
kevman 0:38ceb79fef03 280 if( p == end )
kevman 0:38ceb79fef03 281 return( 0 );
kevman 0:38ceb79fef03 282
kevman 0:38ceb79fef03 283 /*
kevman 0:38ceb79fef03 284 * salt_len
kevman 0:38ceb79fef03 285 */
kevman 0:38ceb79fef03 286 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kevman 0:38ceb79fef03 287 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
kevman 0:38ceb79fef03 288 {
kevman 0:38ceb79fef03 289 end2 = p + len;
kevman 0:38ceb79fef03 290
kevman 0:38ceb79fef03 291 if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
kevman 0:38ceb79fef03 292 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 293
kevman 0:38ceb79fef03 294 if( p != end2 )
kevman 0:38ceb79fef03 295 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 296 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 297 }
kevman 0:38ceb79fef03 298 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kevman 0:38ceb79fef03 299 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 300
kevman 0:38ceb79fef03 301 if( p == end )
kevman 0:38ceb79fef03 302 return( 0 );
kevman 0:38ceb79fef03 303
kevman 0:38ceb79fef03 304 /*
kevman 0:38ceb79fef03 305 * trailer_field (if present, must be 1)
kevman 0:38ceb79fef03 306 */
kevman 0:38ceb79fef03 307 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
kevman 0:38ceb79fef03 308 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
kevman 0:38ceb79fef03 309 {
kevman 0:38ceb79fef03 310 int trailer_field;
kevman 0:38ceb79fef03 311
kevman 0:38ceb79fef03 312 end2 = p + len;
kevman 0:38ceb79fef03 313
kevman 0:38ceb79fef03 314 if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
kevman 0:38ceb79fef03 315 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 316
kevman 0:38ceb79fef03 317 if( p != end2 )
kevman 0:38ceb79fef03 318 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 319 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 320
kevman 0:38ceb79fef03 321 if( trailer_field != 1 )
kevman 0:38ceb79fef03 322 return( MBEDTLS_ERR_X509_INVALID_ALG );
kevman 0:38ceb79fef03 323 }
kevman 0:38ceb79fef03 324 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
kevman 0:38ceb79fef03 325 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
kevman 0:38ceb79fef03 326
kevman 0:38ceb79fef03 327 if( p != end )
kevman 0:38ceb79fef03 328 return( MBEDTLS_ERR_X509_INVALID_ALG +
kevman 0:38ceb79fef03 329 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 330
kevman 0:38ceb79fef03 331 return( 0 );
kevman 0:38ceb79fef03 332 }
kevman 0:38ceb79fef03 333 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
kevman 0:38ceb79fef03 334
kevman 0:38ceb79fef03 335 /*
kevman 0:38ceb79fef03 336 * AttributeTypeAndValue ::= SEQUENCE {
kevman 0:38ceb79fef03 337 * type AttributeType,
kevman 0:38ceb79fef03 338 * value AttributeValue }
kevman 0:38ceb79fef03 339 *
kevman 0:38ceb79fef03 340 * AttributeType ::= OBJECT IDENTIFIER
kevman 0:38ceb79fef03 341 *
kevman 0:38ceb79fef03 342 * AttributeValue ::= ANY DEFINED BY AttributeType
kevman 0:38ceb79fef03 343 */
kevman 0:38ceb79fef03 344 static int x509_get_attr_type_value( unsigned char **p,
kevman 0:38ceb79fef03 345 const unsigned char *end,
kevman 0:38ceb79fef03 346 mbedtls_x509_name *cur )
kevman 0:38ceb79fef03 347 {
kevman 0:38ceb79fef03 348 int ret;
kevman 0:38ceb79fef03 349 size_t len;
kevman 0:38ceb79fef03 350 mbedtls_x509_buf *oid;
kevman 0:38ceb79fef03 351 mbedtls_x509_buf *val;
kevman 0:38ceb79fef03 352
kevman 0:38ceb79fef03 353 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kevman 0:38ceb79fef03 354 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kevman 0:38ceb79fef03 355 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
kevman 0:38ceb79fef03 356
kevman 0:38ceb79fef03 357 if( ( end - *p ) < 1 )
kevman 0:38ceb79fef03 358 return( MBEDTLS_ERR_X509_INVALID_NAME +
kevman 0:38ceb79fef03 359 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 360
kevman 0:38ceb79fef03 361 oid = &cur->oid;
kevman 0:38ceb79fef03 362 oid->tag = **p;
kevman 0:38ceb79fef03 363
kevman 0:38ceb79fef03 364 if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
kevman 0:38ceb79fef03 365 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
kevman 0:38ceb79fef03 366
kevman 0:38ceb79fef03 367 oid->p = *p;
kevman 0:38ceb79fef03 368 *p += oid->len;
kevman 0:38ceb79fef03 369
kevman 0:38ceb79fef03 370 if( ( end - *p ) < 1 )
kevman 0:38ceb79fef03 371 return( MBEDTLS_ERR_X509_INVALID_NAME +
kevman 0:38ceb79fef03 372 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 373
kevman 0:38ceb79fef03 374 if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
kevman 0:38ceb79fef03 375 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
kevman 0:38ceb79fef03 376 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
kevman 0:38ceb79fef03 377 **p != MBEDTLS_ASN1_BIT_STRING )
kevman 0:38ceb79fef03 378 return( MBEDTLS_ERR_X509_INVALID_NAME +
kevman 0:38ceb79fef03 379 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kevman 0:38ceb79fef03 380
kevman 0:38ceb79fef03 381 val = &cur->val;
kevman 0:38ceb79fef03 382 val->tag = *(*p)++;
kevman 0:38ceb79fef03 383
kevman 0:38ceb79fef03 384 if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
kevman 0:38ceb79fef03 385 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
kevman 0:38ceb79fef03 386
kevman 0:38ceb79fef03 387 val->p = *p;
kevman 0:38ceb79fef03 388 *p += val->len;
kevman 0:38ceb79fef03 389
kevman 0:38ceb79fef03 390 cur->next = NULL;
kevman 0:38ceb79fef03 391
kevman 0:38ceb79fef03 392 return( 0 );
kevman 0:38ceb79fef03 393 }
kevman 0:38ceb79fef03 394
kevman 0:38ceb79fef03 395 /*
kevman 0:38ceb79fef03 396 * Name ::= CHOICE { -- only one possibility for now --
kevman 0:38ceb79fef03 397 * rdnSequence RDNSequence }
kevman 0:38ceb79fef03 398 *
kevman 0:38ceb79fef03 399 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
kevman 0:38ceb79fef03 400 *
kevman 0:38ceb79fef03 401 * RelativeDistinguishedName ::=
kevman 0:38ceb79fef03 402 * SET OF AttributeTypeAndValue
kevman 0:38ceb79fef03 403 *
kevman 0:38ceb79fef03 404 * AttributeTypeAndValue ::= SEQUENCE {
kevman 0:38ceb79fef03 405 * type AttributeType,
kevman 0:38ceb79fef03 406 * value AttributeValue }
kevman 0:38ceb79fef03 407 *
kevman 0:38ceb79fef03 408 * AttributeType ::= OBJECT IDENTIFIER
kevman 0:38ceb79fef03 409 *
kevman 0:38ceb79fef03 410 * AttributeValue ::= ANY DEFINED BY AttributeType
kevman 0:38ceb79fef03 411 *
kevman 0:38ceb79fef03 412 * The data structure is optimized for the common case where each RDN has only
kevman 0:38ceb79fef03 413 * one element, which is represented as a list of AttributeTypeAndValue.
kevman 0:38ceb79fef03 414 * For the general case we still use a flat list, but we mark elements of the
kevman 0:38ceb79fef03 415 * same set so that they are "merged" together in the functions that consume
kevman 0:38ceb79fef03 416 * this list, eg mbedtls_x509_dn_gets().
kevman 0:38ceb79fef03 417 */
kevman 0:38ceb79fef03 418 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 419 mbedtls_x509_name *cur )
kevman 0:38ceb79fef03 420 {
kevman 0:38ceb79fef03 421 int ret;
kevman 0:38ceb79fef03 422 size_t set_len;
kevman 0:38ceb79fef03 423 const unsigned char *end_set;
kevman 0:38ceb79fef03 424
kevman 0:38ceb79fef03 425 /* don't use recursion, we'd risk stack overflow if not optimized */
kevman 0:38ceb79fef03 426 while( 1 )
kevman 0:38ceb79fef03 427 {
kevman 0:38ceb79fef03 428 /*
kevman 0:38ceb79fef03 429 * parse SET
kevman 0:38ceb79fef03 430 */
kevman 0:38ceb79fef03 431 if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
kevman 0:38ceb79fef03 432 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
kevman 0:38ceb79fef03 433 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
kevman 0:38ceb79fef03 434
kevman 0:38ceb79fef03 435 end_set = *p + set_len;
kevman 0:38ceb79fef03 436
kevman 0:38ceb79fef03 437 while( 1 )
kevman 0:38ceb79fef03 438 {
kevman 0:38ceb79fef03 439 if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
kevman 0:38ceb79fef03 440 return( ret );
kevman 0:38ceb79fef03 441
kevman 0:38ceb79fef03 442 if( *p == end_set )
kevman 0:38ceb79fef03 443 break;
kevman 0:38ceb79fef03 444
kevman 0:38ceb79fef03 445 /* Mark this item as being no the only one in a set */
kevman 0:38ceb79fef03 446 cur->next_merged = 1;
kevman 0:38ceb79fef03 447
kevman 0:38ceb79fef03 448 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
kevman 0:38ceb79fef03 449
kevman 0:38ceb79fef03 450 if( cur->next == NULL )
kevman 0:38ceb79fef03 451 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kevman 0:38ceb79fef03 452
kevman 0:38ceb79fef03 453 cur = cur->next;
kevman 0:38ceb79fef03 454 }
kevman 0:38ceb79fef03 455
kevman 0:38ceb79fef03 456 /*
kevman 0:38ceb79fef03 457 * continue until end of SEQUENCE is reached
kevman 0:38ceb79fef03 458 */
kevman 0:38ceb79fef03 459 if( *p == end )
kevman 0:38ceb79fef03 460 return( 0 );
kevman 0:38ceb79fef03 461
kevman 0:38ceb79fef03 462 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
kevman 0:38ceb79fef03 463
kevman 0:38ceb79fef03 464 if( cur->next == NULL )
kevman 0:38ceb79fef03 465 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kevman 0:38ceb79fef03 466
kevman 0:38ceb79fef03 467 cur = cur->next;
kevman 0:38ceb79fef03 468 }
kevman 0:38ceb79fef03 469 }
kevman 0:38ceb79fef03 470
kevman 0:38ceb79fef03 471 static int x509_parse_int( unsigned char **p, size_t n, int *res )
kevman 0:38ceb79fef03 472 {
kevman 0:38ceb79fef03 473 *res = 0;
kevman 0:38ceb79fef03 474
kevman 0:38ceb79fef03 475 for( ; n > 0; --n )
kevman 0:38ceb79fef03 476 {
kevman 0:38ceb79fef03 477 if( ( **p < '0') || ( **p > '9' ) )
kevman 0:38ceb79fef03 478 return ( MBEDTLS_ERR_X509_INVALID_DATE );
kevman 0:38ceb79fef03 479
kevman 0:38ceb79fef03 480 *res *= 10;
kevman 0:38ceb79fef03 481 *res += ( *(*p)++ - '0' );
kevman 0:38ceb79fef03 482 }
kevman 0:38ceb79fef03 483
kevman 0:38ceb79fef03 484 return( 0 );
kevman 0:38ceb79fef03 485 }
kevman 0:38ceb79fef03 486
kevman 0:38ceb79fef03 487 static int x509_date_is_valid(const mbedtls_x509_time *t )
kevman 0:38ceb79fef03 488 {
kevman 0:38ceb79fef03 489 int ret = MBEDTLS_ERR_X509_INVALID_DATE;
kevman 0:38ceb79fef03 490 int month_len;
kevman 0:38ceb79fef03 491
kevman 0:38ceb79fef03 492 CHECK_RANGE( 0, 9999, t->year );
kevman 0:38ceb79fef03 493 CHECK_RANGE( 0, 23, t->hour );
kevman 0:38ceb79fef03 494 CHECK_RANGE( 0, 59, t->min );
kevman 0:38ceb79fef03 495 CHECK_RANGE( 0, 59, t->sec );
kevman 0:38ceb79fef03 496
kevman 0:38ceb79fef03 497 switch( t->mon )
kevman 0:38ceb79fef03 498 {
kevman 0:38ceb79fef03 499 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
kevman 0:38ceb79fef03 500 month_len = 31;
kevman 0:38ceb79fef03 501 break;
kevman 0:38ceb79fef03 502 case 4: case 6: case 9: case 11:
kevman 0:38ceb79fef03 503 month_len = 30;
kevman 0:38ceb79fef03 504 break;
kevman 0:38ceb79fef03 505 case 2:
kevman 0:38ceb79fef03 506 if( ( !( t->year % 4 ) && t->year % 100 ) ||
kevman 0:38ceb79fef03 507 !( t->year % 400 ) )
kevman 0:38ceb79fef03 508 month_len = 29;
kevman 0:38ceb79fef03 509 else
kevman 0:38ceb79fef03 510 month_len = 28;
kevman 0:38ceb79fef03 511 break;
kevman 0:38ceb79fef03 512 default:
kevman 0:38ceb79fef03 513 return( ret );
kevman 0:38ceb79fef03 514 }
kevman 0:38ceb79fef03 515 CHECK_RANGE( 1, month_len, t->day );
kevman 0:38ceb79fef03 516
kevman 0:38ceb79fef03 517 return( 0 );
kevman 0:38ceb79fef03 518 }
kevman 0:38ceb79fef03 519
kevman 0:38ceb79fef03 520 /*
kevman 0:38ceb79fef03 521 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
kevman 0:38ceb79fef03 522 * field.
kevman 0:38ceb79fef03 523 */
kevman 0:38ceb79fef03 524 static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
kevman 0:38ceb79fef03 525 mbedtls_x509_time *tm )
kevman 0:38ceb79fef03 526 {
kevman 0:38ceb79fef03 527 int ret;
kevman 0:38ceb79fef03 528
kevman 0:38ceb79fef03 529 /*
kevman 0:38ceb79fef03 530 * Minimum length is 10 or 12 depending on yearlen
kevman 0:38ceb79fef03 531 */
kevman 0:38ceb79fef03 532 if ( len < yearlen + 8 )
kevman 0:38ceb79fef03 533 return ( MBEDTLS_ERR_X509_INVALID_DATE );
kevman 0:38ceb79fef03 534 len -= yearlen + 8;
kevman 0:38ceb79fef03 535
kevman 0:38ceb79fef03 536 /*
kevman 0:38ceb79fef03 537 * Parse year, month, day, hour, minute
kevman 0:38ceb79fef03 538 */
kevman 0:38ceb79fef03 539 CHECK( x509_parse_int( p, yearlen, &tm->year ) );
kevman 0:38ceb79fef03 540 if ( 2 == yearlen )
kevman 0:38ceb79fef03 541 {
kevman 0:38ceb79fef03 542 if ( tm->year < 50 )
kevman 0:38ceb79fef03 543 tm->year += 100;
kevman 0:38ceb79fef03 544
kevman 0:38ceb79fef03 545 tm->year += 1900;
kevman 0:38ceb79fef03 546 }
kevman 0:38ceb79fef03 547
kevman 0:38ceb79fef03 548 CHECK( x509_parse_int( p, 2, &tm->mon ) );
kevman 0:38ceb79fef03 549 CHECK( x509_parse_int( p, 2, &tm->day ) );
kevman 0:38ceb79fef03 550 CHECK( x509_parse_int( p, 2, &tm->hour ) );
kevman 0:38ceb79fef03 551 CHECK( x509_parse_int( p, 2, &tm->min ) );
kevman 0:38ceb79fef03 552
kevman 0:38ceb79fef03 553 /*
kevman 0:38ceb79fef03 554 * Parse seconds if present
kevman 0:38ceb79fef03 555 */
kevman 0:38ceb79fef03 556 if ( len >= 2 )
kevman 0:38ceb79fef03 557 {
kevman 0:38ceb79fef03 558 CHECK( x509_parse_int( p, 2, &tm->sec ) );
kevman 0:38ceb79fef03 559 len -= 2;
kevman 0:38ceb79fef03 560 }
kevman 0:38ceb79fef03 561 else
kevman 0:38ceb79fef03 562 return ( MBEDTLS_ERR_X509_INVALID_DATE );
kevman 0:38ceb79fef03 563
kevman 0:38ceb79fef03 564 /*
kevman 0:38ceb79fef03 565 * Parse trailing 'Z' if present
kevman 0:38ceb79fef03 566 */
kevman 0:38ceb79fef03 567 if ( 1 == len && 'Z' == **p )
kevman 0:38ceb79fef03 568 {
kevman 0:38ceb79fef03 569 (*p)++;
kevman 0:38ceb79fef03 570 len--;
kevman 0:38ceb79fef03 571 }
kevman 0:38ceb79fef03 572
kevman 0:38ceb79fef03 573 /*
kevman 0:38ceb79fef03 574 * We should have parsed all characters at this point
kevman 0:38ceb79fef03 575 */
kevman 0:38ceb79fef03 576 if ( 0 != len )
kevman 0:38ceb79fef03 577 return ( MBEDTLS_ERR_X509_INVALID_DATE );
kevman 0:38ceb79fef03 578
kevman 0:38ceb79fef03 579 CHECK( x509_date_is_valid( tm ) );
kevman 0:38ceb79fef03 580
kevman 0:38ceb79fef03 581 return ( 0 );
kevman 0:38ceb79fef03 582 }
kevman 0:38ceb79fef03 583
kevman 0:38ceb79fef03 584 /*
kevman 0:38ceb79fef03 585 * Time ::= CHOICE {
kevman 0:38ceb79fef03 586 * utcTime UTCTime,
kevman 0:38ceb79fef03 587 * generalTime GeneralizedTime }
kevman 0:38ceb79fef03 588 */
kevman 0:38ceb79fef03 589 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 590 mbedtls_x509_time *tm )
kevman 0:38ceb79fef03 591 {
kevman 0:38ceb79fef03 592 int ret;
kevman 0:38ceb79fef03 593 size_t len, year_len;
kevman 0:38ceb79fef03 594 unsigned char tag;
kevman 0:38ceb79fef03 595
kevman 0:38ceb79fef03 596 if( ( end - *p ) < 1 )
kevman 0:38ceb79fef03 597 return( MBEDTLS_ERR_X509_INVALID_DATE +
kevman 0:38ceb79fef03 598 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 599
kevman 0:38ceb79fef03 600 tag = **p;
kevman 0:38ceb79fef03 601
kevman 0:38ceb79fef03 602 if( tag == MBEDTLS_ASN1_UTC_TIME )
kevman 0:38ceb79fef03 603 year_len = 2;
kevman 0:38ceb79fef03 604 else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
kevman 0:38ceb79fef03 605 year_len = 4;
kevman 0:38ceb79fef03 606 else
kevman 0:38ceb79fef03 607 return( MBEDTLS_ERR_X509_INVALID_DATE +
kevman 0:38ceb79fef03 608 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
kevman 0:38ceb79fef03 609
kevman 0:38ceb79fef03 610 (*p)++;
kevman 0:38ceb79fef03 611 ret = mbedtls_asn1_get_len( p, end, &len );
kevman 0:38ceb79fef03 612
kevman 0:38ceb79fef03 613 if( ret != 0 )
kevman 0:38ceb79fef03 614 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
kevman 0:38ceb79fef03 615
kevman 0:38ceb79fef03 616 return x509_parse_time( p, len, year_len, tm );
kevman 0:38ceb79fef03 617 }
kevman 0:38ceb79fef03 618
kevman 0:38ceb79fef03 619 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
kevman 0:38ceb79fef03 620 {
kevman 0:38ceb79fef03 621 int ret;
kevman 0:38ceb79fef03 622 size_t len;
kevman 0:38ceb79fef03 623 int tag_type;
kevman 0:38ceb79fef03 624
kevman 0:38ceb79fef03 625 if( ( end - *p ) < 1 )
kevman 0:38ceb79fef03 626 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
kevman 0:38ceb79fef03 627 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
kevman 0:38ceb79fef03 628
kevman 0:38ceb79fef03 629 tag_type = **p;
kevman 0:38ceb79fef03 630
kevman 0:38ceb79fef03 631 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
kevman 0:38ceb79fef03 632 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
kevman 0:38ceb79fef03 633
kevman 0:38ceb79fef03 634 sig->tag = tag_type;
kevman 0:38ceb79fef03 635 sig->len = len;
kevman 0:38ceb79fef03 636 sig->p = *p;
kevman 0:38ceb79fef03 637
kevman 0:38ceb79fef03 638 *p += len;
kevman 0:38ceb79fef03 639
kevman 0:38ceb79fef03 640 return( 0 );
kevman 0:38ceb79fef03 641 }
kevman 0:38ceb79fef03 642
kevman 0:38ceb79fef03 643 /*
kevman 0:38ceb79fef03 644 * Get signature algorithm from alg OID and optional parameters
kevman 0:38ceb79fef03 645 */
kevman 0:38ceb79fef03 646 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
kevman 0:38ceb79fef03 647 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
kevman 0:38ceb79fef03 648 void **sig_opts )
kevman 0:38ceb79fef03 649 {
kevman 0:38ceb79fef03 650 int ret;
kevman 0:38ceb79fef03 651
kevman 0:38ceb79fef03 652 if( *sig_opts != NULL )
kevman 0:38ceb79fef03 653 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 654
kevman 0:38ceb79fef03 655 if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
kevman 0:38ceb79fef03 656 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
kevman 0:38ceb79fef03 657
kevman 0:38ceb79fef03 658 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
kevman 0:38ceb79fef03 659 if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
kevman 0:38ceb79fef03 660 {
kevman 0:38ceb79fef03 661 mbedtls_pk_rsassa_pss_options *pss_opts;
kevman 0:38ceb79fef03 662
kevman 0:38ceb79fef03 663 pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
kevman 0:38ceb79fef03 664 if( pss_opts == NULL )
kevman 0:38ceb79fef03 665 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
kevman 0:38ceb79fef03 666
kevman 0:38ceb79fef03 667 ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
kevman 0:38ceb79fef03 668 md_alg,
kevman 0:38ceb79fef03 669 &pss_opts->mgf1_hash_id,
kevman 0:38ceb79fef03 670 &pss_opts->expected_salt_len );
kevman 0:38ceb79fef03 671 if( ret != 0 )
kevman 0:38ceb79fef03 672 {
kevman 0:38ceb79fef03 673 mbedtls_free( pss_opts );
kevman 0:38ceb79fef03 674 return( ret );
kevman 0:38ceb79fef03 675 }
kevman 0:38ceb79fef03 676
kevman 0:38ceb79fef03 677 *sig_opts = (void *) pss_opts;
kevman 0:38ceb79fef03 678 }
kevman 0:38ceb79fef03 679 else
kevman 0:38ceb79fef03 680 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
kevman 0:38ceb79fef03 681 {
kevman 0:38ceb79fef03 682 /* Make sure parameters are absent or NULL */
kevman 0:38ceb79fef03 683 if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
kevman 0:38ceb79fef03 684 sig_params->len != 0 )
kevman 0:38ceb79fef03 685 return( MBEDTLS_ERR_X509_INVALID_ALG );
kevman 0:38ceb79fef03 686 }
kevman 0:38ceb79fef03 687
kevman 0:38ceb79fef03 688 return( 0 );
kevman 0:38ceb79fef03 689 }
kevman 0:38ceb79fef03 690
kevman 0:38ceb79fef03 691 /*
kevman 0:38ceb79fef03 692 * X.509 Extensions (No parsing of extensions, pointer should
kevman 0:38ceb79fef03 693 * be either manually updated or extensions should be parsed!)
kevman 0:38ceb79fef03 694 */
kevman 0:38ceb79fef03 695 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
kevman 0:38ceb79fef03 696 mbedtls_x509_buf *ext, int tag )
kevman 0:38ceb79fef03 697 {
kevman 0:38ceb79fef03 698 int ret;
kevman 0:38ceb79fef03 699 size_t len;
kevman 0:38ceb79fef03 700
kevman 0:38ceb79fef03 701 if( *p == end )
kevman 0:38ceb79fef03 702 return( 0 );
kevman 0:38ceb79fef03 703
kevman 0:38ceb79fef03 704 ext->tag = **p;
kevman 0:38ceb79fef03 705
kevman 0:38ceb79fef03 706 if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
kevman 0:38ceb79fef03 707 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 )
kevman 0:38ceb79fef03 708 return( ret );
kevman 0:38ceb79fef03 709
kevman 0:38ceb79fef03 710 ext->p = *p;
kevman 0:38ceb79fef03 711 end = *p + ext->len;
kevman 0:38ceb79fef03 712
kevman 0:38ceb79fef03 713 /*
kevman 0:38ceb79fef03 714 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
kevman 0:38ceb79fef03 715 *
kevman 0:38ceb79fef03 716 * Extension ::= SEQUENCE {
kevman 0:38ceb79fef03 717 * extnID OBJECT IDENTIFIER,
kevman 0:38ceb79fef03 718 * critical BOOLEAN DEFAULT FALSE,
kevman 0:38ceb79fef03 719 * extnValue OCTET STRING }
kevman 0:38ceb79fef03 720 */
kevman 0:38ceb79fef03 721 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
kevman 0:38ceb79fef03 722 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
kevman 0:38ceb79fef03 723 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
kevman 0:38ceb79fef03 724
kevman 0:38ceb79fef03 725 if( end != *p + len )
kevman 0:38ceb79fef03 726 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
kevman 0:38ceb79fef03 727 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
kevman 0:38ceb79fef03 728
kevman 0:38ceb79fef03 729 return( 0 );
kevman 0:38ceb79fef03 730 }
kevman 0:38ceb79fef03 731
kevman 0:38ceb79fef03 732 /*
kevman 0:38ceb79fef03 733 * Store the name in printable form into buf; no more
kevman 0:38ceb79fef03 734 * than size characters will be written
kevman 0:38ceb79fef03 735 */
kevman 0:38ceb79fef03 736 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
kevman 0:38ceb79fef03 737 {
kevman 0:38ceb79fef03 738 int ret;
kevman 0:38ceb79fef03 739 size_t i, n;
kevman 0:38ceb79fef03 740 unsigned char c, merge = 0;
kevman 0:38ceb79fef03 741 const mbedtls_x509_name *name;
kevman 0:38ceb79fef03 742 const char *short_name = NULL;
kevman 0:38ceb79fef03 743 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
kevman 0:38ceb79fef03 744
kevman 0:38ceb79fef03 745 memset( s, 0, sizeof( s ) );
kevman 0:38ceb79fef03 746
kevman 0:38ceb79fef03 747 name = dn;
kevman 0:38ceb79fef03 748 p = buf;
kevman 0:38ceb79fef03 749 n = size;
kevman 0:38ceb79fef03 750
kevman 0:38ceb79fef03 751 while( name != NULL )
kevman 0:38ceb79fef03 752 {
kevman 0:38ceb79fef03 753 if( !name->oid.p )
kevman 0:38ceb79fef03 754 {
kevman 0:38ceb79fef03 755 name = name->next;
kevman 0:38ceb79fef03 756 continue;
kevman 0:38ceb79fef03 757 }
kevman 0:38ceb79fef03 758
kevman 0:38ceb79fef03 759 if( name != dn )
kevman 0:38ceb79fef03 760 {
kevman 0:38ceb79fef03 761 ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
kevman 0:38ceb79fef03 762 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 763 }
kevman 0:38ceb79fef03 764
kevman 0:38ceb79fef03 765 ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
kevman 0:38ceb79fef03 766
kevman 0:38ceb79fef03 767 if( ret == 0 )
kevman 0:38ceb79fef03 768 ret = mbedtls_snprintf( p, n, "%s=", short_name );
kevman 0:38ceb79fef03 769 else
kevman 0:38ceb79fef03 770 ret = mbedtls_snprintf( p, n, "\?\?=" );
kevman 0:38ceb79fef03 771 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 772
kevman 0:38ceb79fef03 773 for( i = 0; i < name->val.len; i++ )
kevman 0:38ceb79fef03 774 {
kevman 0:38ceb79fef03 775 if( i >= sizeof( s ) - 1 )
kevman 0:38ceb79fef03 776 break;
kevman 0:38ceb79fef03 777
kevman 0:38ceb79fef03 778 c = name->val.p[i];
kevman 0:38ceb79fef03 779 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
kevman 0:38ceb79fef03 780 s[i] = '?';
kevman 0:38ceb79fef03 781 else s[i] = c;
kevman 0:38ceb79fef03 782 }
kevman 0:38ceb79fef03 783 s[i] = '\0';
kevman 0:38ceb79fef03 784 ret = mbedtls_snprintf( p, n, "%s", s );
kevman 0:38ceb79fef03 785 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 786
kevman 0:38ceb79fef03 787 merge = name->next_merged;
kevman 0:38ceb79fef03 788 name = name->next;
kevman 0:38ceb79fef03 789 }
kevman 0:38ceb79fef03 790
kevman 0:38ceb79fef03 791 return( (int) ( size - n ) );
kevman 0:38ceb79fef03 792 }
kevman 0:38ceb79fef03 793
kevman 0:38ceb79fef03 794 /*
kevman 0:38ceb79fef03 795 * Store the serial in printable form into buf; no more
kevman 0:38ceb79fef03 796 * than size characters will be written
kevman 0:38ceb79fef03 797 */
kevman 0:38ceb79fef03 798 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
kevman 0:38ceb79fef03 799 {
kevman 0:38ceb79fef03 800 int ret;
kevman 0:38ceb79fef03 801 size_t i, n, nr;
kevman 0:38ceb79fef03 802 char *p;
kevman 0:38ceb79fef03 803
kevman 0:38ceb79fef03 804 p = buf;
kevman 0:38ceb79fef03 805 n = size;
kevman 0:38ceb79fef03 806
kevman 0:38ceb79fef03 807 nr = ( serial->len <= 32 )
kevman 0:38ceb79fef03 808 ? serial->len : 28;
kevman 0:38ceb79fef03 809
kevman 0:38ceb79fef03 810 for( i = 0; i < nr; i++ )
kevman 0:38ceb79fef03 811 {
kevman 0:38ceb79fef03 812 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
kevman 0:38ceb79fef03 813 continue;
kevman 0:38ceb79fef03 814
kevman 0:38ceb79fef03 815 ret = mbedtls_snprintf( p, n, "%02X%s",
kevman 0:38ceb79fef03 816 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
kevman 0:38ceb79fef03 817 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 818 }
kevman 0:38ceb79fef03 819
kevman 0:38ceb79fef03 820 if( nr != serial->len )
kevman 0:38ceb79fef03 821 {
kevman 0:38ceb79fef03 822 ret = mbedtls_snprintf( p, n, "...." );
kevman 0:38ceb79fef03 823 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 824 }
kevman 0:38ceb79fef03 825
kevman 0:38ceb79fef03 826 return( (int) ( size - n ) );
kevman 0:38ceb79fef03 827 }
kevman 0:38ceb79fef03 828
kevman 0:38ceb79fef03 829 /*
kevman 0:38ceb79fef03 830 * Helper for writing signature algorithms
kevman 0:38ceb79fef03 831 */
kevman 0:38ceb79fef03 832 int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
kevman 0:38ceb79fef03 833 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 834 const void *sig_opts )
kevman 0:38ceb79fef03 835 {
kevman 0:38ceb79fef03 836 int ret;
kevman 0:38ceb79fef03 837 char *p = buf;
kevman 0:38ceb79fef03 838 size_t n = size;
kevman 0:38ceb79fef03 839 const char *desc = NULL;
kevman 0:38ceb79fef03 840
kevman 0:38ceb79fef03 841 ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
kevman 0:38ceb79fef03 842 if( ret != 0 )
kevman 0:38ceb79fef03 843 ret = mbedtls_snprintf( p, n, "???" );
kevman 0:38ceb79fef03 844 else
kevman 0:38ceb79fef03 845 ret = mbedtls_snprintf( p, n, "%s", desc );
kevman 0:38ceb79fef03 846 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 847
kevman 0:38ceb79fef03 848 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
kevman 0:38ceb79fef03 849 if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
kevman 0:38ceb79fef03 850 {
kevman 0:38ceb79fef03 851 const mbedtls_pk_rsassa_pss_options *pss_opts;
kevman 0:38ceb79fef03 852 const mbedtls_md_info_t *md_info, *mgf_md_info;
kevman 0:38ceb79fef03 853
kevman 0:38ceb79fef03 854 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
kevman 0:38ceb79fef03 855
kevman 0:38ceb79fef03 856 md_info = mbedtls_md_info_from_type( md_alg );
kevman 0:38ceb79fef03 857 mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
kevman 0:38ceb79fef03 858
kevman 0:38ceb79fef03 859 ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
kevman 0:38ceb79fef03 860 md_info ? mbedtls_md_get_name( md_info ) : "???",
kevman 0:38ceb79fef03 861 mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
kevman 0:38ceb79fef03 862 pss_opts->expected_salt_len );
kevman 0:38ceb79fef03 863 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 864 }
kevman 0:38ceb79fef03 865 #else
kevman 0:38ceb79fef03 866 ((void) pk_alg);
kevman 0:38ceb79fef03 867 ((void) md_alg);
kevman 0:38ceb79fef03 868 ((void) sig_opts);
kevman 0:38ceb79fef03 869 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
kevman 0:38ceb79fef03 870
kevman 0:38ceb79fef03 871 return( (int)( size - n ) );
kevman 0:38ceb79fef03 872 }
kevman 0:38ceb79fef03 873
kevman 0:38ceb79fef03 874 /*
kevman 0:38ceb79fef03 875 * Helper for writing "RSA key size", "EC key size", etc
kevman 0:38ceb79fef03 876 */
kevman 0:38ceb79fef03 877 int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
kevman 0:38ceb79fef03 878 {
kevman 0:38ceb79fef03 879 char *p = buf;
kevman 0:38ceb79fef03 880 size_t n = buf_size;
kevman 0:38ceb79fef03 881 int ret;
kevman 0:38ceb79fef03 882
kevman 0:38ceb79fef03 883 ret = mbedtls_snprintf( p, n, "%s key size", name );
kevman 0:38ceb79fef03 884 MBEDTLS_X509_SAFE_SNPRINTF;
kevman 0:38ceb79fef03 885
kevman 0:38ceb79fef03 886 return( 0 );
kevman 0:38ceb79fef03 887 }
kevman 0:38ceb79fef03 888
kevman 0:38ceb79fef03 889 #if defined(MBEDTLS_HAVE_TIME_DATE)
kevman 0:38ceb79fef03 890 /*
kevman 0:38ceb79fef03 891 * Set the time structure to the current time.
kevman 0:38ceb79fef03 892 * Return 0 on success, non-zero on failure.
kevman 0:38ceb79fef03 893 */
kevman 0:38ceb79fef03 894 static int x509_get_current_time( mbedtls_x509_time *now )
kevman 0:38ceb79fef03 895 {
kevman 0:38ceb79fef03 896 struct tm *lt, tm_buf;
kevman 0:38ceb79fef03 897 mbedtls_time_t tt;
kevman 0:38ceb79fef03 898 int ret = 0;
kevman 0:38ceb79fef03 899
kevman 0:38ceb79fef03 900 tt = mbedtls_time( NULL );
kevman 0:38ceb79fef03 901 lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
kevman 0:38ceb79fef03 902
kevman 0:38ceb79fef03 903 if( lt == NULL )
kevman 0:38ceb79fef03 904 ret = -1;
kevman 0:38ceb79fef03 905 else
kevman 0:38ceb79fef03 906 {
kevman 0:38ceb79fef03 907 now->year = lt->tm_year + 1900;
kevman 0:38ceb79fef03 908 now->mon = lt->tm_mon + 1;
kevman 0:38ceb79fef03 909 now->day = lt->tm_mday;
kevman 0:38ceb79fef03 910 now->hour = lt->tm_hour;
kevman 0:38ceb79fef03 911 now->min = lt->tm_min;
kevman 0:38ceb79fef03 912 now->sec = lt->tm_sec;
kevman 0:38ceb79fef03 913 }
kevman 0:38ceb79fef03 914
kevman 0:38ceb79fef03 915 return( ret );
kevman 0:38ceb79fef03 916 }
kevman 0:38ceb79fef03 917
kevman 0:38ceb79fef03 918 /*
kevman 0:38ceb79fef03 919 * Return 0 if before <= after, 1 otherwise
kevman 0:38ceb79fef03 920 */
kevman 0:38ceb79fef03 921 static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
kevman 0:38ceb79fef03 922 {
kevman 0:38ceb79fef03 923 if( before->year > after->year )
kevman 0:38ceb79fef03 924 return( 1 );
kevman 0:38ceb79fef03 925
kevman 0:38ceb79fef03 926 if( before->year == after->year &&
kevman 0:38ceb79fef03 927 before->mon > after->mon )
kevman 0:38ceb79fef03 928 return( 1 );
kevman 0:38ceb79fef03 929
kevman 0:38ceb79fef03 930 if( before->year == after->year &&
kevman 0:38ceb79fef03 931 before->mon == after->mon &&
kevman 0:38ceb79fef03 932 before->day > after->day )
kevman 0:38ceb79fef03 933 return( 1 );
kevman 0:38ceb79fef03 934
kevman 0:38ceb79fef03 935 if( before->year == after->year &&
kevman 0:38ceb79fef03 936 before->mon == after->mon &&
kevman 0:38ceb79fef03 937 before->day == after->day &&
kevman 0:38ceb79fef03 938 before->hour > after->hour )
kevman 0:38ceb79fef03 939 return( 1 );
kevman 0:38ceb79fef03 940
kevman 0:38ceb79fef03 941 if( before->year == after->year &&
kevman 0:38ceb79fef03 942 before->mon == after->mon &&
kevman 0:38ceb79fef03 943 before->day == after->day &&
kevman 0:38ceb79fef03 944 before->hour == after->hour &&
kevman 0:38ceb79fef03 945 before->min > after->min )
kevman 0:38ceb79fef03 946 return( 1 );
kevman 0:38ceb79fef03 947
kevman 0:38ceb79fef03 948 if( before->year == after->year &&
kevman 0:38ceb79fef03 949 before->mon == after->mon &&
kevman 0:38ceb79fef03 950 before->day == after->day &&
kevman 0:38ceb79fef03 951 before->hour == after->hour &&
kevman 0:38ceb79fef03 952 before->min == after->min &&
kevman 0:38ceb79fef03 953 before->sec > after->sec )
kevman 0:38ceb79fef03 954 return( 1 );
kevman 0:38ceb79fef03 955
kevman 0:38ceb79fef03 956 return( 0 );
kevman 0:38ceb79fef03 957 }
kevman 0:38ceb79fef03 958
kevman 0:38ceb79fef03 959 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
kevman 0:38ceb79fef03 960 {
kevman 0:38ceb79fef03 961 mbedtls_x509_time now;
kevman 0:38ceb79fef03 962
kevman 0:38ceb79fef03 963 if( x509_get_current_time( &now ) != 0 )
kevman 0:38ceb79fef03 964 return( 1 );
kevman 0:38ceb79fef03 965
kevman 0:38ceb79fef03 966 return( x509_check_time( &now, to ) );
kevman 0:38ceb79fef03 967 }
kevman 0:38ceb79fef03 968
kevman 0:38ceb79fef03 969 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
kevman 0:38ceb79fef03 970 {
kevman 0:38ceb79fef03 971 mbedtls_x509_time now;
kevman 0:38ceb79fef03 972
kevman 0:38ceb79fef03 973 if( x509_get_current_time( &now ) != 0 )
kevman 0:38ceb79fef03 974 return( 1 );
kevman 0:38ceb79fef03 975
kevman 0:38ceb79fef03 976 return( x509_check_time( from, &now ) );
kevman 0:38ceb79fef03 977 }
kevman 0:38ceb79fef03 978
kevman 0:38ceb79fef03 979 #else /* MBEDTLS_HAVE_TIME_DATE */
kevman 0:38ceb79fef03 980
kevman 0:38ceb79fef03 981 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
kevman 0:38ceb79fef03 982 {
kevman 0:38ceb79fef03 983 ((void) to);
kevman 0:38ceb79fef03 984 return( 0 );
kevman 0:38ceb79fef03 985 }
kevman 0:38ceb79fef03 986
kevman 0:38ceb79fef03 987 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
kevman 0:38ceb79fef03 988 {
kevman 0:38ceb79fef03 989 ((void) from);
kevman 0:38ceb79fef03 990 return( 0 );
kevman 0:38ceb79fef03 991 }
kevman 0:38ceb79fef03 992 #endif /* MBEDTLS_HAVE_TIME_DATE */
kevman 0:38ceb79fef03 993
kevman 0:38ceb79fef03 994 #if defined(MBEDTLS_SELF_TEST)
kevman 0:38ceb79fef03 995
kevman 0:38ceb79fef03 996 #include "mbedtls/x509_crt.h"
kevman 0:38ceb79fef03 997 #include "mbedtls/certs.h"
kevman 0:38ceb79fef03 998
kevman 0:38ceb79fef03 999 /*
kevman 0:38ceb79fef03 1000 * Checkup routine
kevman 0:38ceb79fef03 1001 */
kevman 0:38ceb79fef03 1002 int mbedtls_x509_self_test( int verbose )
kevman 0:38ceb79fef03 1003 {
kevman 0:38ceb79fef03 1004 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
kevman 0:38ceb79fef03 1005 int ret;
kevman 0:38ceb79fef03 1006 uint32_t flags;
kevman 0:38ceb79fef03 1007 mbedtls_x509_crt cacert;
kevman 0:38ceb79fef03 1008 mbedtls_x509_crt clicert;
kevman 0:38ceb79fef03 1009
kevman 0:38ceb79fef03 1010 if( verbose != 0 )
kevman 0:38ceb79fef03 1011 mbedtls_printf( " X.509 certificate load: " );
kevman 0:38ceb79fef03 1012
kevman 0:38ceb79fef03 1013 mbedtls_x509_crt_init( &clicert );
kevman 0:38ceb79fef03 1014
kevman 0:38ceb79fef03 1015 ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
kevman 0:38ceb79fef03 1016 mbedtls_test_cli_crt_len );
kevman 0:38ceb79fef03 1017 if( ret != 0 )
kevman 0:38ceb79fef03 1018 {
kevman 0:38ceb79fef03 1019 if( verbose != 0 )
kevman 0:38ceb79fef03 1020 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 1021
kevman 0:38ceb79fef03 1022 return( ret );
kevman 0:38ceb79fef03 1023 }
kevman 0:38ceb79fef03 1024
kevman 0:38ceb79fef03 1025 mbedtls_x509_crt_init( &cacert );
kevman 0:38ceb79fef03 1026
kevman 0:38ceb79fef03 1027 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
kevman 0:38ceb79fef03 1028 mbedtls_test_ca_crt_len );
kevman 0:38ceb79fef03 1029 if( ret != 0 )
kevman 0:38ceb79fef03 1030 {
kevman 0:38ceb79fef03 1031 if( verbose != 0 )
kevman 0:38ceb79fef03 1032 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 1033
kevman 0:38ceb79fef03 1034 return( ret );
kevman 0:38ceb79fef03 1035 }
kevman 0:38ceb79fef03 1036
kevman 0:38ceb79fef03 1037 if( verbose != 0 )
kevman 0:38ceb79fef03 1038 mbedtls_printf( "passed\n X.509 signature verify: ");
kevman 0:38ceb79fef03 1039
kevman 0:38ceb79fef03 1040 ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
kevman 0:38ceb79fef03 1041 if( ret != 0 )
kevman 0:38ceb79fef03 1042 {
kevman 0:38ceb79fef03 1043 if( verbose != 0 )
kevman 0:38ceb79fef03 1044 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 1045
kevman 0:38ceb79fef03 1046 return( ret );
kevman 0:38ceb79fef03 1047 }
kevman 0:38ceb79fef03 1048
kevman 0:38ceb79fef03 1049 if( verbose != 0 )
kevman 0:38ceb79fef03 1050 mbedtls_printf( "passed\n\n");
kevman 0:38ceb79fef03 1051
kevman 0:38ceb79fef03 1052 mbedtls_x509_crt_free( &cacert );
kevman 0:38ceb79fef03 1053 mbedtls_x509_crt_free( &clicert );
kevman 0:38ceb79fef03 1054
kevman 0:38ceb79fef03 1055 return( 0 );
kevman 0:38ceb79fef03 1056 #else
kevman 0:38ceb79fef03 1057 ((void) verbose);
kevman 0:38ceb79fef03 1058 return( 0 );
kevman 0:38ceb79fef03 1059 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
kevman 0:38ceb79fef03 1060 }
kevman 0:38ceb79fef03 1061
kevman 0:38ceb79fef03 1062 #endif /* MBEDTLS_SELF_TEST */
kevman 0:38ceb79fef03 1063
kevman 0:38ceb79fef03 1064 #endif /* MBEDTLS_X509_USE_C */