1 /**************************************************************************** 2 * * 3 * Certificate Attribute Routines Header File * 4 * Copyright Peter Gutmann 1997-2011 * 5 * * 6 ****************************************************************************/ 7 8 #ifndef _CERTATTR_DEFINED 9 10 #define _CERTATTR_DEFINED 11 12 /**************************************************************************** 13 * * 14 * Type Information Flags * 15 * * 16 ****************************************************************************/ 17 18 /* The attribute type information. This is used to both check the validity 19 of encoded attribute data and to describe the structure of an attribute 20 when encoding it. 21 22 The flags are broken down into the following groups: 23 24 Attribute-specific flags that apply to an individual field or an 25 overall attribute. 26 27 SET/SEQUENCE control flags that indicate the end of a SET/SEQUENCE or 28 nested SET/SEQUENCE. These are only used for encoding, for decoding the 29 decoder maintains a parse state stack driven by the encoded data 30 (actually that's not quite correct, when skipping to the end of some 31 SEQUENCEs containing type-and-value pairs we also use the flags to locate 32 the end of the SEQUENCE encoding/start of the next type-and-value entry). 33 The use of SEQEND gets extremely complicated in the presence of optional 34 nested SEQUENCEs because it's not certain how many levels we need to 35 undo. Consider for example name constraints: 36 37 SEQUENCE { 38 permittedSubtrees [ 0 ] SEQUENCE OF { 39 SEQUENCE { GeneralName } 40 } OPTIONAL, 41 excludedSubtrees [ 1 ] SEQUENCE OF { 42 SEQUENCE { GeneralName } 43 } OPTIONAL, 44 } 45 46 Is the value at the end FL_SEQEND or FL_SEQEND_3? If excludedSubtrees 47 are absent then it's FL_SEQEND but if we're encoding the excluded 48 subtree then it's FL_SEQEND_3. Because of this ambiguity the current 49 encoding routines simply assume that once they reach the end of an 50 extension there's an implicit FL_SEQEND_whatever there. Luckily all of 51 the ambiguous decoding-level points occur at the end of extensions so 52 this is a workable way to handle things. 53 54 Decoding level flags that indicate the compliance level at which this 55 attribute is decoded. 56 57 The object subtypes for which an attribute is valid. CRLs actually 58 contain two sets of extensions, one for the entire CRL (crlExtensions) 59 and the other for each entry in the CRL (crlEntryExtension). Sorting 60 out whether we're adding a CRL extension or per-entry extension is 61 handled by the higher-level code which references the CRL attribute list 62 or per-entry attribute list as appropriate. 63 64 The total-attribute flags are: 65 66 FL_ATTR_ATTRSTART/FL_ATTR_ATTREND: Marks the start and end of an 67 attribute. This has to be done explicitly because there's no other 68 field or flag that we can guarantee will always be set for the first 69 or last field in an attribute and never for any other field. 70 71 FL_ATTR_NOCOPY: The attribute is regarded as sensitive and therefore 72 shouldn't be copied from source to destination (e.g. from a 73 certificate request into a certificate) when the other attributes 74 are copied. 75 76 FL_ATTR_CRITICAL: The overall extension is marked critical when encoding. 77 78 The encoding flags are: 79 80 FL_DEFAULT: The field has a default value that's set if no field data 81 is present. 82 83 FL_EXPLICIT: The field is explicitly tagged so instead of being en/ 84 decoded using the tag for the field it's given a second level of 85 tagging that encapsulates the field's actual tag type. 86 87 FL_IDENTIFIER: Used to mark the encapsulating SEQUENCE in fields of the 88 type: 89 90 SEQUENCE { 91 identifier OBJECT IDENTIFIER 92 data ANY DEFINED BY identifier 93 } 94 95 for which the field identified by a CRYPT_CERTINFO_xxx is the 'data' 96 field and the whole is only encoded if the data field is present. 97 98 FL_MULTIVALUED: If a cryptlib-level attribute is part of a SET OF x/ 99 SEQUENCE OF x then this flag is set to indicate that more than one 100 instance can exist at the same time. If this flag isn't set then 101 cryptlib will detect that an attribute of that type already exists 102 and refuse to allow a second instance to be added. 103 104 FL_EMPTYOK: Used for a SET/SEQUENCE consisting of nothing but OPTIONAL 105 elements to indicate that it's OK to end up with a zero-length 106 entry, by default we don't allow an empty SET/SEQUENCE since if the 107 data didn't match any of the optional elements then the decoder 108 would get stuck in an endless loop. At the moment this is OK 109 because the only time we can have an empty SEQUENCE is for the 110 basicConstraints extension, which is an entire extension for which 111 the termination point is easily detected. 112 113 FL_NONENCODING: The field is read and written but not associated with 114 any user data. This is used for fields such as version numbers that 115 aren't used for encoding user-supplied data but that must be read and 116 written when processing an attribute 117 118 FL_OPTIONAL: The field is optional. 119 120 FL_SETOF: Applied to the encapsulating SET/SEQUENCE of a SET OF x/ 121 SEQUENCE OF x to indicate that one or more inner fields may be 122 present. The field marked with FL_SETOF in the encoding/decoding 123 table is bookmarked, if all of the SET/SEQUENCE data isn't read the 124 first time through then the decoding table position is restarted 125 from the bookmark until the SET/SEQUENCE data is exhausted. 126 127 FL_SPECIALENCODING: The attribute isn't encoded as part of the standard 128 attributes but requires special-case encoding. This exists for use 129 with certificate requests to indicate that the attribute isn't 130 encoded encapsulated inside an extensionRequest but as a standalone 131 attribute, because certificate request attributes are usually 132 encapsulated inside an extensionRequest wrapper, however occasionally 133 an attribute needs to be encoded in non-encapsulated form. 134 135 In addition this is just as much an attribute flag as an encoding 136 one since it controls the encoding of an entire attribute, we group 137 it with the encoding flags mostly because there's no room for 138 expansion any more in the attribute flags */ 139 140 /* Type information and whole-attribute flags */ 141 142 #define FL_VALID_CERT 0x0001 /* Valid in a certificate */ 143 #define FL_VALID_ATTRCERT 0x0002 /* Valid in an attribute cert */ 144 #define FL_VALID_CRL 0x0004 /* Valid in a CRL */ 145 #define FL_VALID_CERTREQ 0x0008 /* Valid in a cert.request */ 146 #define FL_VALID_REVREQ 0x0010 /* Valid in a rev.request */ 147 #define FL_VALID_OCSPREQ 0x0010 /* Valid in an OCSP request */ 148 #define FL_VALID_OCSPRESP 0x0010 /* Valid in an OCSP response */ 149 150 #define FL_LEVEL_OBLIVIOUS 0x0000 /* Process at oblivious compliance level */ 151 #define FL_LEVEL_REDUCED 0x0100 /* Process at reduced compliance level */ 152 #define FL_LEVEL_STANDARD 0x0200 /* Process at standard compliance level */ 153 #define FL_LEVEL_PKIX_PARTIAL 0x0300 /* Process at partial PKIX compliance level */ 154 #define FL_LEVEL_PKIX_FULL 0x0400 /* Process at full PKIX compliance level */ 155 156 #define FL_ATTR_NOCOPY 0x1000 /* Attr.isn't copied when attrs.copied */ 157 #define FL_ATTR_CRITICAL 0x2000 /* Extension is marked critical */ 158 #define FL_ATTR_ATTRSTART 0x4000 /* Start-of-attribute marker */ 159 #define FL_ATTR_ATTREND 0x8000 /* End-of-attribute marker */ 160 161 #define FL_VALID_MASK 0x1F /* Mask for type-validity value */ 162 #define FL_LEVEL_SHIFT 8 /* Shift amount to get into range 0...n */ 163 #define FL_LEVEL_MASK 7 /* Mask for compliance level value */ 164 165 /* Encoding flags */ 166 167 #define FL_SEQEND 0x0001 /* End of constructed object */ 168 #define FL_SEQEND_2 0x0002 /* End of cons.obj + one nesting lvl.*/ 169 #define FL_SEQEND_3 0x0003 /* End of cons.obj + two nesting lvls.*/ 170 #define FL_SEQEND_4 0x0004 /* End of cons.obj + three nesting lvls.*/ 171 #define FL_SEQEND_5 0x0005 /* End of cons.obj + four nesting lvls.*/ 172 #define FL_SEQEND_6 0x0006 /* End of cons.obj + four nesting lvls.*/ 173 #define FL_SEQEND_7 0x0007 /* End of cons.obj + four nesting lvls.*/ 174 175 #define FL_SEQEND_MASK 7 /* Mask for sequence control value */ 176 177 #define FL_OPTIONAL 0x0010 /* Field is optional */ 178 #define FL_DEFAULT 0x0020 /* Field has default value */ 179 #define FL_EXPLICIT 0x0040 /* Field is explicitly tagged */ 180 #define FL_IDENTIFIER 0x0080 /* Following field contains selection OID */ 181 #define FL_SETOF 0x0100 /* Start of SET/SEQ OF values */ 182 #define FL_EMPTYOK 0x0200 /* SET/SEQ may be empty */ 183 #define FL_NONENCODING 0x0400 /* Field is a non-encoding value */ 184 #define FL_MULTIVALUED 0x0800 /* Field can occur multiple times */ 185 #define FL_SPECIALENCODING 0x1000 /* Attribute requires special-case encoding */ 186 187 /* If a constructed field is nested (for example a SEQUENCE OF SEQUENCE) 188 then the FL_SEQEND may need to denote multiple levels of unnesting. This 189 is done by using FL_SEQEND_n, the following macro can be used to extract 190 the actual level of nesting */ 191 192 #define decodeNestingLevel( value ) ( ( value ) & FL_SEQEND_MASK ) 193 194 /* In order to be able to process broken certificates we allow for 195 processing them at various levels of standards compliance. If the 196 current processing level is below that required for the extension then 197 we skip it and treat it as a blob extension */ 198 199 #define decodeComplianceLevel( value ) \ 200 ( ( ( value ) >> FL_LEVEL_SHIFT ) & FL_LEVEL_MASK ) 201 202 /* Usually the field ID for the first field in an entry (the one containing 203 the OID) is the overall attribute ID, however there are one or two 204 exceptions in which the attribute ID and field ID are the same but are 205 given in separate fields (examples of this are the altNames, which have 206 a single field ID SUBJECT/ISSUERALTNAME that applies to the attribute as 207 a whole but also to the one and only field in it. 208 209 If this happens the field ID for the attribute as a whole is given the 210 value FIELDTYPE_ID_FOLLOWS to indicate that the actual ID is present at a 211 later point, with the first field that isn't a FIELDTYPE_ID_FOLLOWS code 212 being treated as the attribute ID */ 213 214 #define FIELDID_FOLLOWS CRYPT_XATTRIBUTE_PRIVATE 215 216 /* Determine whether an attribute information entry represents the start of 217 the attribute */ 218 219 #define isAttributeStart( attributeInfoPtr ) \ 220 ( ( attributeInfoPtr )->typeInfoFlags & FL_ATTR_ATTRSTART ) 221 222 /* Determine whether an attribute information entry represents the end of 223 the attribute information table */ 224 225 #define isAttributeTableEnd( attributeInfoPtr ) \ 226 ( ( attributeInfoPtr )->oid == NULL && \ 227 ( attributeInfoPtr )->fieldID == CRYPT_IATTRIBUTE_LAST ) 228 229 /**************************************************************************** 230 * * 231 * Special-case Field-encoding Values * 232 * * 233 ****************************************************************************/ 234 235 /* Some fields have an intrinsic value but no explicitly set value (that is, 236 their mere presence communicates the information they are intended to 237 convey but the fields themselves contain no actual data). This applies 238 for fields that contain OIDs that denote certain things such as 239 certificate policies or key usage. To denote these identifier fields 240 the field type is set to FIELDTYPE_IDENTIFIER (note that we start the 241 values at -2 rather than -1, which is the CRYPT_ERROR value). When a 242 field of this type is encountered no data value is recorded but the OID 243 for the field is written to the certificate when the field is encoded. 244 The parentheses are to catch potential erroneous use in an expression */ 245 246 #define FIELDTYPE_IDENTIFIER -2 247 248 /* Some fields have no set value (these arise from ANY DEFINED BY 249 definitions) or an opaque value (typically fixed parameters for type-and- 250 value pairs). To denote these fields the field type is set to 251 FIELDTYPE_BLOB. However this causes problems with type-checking since 252 now absolutely anything can be passed in as valid data. To allow at 253 least some type-checking we provide a hint as to the general encoding of 254 the blob, which can be one of SEQUENCE, BIT STRING, or a genuine blob 255 used in ANY DEFINED BY constructions, for which we can at least check 256 that it's some sort of ASN.1 object. There are also two cases in which 257 an ANY blob is used where it'd be possible to use more specific blobs 258 for OBJECT IDENTIFIERs and GeneralNames and that's in { OID, value } 259 selection lists in which the ANY blob acts spefically as an end-of- 260 list marker as well as being just a catchall type */ 261 262 #define FIELDTYPE_BLOB_ANY -3 263 #define FIELDTYPE_BLOB_BITSTRING -4 264 #define FIELDTYPE_BLOB_SEQUENCE -5 265 266 /* When a field contains a CHOICE it can contain any one of the CHOICE 267 fields, as opposed to a FL_SETOF which can contain any of the fields that 268 follow it. Currently the only CHOICE fields contain OIDs as choices, the 269 CHOICE fieldtype indicates that the value is stored in the field itself 270 but the encoding is handled via a separate encoding table pointed to by 271 extraData that maps the value to an OID */ 272 273 #define FIELDTYPE_CHOICE -6 274 275 /* Some fields are composite fields that contain complete certificate data 276 structures. To denote these fields the field type is a special code that 277 specifies the type and the value member contains the handle or the data 278 member contains a pointer to the composite object */ 279 280 #define FIELDTYPE_DN -7 281 282 /* As an extension of the above, some fields are complex enough to require 283 complete alternative encoding tables. The most obvious one is 284 GeneralName but this is also used for some CHOICE types where the value 285 selects a particular OID or entry from an alternative encoding table. In 286 this case the extraData member is a pointer to the alternative encoding 287 table */ 288 289 #define FIELDTYPE_SUBTYPED -8 290 291 /* Another variant of FIELDTYPE_DN is one where the field can contain one of 292 a number of string types chosen from the ASN.1 string menagerie. The two 293 main classes that seem to be popular in standards are the DirectoryString, 294 { BMPString | PrintableString | TeletexString | UniversalString | 295 UTF8String } and DisplayText, { BMPString | IA5String | UTF8String | 296 VisibleString }. Rather than adding a list of the different string 297 types all marked as optional to the en/decoding tables (so that the 298 decoder stops whenever it reaches the one that matches the string value 299 being decoded) we provide a single TextString meta-type which has a 300 custom decoding routine that makes the appropriate choice between the 301 union of all of the above types */ 302 303 #define FIELDTYPE_TEXTSTRING -9 304 305 /* The last possible field type */ 306 307 #define FIELDTYPE_LAST FIELDTYPE_TEXTSTRING 308 309 /* Since there are multiple blob fields (due to the use of typing hints) we 310 need a macro to determine whether a field is a blob of any form. The 311 odd-looking range comparison below is because the fields have negative 312 values */ 313 314 #define isBlobField( field ) \ 315 ( ( field ) <= FIELDTYPE_BLOB_ANY && \ 316 ( field ) >= FIELDTYPE_BLOB_SEQUENCE ) 317 318 /**************************************************************************** 319 * * 320 * Attribute Data Structures * 321 * * 322 ****************************************************************************/ 323 324 /* The structure to store en/decoding information for an attribute field */ 325 326 typedef struct { 327 /* Information on the overall attribute. These fields are only set 328 for overall attribute definitions */ 329 const BYTE FAR_BSS *oid; /* OID for this attribute */ 330 331 /* Information on this particular field in the attribute. The fieldID 332 is the attribute type for this field or one of the FIELDTYPE_xxx 333 codes defined above, the fieldType is the field as defined (e.g. 334 SEQUENCE, INTEGER), the fieldEncodingType is the field as encoded: 0 335 if it's the same as the field type or the tag if it's a tagged field. 336 The default tagging is to use implicit tags (e.g. [ 0 ] IMPLICIT 337 SEQUENCE) with a field of type fieldType and encoding of type 338 fieldEncodedType. If FL_EXPLICIT is set then it's an explicitly 339 tagged field and both fields are used for the encoding */ 340 const CRYPT_ATTRIBUTE_TYPE fieldID; /* Magic ID for this field */ 341 #ifndef NDEBUG 342 const char *description; /* Text description */ 343 #endif /* NDEBUG */ 344 const int fieldType; /* ASN.1 tag/type for this field */ 345 const int fieldEncodedType; /* ASN.1 tag for field as encoded */ 346 347 /* General status information */ 348 const int typeInfoFlags; /* Attribute-processing */ 349 const int encodingFlags; /* Encoding flags */ 350 351 /* Information to allow validity checking for this field */ 352 const int lowRange; /* Min/max allowed if numeric/boolean */ 353 const int highRange; /* Min/max length if string */ 354 const int defaultValue; /* Default value if FL_DEFAULT set, 355 length if FIELDTYPE_BLOB */ 356 357 /* Extra data needed to process this field, either a pointer to an 358 alternative encoding table or a pointer to the validation function to 359 allow extended validity checking */ 360 const void *extraData; 361 } ATTRIBUTE_INFO; 362 363 /* When building the debug version of the code we include a text string 364 describing the field which is being processed, this makes it easier to 365 track down the point in a certificate where cryptlib finds a problem */ 366 367 #ifndef NDEBUG 368 #define DESCRIPTION( text ) text, 369 #else 370 #define DESCRIPTION( text ) 371 #endif /* NDEBUG */ 372 373 /* Attribute information flags. These are: 374 375 FLAG_BLOB: Disables all type-checking on the field, needed to handle 376 some certificates that have invalid field encodings. 377 378 FLAG_BLOB_PAYLOAD: Disables type checking on the field payload, for 379 example checking that the chars in the string are valid for the 380 given ASN.1 string type. 381 382 FLAG_CRITICAL: The extension containing the field is marked criticial. 383 384 FLAG_DEFAULTVALUE: The field has a value which is equal to the default 385 for this field, so it doesn't get encoded. This flag is set 386 during the encoding pre-processing pass. 387 388 FLAG_IGNORED: The field is recognised but was ignored at this compliance 389 level. This prevents the certificate from being rejected if the 390 field is marked critical. 391 392 FLAG_LOCKED: The attribute can't be deleted once set, needed to handle 393 fields that are added internally by cryptlib that shouldn't be 394 deleted by users once set. 395 396 FLAG_MULTIVALUED: Multiple instantiations of this field are allowed */ 397 398 #define ATTR_FLAG_NONE 0x0000 /* No flag */ 399 #define ATTR_FLAG_CRITICAL 0x0001 /* Critical cert extension */ 400 #define ATTR_FLAG_LOCKED 0x0002 /* Field can't be modified */ 401 #define ATTR_FLAG_BLOB 0x0004 /* Non-type-checked blob data */ 402 #define ATTR_FLAG_BLOB_PAYLOAD 0x0008 /* Payload is non-type-checked blob data */ 403 #define ATTR_FLAG_MULTIVALUED 0x0010 /* Multiple instances allowed */ 404 #define ATTR_FLAG_DEFAULTVALUE 0x0020 /* Field has default value */ 405 #define ATTR_FLAG_IGNORED 0x0040 /* Attribute ignored at this compl.level */ 406 #define ATTR_FLAG_MAX 0x007F /* Maximum possible flag value */ 407 408 /* When comparing attribute fields we only want to compare relevant data and 409 not incidental flags related to parsing or encoding actions. The following 410 mask defines the attribute flags that we want to compare */ 411 412 #define ATTR_FLAGS_COMPARE_MASK ( ATTR_FLAG_CRITICAL ) 413 414 /* The structure to hold a field of a certificate attribute */ 415 416 typedef struct AL { 417 /* Identification and encoding information for this attribute field or 418 attribute. This consists of the field ID for the attribute as a 419 whole (e.g. CRYPT_CERTINFO_NAMECONSTRAINTS), for the attribute field 420 (that is, one field of a full attribute, e.g. 421 CRYPT_CERTINFO_EXCLUDEDSUBTREES) and for the subfield of the attribute 422 field in the case of composite fields like GeneralNames, a pointer to 423 the sync point used when encoding the attribute, and the encoded size 424 of this field. If it's a special-case attribute field such as a blob 425 field or a field with a fixed default value that's present only for 426 encoding purposes then the attributeID and fieldID are set to special 427 values decoded by the isXXX() macros further down. The subFieldID is 428 only set if the fieldID is for a GeneralName field. 429 430 Although the field type information is contained in the 431 attributeInfoPtr it's sometimes needed before this has been set up 432 to handle special formatting requirements, for example to enable 433 special-case handling for a DN attribute field or to specify that an 434 OID needs to be decoded into its string representation before being 435 returned to the caller. Because of this we store a copy of the field 436 type information here to allow for this special processing */ 437 CRYPT_ATTRIBUTE_TYPE attributeID;/* Attribute ID */ 438 CRYPT_ATTRIBUTE_TYPE fieldID; /* Attribute field ID */ 439 CRYPT_ATTRIBUTE_TYPE subFieldID; /* Attribute subfield ID */ 440 const ATTRIBUTE_INFO *attributeInfoPtr; /* Pointer to encoding sync point */ 441 int encodedSize; /* Encoded size of this field */ 442 int fieldType; /* Attribute field type */ 443 int flags; /* Flags for this field */ 444 445 /* Sometimes a field is part of a constructed object or even a nested 446 series of constructed objects (these are always SEQUENCEs). Since 447 this is purely an encoding issue there are no attribute list entries 448 for the SEQUENCE fields so when we perform the first pass over the 449 attribute list prior to encoding we remember the lengths of the 450 SEQUENCEs for later use. Since we can have nested SEQUENCEs 451 containing a given field we store the lengths and pointers to the 452 ATTRIBUTE_INFO table entries used to encode them in a fifo with the 453 innermost one first and successive outer ones following it */ 454 ARRAY( ENCODING_FIFO_SIZE, fifoPos ) \ 455 int sizeFifo[ ENCODING_FIFO_SIZE + 2 ]; 456 /* Encoded size of SEQUENCE containing 457 this field, if present */ 458 ARRAY( ENCODING_FIFO_SIZE, fifoPos ) \ 459 const ATTRIBUTE_INFO *encodingFifo[ ENCODING_FIFO_SIZE + 2 ]; 460 /* Encoding table entry used to encode 461 this SEQUENCE */ 462 int fifoEnd; /* End of list of SEQUENCE sizes */ 463 int fifoPos; /* Current position in list */ 464 465 /* The data payload for this attribute field or attribute. If it's 466 numeric data such as a simple boolean, bitstring, or small integer, 467 we store it in the intValue member. If it's an OID or some form of 468 string we store it in the variable-length buffer */ 469 long intValue; /* Integer value for simple types */ 470 BUFFER_OPT_FIXED( valueLength ) \ 471 void *value; /* Attribute value */ 472 int valueLength; /* Attribute value length */ 473 474 /* The OID, for blob-type attributes */ 475 BYTE *oid; /* Attribute OID */ 476 477 /* The previous and next list element in the linked list of elements */ 478 struct AL *prev, *next; 479 480 /* Variable-length storage for the attribute data */ 481 DECLARE_VARSTRUCT_VARS; 482 } ATTRIBUTE_LIST; 483 484 /**************************************************************************** 485 * * 486 * Attribute Functions * 487 * * 488 ****************************************************************************/ 489 490 /* The validation function used to perform additional validation on fields */ 491 492 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \ 493 int ( *VALIDATION_FUNCTION )( const ATTRIBUTE_LIST *attributeListPtr ); 494 495 /* Look up an ATTRIBUTE_INFO entry based on an OID */ 496 497 CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \ 498 const ATTRIBUTE_INFO *oidToAttribute( IN_ENUM( ATTRIBUTE ) \ 499 const ATTRIBUTE_TYPE attributeType, 500 IN_BUFFER( oidLength ) const BYTE *oid, 501 IN_LENGTH_OID const int oidLength ); 502 503 /* Select the appropriate attribute info table for encoding/type checking */ 504 505 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \ 506 int getAttributeInfo( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType, 507 OUT const ATTRIBUTE_INFO **attributeInfoPtrPtr, 508 OUT_INT_Z int *noAttributeEntries ); 509 510 /* Get the encoded tag for a field */ 511 512 CHECK_RETVAL_RANGE( MAKE_CTAG_PRIMITIVE( 0 ), MAX_TAG ) STDC_NONNULL_ARG( ( 1 ) ) \ 513 int getFieldEncodedTag( const ATTRIBUTE_INFO *attributeInfoPtr ); 514 515 /* Get the attribute and attributeID for a field ID */ 516 517 CHECK_RETVAL_PTR \ 518 const ATTRIBUTE_INFO *fieldIDToAttribute( IN_ENUM( ATTRIBUTE ) \ 519 const ATTRIBUTE_TYPE attributeType, 520 IN_ATTRIBUTE \ 521 const CRYPT_ATTRIBUTE_TYPE fieldID, 522 IN_ATTRIBUTE_OPT \ 523 const CRYPT_ATTRIBUTE_TYPE subFieldID, 524 OUT_OPT_ATTRIBUTE_Z \ 525 CRYPT_ATTRIBUTE_TYPE *attributeID ); 526 527 /* Find the start of an attribute from an arbitrary position in an attribute 528 list */ 529 530 CHECK_RETVAL_PTR \ 531 ATTRIBUTE_LIST *findAttributeStart( IN_OPT const ATTRIBUTE_LIST *attributeListPtr ); 532 533 /* Write an attribute field */ 534 535 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \ 536 int writeAttributeField( INOUT_OPT STREAM *stream, 537 INOUT ATTRIBUTE_LIST *attributeListPtr, 538 IN_RANGE( 0, 4 ) const int complianceLevel ); 539 540 #endif /* _CERTATTR_DEFINED */ 541