mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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