Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

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