1 /* 2 * X.509 base functions for creating certificates / CSRs 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 * 7 * This file is provided under the Apache License 2.0, or the 8 * GNU General Public License v2.0 or later. 9 * 10 * ********** 11 * Apache License 2.0: 12 * 13 * Licensed under the Apache License, Version 2.0 (the "License"); you may 14 * not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 * 25 * ********** 26 * 27 * ********** 28 * GNU General Public License v2.0 or later: 29 * 30 * This program is free software; you can redistribute it and/or modify 31 * it under the terms of the GNU General Public License as published by 32 * the Free Software Foundation; either version 2 of the License, or 33 * (at your option) any later version. 34 * 35 * This program is distributed in the hope that it will be useful, 36 * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 * GNU General Public License for more details. 39 * 40 * You should have received a copy of the GNU General Public License along 41 * with this program; if not, write to the Free Software Foundation, Inc., 42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43 * 44 * ********** 45 */ 46 47 #if !defined(MBEDTLS_CONFIG_FILE) 48 #include "mbedtls/config.h" 49 #else 50 #include MBEDTLS_CONFIG_FILE 51 #endif 52 53 #if defined(MBEDTLS_X509_CREATE_C) 54 55 #include "mbedtls/x509.h" 56 #include "mbedtls/asn1write.h" 57 #include "mbedtls/oid.h" 58 59 #include <string.h> 60 61 /* Structure linking OIDs for X.509 DN AttributeTypes to their 62 * string representations and default string encodings used by Mbed TLS. */ 63 typedef struct { 64 const char *name; /* String representation of AttributeType, e.g. 65 * "CN" or "emailAddress". */ 66 size_t name_len; /* Length of 'name', without trailing 0 byte. */ 67 const char *oid; /* String representation of OID of AttributeType, 68 * as per RFC 5280, Appendix A.1. */ 69 int default_tag; /* The default character encoding used for the 70 * given attribute type, e.g. 71 * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ 72 } x509_attr_descriptor_t; 73 74 #define ADD_STRLEN( s ) s, sizeof( s ) - 1 75 76 /* X.509 DN attributes from RFC 5280, Appendix A.1. */ 77 static const x509_attr_descriptor_t x509_attrs[] = 78 { 79 { ADD_STRLEN( "CN" ), 80 MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, 81 { ADD_STRLEN( "commonName" ), 82 MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, 83 { ADD_STRLEN( "C" ), 84 MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, 85 { ADD_STRLEN( "countryName" ), 86 MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, 87 { ADD_STRLEN( "O" ), 88 MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, 89 { ADD_STRLEN( "organizationName" ), 90 MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, 91 { ADD_STRLEN( "L" ), 92 MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, 93 { ADD_STRLEN( "locality" ), 94 MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, 95 { ADD_STRLEN( "R" ), 96 MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, 97 { ADD_STRLEN( "OU" ), 98 MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, 99 { ADD_STRLEN( "organizationalUnitName" ), 100 MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, 101 { ADD_STRLEN( "ST" ), 102 MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, 103 { ADD_STRLEN( "stateOrProvinceName" ), 104 MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, 105 { ADD_STRLEN( "emailAddress" ), 106 MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, 107 { ADD_STRLEN( "serialNumber" ), 108 MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, 109 { ADD_STRLEN( "postalAddress" ), 110 MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, 111 { ADD_STRLEN( "postalCode" ), 112 MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, 113 { ADD_STRLEN( "dnQualifier" ), 114 MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, 115 { ADD_STRLEN( "title" ), 116 MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, 117 { ADD_STRLEN( "surName" ), 118 MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, 119 { ADD_STRLEN( "SN" ), 120 MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, 121 { ADD_STRLEN( "givenName" ), 122 MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, 123 { ADD_STRLEN( "GN" ), 124 MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, 125 { ADD_STRLEN( "initials" ), 126 MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, 127 { ADD_STRLEN( "pseudonym" ), 128 MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, 129 { ADD_STRLEN( "generationQualifier" ), 130 MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, 131 { ADD_STRLEN( "domainComponent" ), 132 MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, 133 { ADD_STRLEN( "DC" ), 134 MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, 135 { NULL, 0, NULL, MBEDTLS_ASN1_NULL } 136 }; 137 138 static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) 139 { 140 const x509_attr_descriptor_t *cur; 141 142 for( cur = x509_attrs; cur->name != NULL; cur++ ) 143 if( cur->name_len == name_len && 144 strncmp( cur->name, name, name_len ) == 0 ) 145 break; 146 147 if ( cur->name == NULL ) 148 return( NULL ); 149 150 return( cur ); 151 } 152 153 int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) 154 { 155 int ret = 0; 156 const char *s = name, *c = s; 157 const char *end = s + strlen( s ); 158 const char *oid = NULL; 159 const x509_attr_descriptor_t* attr_descr = NULL; 160 int in_tag = 1; 161 char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; 162 char *d = data; 163 164 /* Clear existing chain if present */ 165 mbedtls_asn1_free_named_data_list( head ); 166 167 while( c <= end ) 168 { 169 if( in_tag && *c == '=' ) 170 { 171 if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) 172 { 173 ret = MBEDTLS_ERR_X509_UNKNOWN_OID; 174 goto exit; 175 } 176 177 oid = attr_descr->oid; 178 s = c + 1; 179 in_tag = 0; 180 d = data; 181 } 182 183 if( !in_tag && *c == '\\' && c != end ) 184 { 185 c++; 186 187 /* Check for valid escaped characters */ 188 if( c == end || *c != ',' ) 189 { 190 ret = MBEDTLS_ERR_X509_INVALID_NAME; 191 goto exit; 192 } 193 } 194 else if( !in_tag && ( *c == ',' || c == end ) ) 195 { 196 mbedtls_asn1_named_data* cur = 197 mbedtls_asn1_store_named_data( head, oid, strlen( oid ), 198 (unsigned char *) data, 199 d - data ); 200 201 if(cur == NULL ) 202 { 203 return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 204 } 205 206 // set tagType 207 cur->val.tag = attr_descr->default_tag; 208 209 while( c < end && *(c + 1) == ' ' ) 210 c++; 211 212 s = c + 1; 213 in_tag = 1; 214 } 215 216 if( !in_tag && s != c + 1 ) 217 { 218 *(d++) = *c; 219 220 if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) 221 { 222 ret = MBEDTLS_ERR_X509_INVALID_NAME; 223 goto exit; 224 } 225 } 226 227 c++; 228 } 229 230 exit: 231 232 return( ret ); 233 } 234 235 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved 236 * to store the critical boolean for us 237 */ 238 int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, 239 int critical, const unsigned char *val, size_t val_len ) 240 { 241 mbedtls_asn1_named_data *cur; 242 243 if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, 244 NULL, val_len + 1 ) ) == NULL ) 245 { 246 return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 247 } 248 249 cur->val.p[0] = critical; 250 memcpy( cur->val.p + 1, val, val_len ); 251 252 return( 0 ); 253 } 254 255 /* 256 * RelativeDistinguishedName ::= 257 * SET OF AttributeTypeAndValue 258 * 259 * AttributeTypeAndValue ::= SEQUENCE { 260 * type AttributeType, 261 * value AttributeValue } 262 * 263 * AttributeType ::= OBJECT IDENTIFIER 264 * 265 * AttributeValue ::= ANY DEFINED BY AttributeType 266 */ 267 static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) 268 { 269 int ret; 270 size_t len = 0; 271 const char *oid = (const char*)cur_name->oid.p; 272 size_t oid_len = cur_name->oid.len; 273 const unsigned char *name = cur_name->val.p; 274 size_t name_len = cur_name->val.len; 275 276 // Write correct string tag and value 277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, 278 cur_name->val.tag, 279 (const char *) name, 280 name_len ) ); 281 // Write OID 282 // 283 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, 284 oid_len ) ); 285 286 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 287 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 288 MBEDTLS_ASN1_CONSTRUCTED | 289 MBEDTLS_ASN1_SEQUENCE ) ); 290 291 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 292 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 293 MBEDTLS_ASN1_CONSTRUCTED | 294 MBEDTLS_ASN1_SET ) ); 295 296 return( (int) len ); 297 } 298 299 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, 300 mbedtls_asn1_named_data *first ) 301 { 302 int ret; 303 size_t len = 0; 304 mbedtls_asn1_named_data *cur = first; 305 306 while( cur != NULL ) 307 { 308 MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); 309 cur = cur->next; 310 } 311 312 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 313 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | 314 MBEDTLS_ASN1_SEQUENCE ) ); 315 316 return( (int) len ); 317 } 318 319 int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, 320 const char *oid, size_t oid_len, 321 unsigned char *sig, size_t size ) 322 { 323 int ret; 324 size_t len = 0; 325 326 if( *p < start || (size_t)( *p - start ) < size ) 327 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 328 329 len = size; 330 (*p) -= len; 331 memcpy( *p, sig, len ); 332 333 if( *p - start < 1 ) 334 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 335 336 *--(*p) = 0; 337 len += 1; 338 339 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 340 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 341 342 // Write OID 343 // 344 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, 345 oid_len, 0 ) ); 346 347 return( (int) len ); 348 } 349 350 static int x509_write_extension( unsigned char **p, unsigned char *start, 351 mbedtls_asn1_named_data *ext ) 352 { 353 int ret; 354 size_t len = 0; 355 356 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, 357 ext->val.len - 1 ) ); 358 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); 359 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 360 361 if( ext->val.p[0] != 0 ) 362 { 363 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); 364 } 365 366 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, 367 ext->oid.len ) ); 368 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); 369 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 370 371 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 372 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | 373 MBEDTLS_ASN1_SEQUENCE ) ); 374 375 return( (int) len ); 376 } 377 378 /* 379 * Extension ::= SEQUENCE { 380 * extnID OBJECT IDENTIFIER, 381 * critical BOOLEAN DEFAULT FALSE, 382 * extnValue OCTET STRING 383 * -- contains the DER encoding of an ASN.1 value 384 * -- corresponding to the extension type identified 385 * -- by extnID 386 * } 387 */ 388 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, 389 mbedtls_asn1_named_data *first ) 390 { 391 int ret; 392 size_t len = 0; 393 mbedtls_asn1_named_data *cur_ext = first; 394 395 while( cur_ext != NULL ) 396 { 397 MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); 398 cur_ext = cur_ext->next; 399 } 400 401 return( (int) len ); 402 } 403 404 #endif /* MBEDTLS_X509_CREATE_C */ 405