cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ext_copy.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Certificate Attribute Copy Routines *
4 * Copyright Peter Gutmann 1996-2008 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "cert.h"
10  #include "certattr.h"
11  #include "asn1.h"
12 #else
13  #include "cert/cert.h"
14  #include "cert/certattr.h"
15  #include "enc_dec/asn1.h" /* For sizeofOID() */
16 #endif /* Compiler-specific includes */
17 
18 /* When replicating attributes from one type of certificate object to
19  another (for example from an issuer certificate to a subject certificate
20  when issuing a new certificate) we may have to adjust the attribute
21  information based on the source and destination object roles. The
22  following values denote the different copy types that we have to handle.
23  Usually this is a direct copy, however if we're copying from subject to
24  issuer we have to adjust attribute IDs such as the altName
25  (subjectAltName -> issuerAltName), if we're copying from issuer to
26  subject we have to adjust path length-based contraints since the new
27  subject is one further down the chain than the issuer */
28 
29 typedef enum {
30  COPY_NONE, /* No copy type */
31  COPY_DIRECT, /* Direct attribute copy */
32  COPY_SUBJECT_TO_ISSUER, /* Copy of subject attributes to issuer cert */
33  COPY_ISSUER_TO_SUBJECT, /* Copy of issuer attributes to subject cert */
34  COPY_LAST /* Last valid copy type */
35  } COPY_TYPE;
36 
37 #ifdef USE_CERTIFICATES
38 
39 /****************************************************************************
40 * *
41 * Utility Functions *
42 * *
43 ****************************************************************************/
44 
45 /* Copy an attribute field */
46 
47 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
48 static int copyAttributeField( OUT_OPT_PTR ATTRIBUTE_LIST **destAttributeField,
49  const ATTRIBUTE_LIST *srcAttributeField )
50  {
51  ATTRIBUTE_LIST *newElement;
52  int status = CRYPT_OK;
53 
54  assert( isWritePtr( destAttributeField, sizeof( ATTRIBUTE_LIST * ) ) );
55  assert( isReadPtr( srcAttributeField, sizeof( ATTRIBUTE_LIST ) ) );
56 
57  /* Allocate memory for the new element and copy the information across */
58  *destAttributeField = NULL;
59  if( ( newElement = ( ATTRIBUTE_LIST * ) \
60  clAlloc( "copyAttributeField", \
61  sizeofVarStruct( srcAttributeField, \
62  ATTRIBUTE_LIST ) ) ) == NULL )
63  return( CRYPT_ERROR_MEMORY );
64  copyVarStruct( newElement, srcAttributeField, ATTRIBUTE_LIST );
65  if( srcAttributeField->fieldType == FIELDTYPE_DN )
66  {
67  /* If the field contains a DN, copy that across as well */
68  status = copyDN( ( DN_PTR ** ) &newElement->value,
69  srcAttributeField->value );
70  if( cryptStatusError( status ) )
71  {
72  endVarStruct( newElement, ATTRIBUTE_LIST );
73  clFree( "copyAttributeField", newElement );
74  return( status );
75  }
76  }
77  newElement->next = newElement->prev = NULL;
78  *destAttributeField = newElement;
79 
80  return( CRYPT_OK );
81  }
82 
83 /* Copy an attribute from one attribute list to another */
84 
85 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
86 static int copyAttribute( INOUT_PTR ATTRIBUTE_LIST **destListHeadPtr,
88  IN_ENUM( COPY ) const COPY_TYPE copyType )
89  {
90  const CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
91  CRYPT_ATTRIBUTE_TYPE newAttributeID = attributeID;
92  ATTRIBUTE_LIST *newAttributeListHead = NULL;
93  ATTRIBUTE_LIST *newAttributeListTail = DUMMY_INIT_PTR;
94  ATTRIBUTE_LIST *insertPoint, *prevElement = NULL;
95  int iterationCount;
96 
97  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
98  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
99 
100  REQUIRES( copyType > COPY_NONE && copyType < COPY_LAST );
101 
102  /* If we're re-mapping the destination attribute ID (see the comment
103  further down) we have to insert it at a point corresponding to the
104  re-mapped ID, not the original ID, to maintain the list's sorted
105  property. The CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER is only
106  copied at CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL or above so we'll never
107  see this attribute copied at lower compliance levels (this is
108  enforced in the caller) */
109  if( copyType == COPY_SUBJECT_TO_ISSUER )
110  {
111  if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
112  newAttributeID = CRYPT_CERTINFO_ISSUERALTNAME;
113  if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
114  newAttributeID = CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
115  }
116 
117  /* Find the location at which to insert this attribute (this assumes
118  that the fieldIDs are defined in sorted order) */
119  for( insertPoint = *destListHeadPtr, iterationCount = 0;
120  insertPoint != NULL && \
121  insertPoint->attributeID < newAttributeID && \
122  insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \
123  iterationCount < FAILSAFE_ITERATIONS_LARGE;
124  insertPoint = insertPoint->next, iterationCount++ )
125  {
126  prevElement = insertPoint;
127  }
128  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
129  insertPoint = prevElement;
130 
131  /* Build a new attribute list containing the attribute fields */
132  for( iterationCount = 0;
133  srcListPtr != NULL && srcListPtr->attributeID == attributeID && \
134  iterationCount < FAILSAFE_ITERATIONS_LARGE;
135  iterationCount++ )
136  {
137  ATTRIBUTE_LIST *newAttributeField;
138  int status;
139 
140  /* Copy the field across */
141  status = copyAttributeField( &newAttributeField, srcListPtr );
142  if( cryptStatusError( status ) )
143  {
144  deleteAttributes( ( ATTRIBUTE_PTR ** ) &newAttributeListHead );
145  return( status );
146  }
147 
148  /* If we're copying from an issuer to a subject attribute list and
149  the field is an altName or keyIdentifier, change the field type
150  from issuer.subjectAltName to subject.issuerAltName or
151  issuer.subjectKeyIdentifier to subject.authorityKeyIdentifier */
152  if( copyType == COPY_SUBJECT_TO_ISSUER )
153  {
154  if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
155  {
156  newAttributeField->attributeID = \
157  newAttributeField->fieldID = \
158  CRYPT_CERTINFO_ISSUERALTNAME;
159  }
160  if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
161  {
162  newAttributeField->attributeID = \
163  CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
164  newAttributeField->fieldID = \
165  CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER;
166  }
167  }
168 
169  /* If we're copying from a subject to an issuer attribute list and
170  it's a path length-based constraint, adjust the constraint value
171  by one since we're now one further down the chain */
172  if( copyType == COPY_ISSUER_TO_SUBJECT && \
173  ( newAttributeField->fieldID == \
175  newAttributeField->fieldID == \
177  newAttributeField->fieldID == \
179  {
180  /* If we're already at a path length of zero we can't reduce it
181  any further, the best that we can do is to not copy the
182  attribute */
183  if( newAttributeField->intValue <= 0 )
184  {
185  deleteAttributeField( ( ATTRIBUTE_PTR ** ) &newAttributeField,
186  NULL, newAttributeField, NULL );
187  }
188  else
189  newAttributeField->intValue--;
190  }
191 
192  /* Append the new field to the new attribute list */
193  insertDoubleListElement( &newAttributeListHead, newAttributeListTail,
194  newAttributeField );
195  newAttributeListTail = newAttributeField;
196 
197  /* Move on to the next field */
198  srcListPtr = srcListPtr->next;
199  }
200  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
201  ENSURES( newAttributeListHead != NULL );
202 
203  /* Link the new list into the existing list at the appropriate position */
204  insertDoubleListElements( destListHeadPtr, insertPoint,
205  newAttributeListHead, newAttributeListTail );
206 
207  return( CRYPT_OK );
208  }
209 
210 /* Copy a length constraint from an issuer CA certificate to a subject CA
211  certificate, decrementing the value by one */
212 
213 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
214 static int copyLengthConstraint( INOUT ATTRIBUTE_LIST **destListHeadPtr,
215  const ATTRIBUTE_LIST *srcListPtr,
217  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
218  CRYPT_ATTRIBUTE_TYPE *errorLocus )
219 
220  {
221  ATTRIBUTE_LIST *destListPtr;
222  int status;
223 
224  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
225  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
226  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
227 
228  REQUIRES( fieldID > CRYPT_ATTRIBUTE_NONE && \
229  fieldID < CRYPT_ATTRIBUTE_LAST );
230 
231  /* If there's nothing to copy, we're done */
232  srcListPtr = findAttributeField( srcListPtr, fieldID,
234  if( srcListPtr == NULL )
235  return( CRYPT_OK );
236 
237  /* There's a length constraint present, if the value is already at zero
238  then the next certificate must be an EE certificate rather than a
239  CA certificate */
240  if( srcListPtr->intValue <= 0 )
241  {
242  *errorLocus = fieldID;
243  return( CRYPT_ERROR_INVALID );
244  }
245 
246  /* There's something to copy, if it's not already present in the
247  destination just copy it across */
248  destListPtr = findAttributeField( *destListHeadPtr, fieldID,
250  if( destListPtr == NULL )
251  {
252  status = copyAttributeField( destListHeadPtr, srcListPtr );
253  if( cryptStatusError( status ) )
254  return( status );
255  destListPtr = findAttributeField( *destListHeadPtr, fieldID,
257  ENSURES( destListPtr != NULL && destListPtr->intValue > 0 );
258  destListPtr->intValue--;
259 
260  return( CRYPT_OK );
261  }
262 
263  /* The same constraint exists in source and destination, set the result
264  value to the lesser of the two, with the necessary decrement applied */
265  if( srcListPtr->intValue <= destListPtr->intValue )
266  destListPtr->intValue = srcListPtr->intValue - 1;
267  ENSURES( destListPtr->intValue >= 0 );
268 
269  return( CRYPT_OK );
270  }
271 
272 /****************************************************************************
273 * *
274 * Copy a Complete Attribute List *
275 * *
276 ****************************************************************************/
277 
278 /* Copy a complete attribute list */
279 
280 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
281 int copyAttributes( INOUT ATTRIBUTE_PTR **destHeadPtr,
282  const ATTRIBUTE_PTR *srcPtr,
283  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
284  CRYPT_ATTRIBUTE_TYPE *errorLocus,
285  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
286  CRYPT_ERRTYPE_TYPE *errorType )
287  {
288  const ATTRIBUTE_LIST *srcListPtr = ( ATTRIBUTE_LIST * ) srcPtr;
289  int iterationCount;
290 
291  assert( isWritePtr( destHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
292  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
293  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
294  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
295 
296  /* If there are destination attributes present make a first pass down
297  the list checking that the attribute to copy isn't already present in
298  the destination attributes, first for recognised attributes and then
299  for unrecognised ones. We have to do this separately since once we
300  begin the copy process it's rather hard to undo it. There are two
301  special cases that we could in theory allow:
302 
303  1. Some composite attributes could have non-overlapping fields in
304  the source and destination.
305 
306  2. Some attributes can have multiple instances of a field present.
307 
308  This means that we could allow them to appear in both the source and
309  destination lists, however if this occurs it's more likely to be an
310  error than a desire to merge two disparate collections of fields or
311  attributes so we report them as (disallowed) duplicates */
312  if( *destHeadPtr != NULL )
313  {
315 
316  /* Check the non-blob attributes */
317  for( attributeListCursor = srcListPtr, iterationCount = 0;
318  attributeListCursor != NULL && \
319  !checkAttributeProperty( attributeListCursor,
321  iterationCount < FAILSAFE_ITERATIONS_LARGE;
322  attributeListCursor = attributeListCursor->next, iterationCount++ )
323  {
324  ENSURES( attributeListCursor->next == NULL || \
325  !isValidAttributeField( attributeListCursor->next ) || \
326  attributeListCursor->attributeID <= \
327  attributeListCursor->next->attributeID );
328  if( findAttributeField( *destHeadPtr,
329  attributeListCursor->fieldID,
330  CRYPT_ATTRIBUTE_NONE ) != NULL )
331  {
332  *errorLocus = attributeListCursor->fieldID;
333  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
334  return( CRYPT_ERROR_DUPLICATE );
335  }
336  }
337  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
338 
339  /* Check the blob attributes */
340  for( ; attributeListCursor != NULL && \
341  iterationCount < FAILSAFE_ITERATIONS_LARGE;
342  attributeListCursor = attributeListCursor->next, iterationCount++ )
343  {
344  ENSURES( checkAttributeProperty( attributeListCursor,
346  if( findAttributeByOID( *destHeadPtr,
347  attributeListCursor->oid,
348  sizeofOID( attributeListCursor->oid ) ) != NULL )
349  {
350  /* We can't set the locus for blob-type attributes since
351  it's not a known attribute */
352  *errorLocus = CRYPT_ATTRIBUTE_NONE;
353  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
354  return( CRYPT_ERROR_DUPLICATE );
355  }
356  }
357  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
358  }
359 
360  /* Make a second pass copying everything across, first the non-blob
361  attributes */
362  for( iterationCount = 0;
363  srcListPtr != NULL && \
364  !checkAttributeProperty( srcListPtr,
366  iterationCount < FAILSAFE_ITERATIONS_LARGE;
367  iterationCount++ )
368  {
369  CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
370  const ATTRIBUTE_INFO *attributeInfoPtr;
371  int status;
372 
373  /* Get the attribute information for the attribute to be copied */
374  if( srcListPtr->attributeInfoPtr != NULL )
375  attributeInfoPtr = srcListPtr->attributeInfoPtr;
376  else
377  {
378  attributeInfoPtr = \
379  fieldIDToAttribute( ( attributeID >= CRYPT_CERTINFO_FIRST_CMS ) ? \
381  attributeID, CRYPT_ATTRIBUTE_NONE, NULL );
382  }
383  ENSURES( attributeInfoPtr != NULL );
384 
385  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
386 
387  /* Copy the complete attribute across unless it's one that we
388  explicitly don't propagate from source to destination */
389  if( !( attributeInfoPtr->typeInfoFlags & FL_ATTR_NOCOPY ) )
390  {
391  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destHeadPtr,
392  srcListPtr, COPY_DIRECT );
393  if( cryptStatusError( status ) )
394  return( status );
395  }
396 
397  /* Move on to the next attribute. We retain the loop bounds-check
398  value from the outer loop to bound it at n rather than 2*n */
399  for( ;
400  srcListPtr != NULL && \
401  srcListPtr->attributeID == attributeID && \
402  iterationCount < FAILSAFE_ITERATIONS_LARGE;
403  srcListPtr = srcListPtr->next, iterationCount++ );
404  }
405  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
406 
407  /* If there are blob-type attributes left at the end of the list, copy
408  them across last */
409  if( srcListPtr != NULL )
410  {
411  ATTRIBUTE_LIST *insertPoint;
412 
413  /* Find the end of the destination list */
414  for( insertPoint = *destHeadPtr, iterationCount = 0;
415  insertPoint != NULL && insertPoint->next != NULL && \
416  iterationCount < FAILSAFE_ITERATIONS_LARGE;
417  insertPoint = insertPoint->next, iterationCount++ );
418  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
419 
420  /* Copy all remaining attributes across */
421  for( ; srcListPtr != NULL && \
422  iterationCount < FAILSAFE_ITERATIONS_LARGE;
423  srcListPtr = srcListPtr->next, iterationCount++ )
424  {
425  ATTRIBUTE_LIST *newAttribute;
426  int status;
427 
428  status = copyAttributeField( &newAttribute, srcListPtr );
429  if( cryptStatusError( status ) )
430  return( status );
431  insertDoubleListElement( ( ATTRIBUTE_LIST ** ) destHeadPtr,
432  insertPoint, newAttribute );
433 
434  }
435  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
436  }
437 
438  return( CRYPT_OK );
439  }
440 
441 /****************************************************************************
442 * *
443 * Copy Specific Attributes *
444 * *
445 ****************************************************************************/
446 
447 /* Copy attributes that are propagated down certificate chains from an
448  issuer to a subject certificate, changing the field types from subject
449  to issuer and adjusting constraint values at the same time if required */
450 
451 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
452 int copyIssuerAttributes( INOUT ATTRIBUTE_PTR **destListHeadPtr,
453  const ATTRIBUTE_PTR *srcListPtr,
455  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
456  CRYPT_ATTRIBUTE_TYPE *errorLocus,
457  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
458  CRYPT_ERRTYPE_TYPE *errorType )
459  {
461  int status = CRYPT_OK;
462 
463  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
464  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
465  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
466  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
467 
469 
470  /* If the destination is a CA certificate and the source has constraint
471  extensions, copy them over to the destination. The reason why we
472  copy the constraints even though they're already present in the
473  source is to ensure that they're still present in a certificate chain
474  even if the parent isn't available. This can occur for example when
475  a chain-internal certificate is marked as implicitly trusted and the
476  chain is only available up to the implicitly-trusted certificate with
477  the contraint-imposing parent not present */
478  attributeListPtr = findAttributeField( *destListHeadPtr,
481  if( attributeListPtr != NULL && attributeListPtr->intValue > 0 )
482  {
483 #ifdef USE_CERTLEVEL_PKIX_FULL
484  ATTRIBUTE_LIST *srcPermittedSubtrees, *srcExcludedSubtrees;
485 
486  srcPermittedSubtrees = findAttributeField( srcListPtr,
489  srcExcludedSubtrees = findAttributeField( srcListPtr,
492 
493  /* If we're copying permitted or excluded subtrees they can't
494  already be present. We check the two separately rather than just
495  checking for the overall presence of name constraints since in
496  theory it's possible to merge permitted and excluded constraints,
497  so that permitted constraints in the destination don't clash with
498  excluded constraints in the source (yet another one of X.509's
499  semantic holes) */
500  if( srcPermittedSubtrees != NULL && \
501  findAttributeField( *destListHeadPtr, \
503  CRYPT_ATTRIBUTE_NONE ) != NULL )
504  {
505  *errorLocus = CRYPT_CERTINFO_PERMITTEDSUBTREES;
506  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
507  return( CRYPT_ERROR_DUPLICATE );
508  }
509  if( srcExcludedSubtrees != NULL && \
510  findAttributeField( *destListHeadPtr, \
512  CRYPT_ATTRIBUTE_NONE ) != NULL )
513  {
514  *errorLocus = CRYPT_CERTINFO_EXCLUDEDSUBTREES;
515  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
516  return( CRYPT_ERROR_DUPLICATE );
517  }
518 
519  /* Copy the fields across */
520  if( srcPermittedSubtrees != NULL )
521  {
522  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
523  srcPermittedSubtrees,
525  if( cryptStatusError( status ) )
526  return( status );
527  }
528  if( srcExcludedSubtrees != NULL )
529  {
530  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
531  srcExcludedSubtrees,
533  if( cryptStatusError( status ) )
534  return( status );
535  }
536 
537  /* The path-length constraints are a bit easier to handle, if
538  they're already present we just use the smaller of the two */
539  status = copyLengthConstraint( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
540  srcListPtr,
542  errorLocus );
543  if( cryptStatusOK( status ) )
544  status = copyLengthConstraint( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
545  srcListPtr,
547  errorLocus );
548  if( cryptStatusError( status ) )
549  {
550  *errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
551  return( status );
552  }
553 #endif /* USE_CERTLEVEL_PKIX_FULL */
554 
555  /* Finally, copy the CA basic constraints across */
556  status = copyLengthConstraint( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
557  srcListPtr,
559  errorLocus );
560  if( cryptStatusError( status ) )
561  {
562  *errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
563  return( status );
564  }
565  }
566 
567  /* If it's an attribute certificate, that's all that we can copy */
568  if( type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
569  return( CRYPT_OK );
570 
571  /* Copy the altName and keyIdentifier if these are present. We don't
572  have to check for their presence in the destination certificate since
573  they're read-only fields and can't be added by the user. The
574  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER becomes the
575  CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER when copied from the issuer to
576  the subject so we only copy it at a compliance level of
577  CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL or above, since it's not enforced
578  below that level */
579  attributeListPtr = findAttribute( srcListPtr,
581  TRUE );
582  if( attributeListPtr != NULL )
583  {
584  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
585  attributeListPtr, COPY_SUBJECT_TO_ISSUER );
586  if( cryptStatusError( status ) )
587  return( status );
588  }
589 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
590  attributeListPtr = findAttribute( srcListPtr,
592  TRUE );
593  if( attributeListPtr != NULL )
594  {
595  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
596  attributeListPtr, COPY_SUBJECT_TO_ISSUER );
597  if( cryptStatusError( status ) )
598  return( status );
599  }
600 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
601 
602  /* Copy the authorityInfoAccess if it's present. This one is a bit
603  tricky both because it's a multi-valued attribute and some values
604  may already be present in the destination certificate and because
605  it's not certain that the issuer certificate's AIA should be the same
606  as the subject certificate's AIA. At the moment with monolithic CAs
607  (i.e. ones that control all the certificates down to the EE) this is
608  always the case and if it isn't then it's assumed that the CA will
609  set the EE's AIA to the appropriate value before trying to sign the
610  certificate. Because of this we copy the issuer AIA if there's no
611  subject AIA present, otherwise we assume that the CA has set the
612  subject AIA to its own choice of value and don't try and copy
613  anything */
614  attributeListPtr = findAttribute( srcListPtr,
616  if( attributeListPtr != NULL && \
617  findAttribute( *destListHeadPtr,
619  {
620  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
621  attributeListPtr, COPY_SUBJECT_TO_ISSUER );
622  if( cryptStatusError( status ) )
623  return( status );
624  }
625 
626  return( CRYPT_OK );
627  }
628 
629 #ifdef USE_CERTREQ
630 
631 /* Copy attributes that are propagated from a CRMF certificate request
632  template to the issued certificate */
633 
634 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
635 int copyCRMFRequestAttributes( INOUT ATTRIBUTE_PTR **destListHeadPtr,
636  const ATTRIBUTE_PTR *srcListPtr )
637  {
639  int status;
640 
641  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
642  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
643 
644  /* Copy the altName across, needed for the additional identification
645  that it provides */
646  attributeListPtr = findAttribute( srcListPtr,
648  TRUE );
649  if( attributeListPtr != NULL )
650  {
651  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
652  attributeListPtr, COPY_DIRECT );
653  if( cryptStatusError( status ) )
654  return( status );
655  }
656 
657  return( CRYPT_OK );
658  }
659 #endif /* USE_CERTREQ */
660 
661 #if defined( USE_CERTVAL ) || defined( USE_CERTREV )
662 
663 /* Copy attributes that are propagated from an RTCS or OCSP request to a
664  response. Since only one attribute, the nonce, is copied across we can
665  use the same function for both operations */
666 
667 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
668 int copyRTCSRequestAttributes( INOUT ATTRIBUTE_PTR **destListHeadPtr,
669  const ATTRIBUTE_PTR *srcListPtr )
670  {
672 
673  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
674  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
675 
676  /* If the nonce attribute is already present in the destination, delete
677  it */
678  attributeListPtr = findAttributeField( *destListHeadPtr,
680  if( attributeListPtr != NULL )
681  deleteAttributeField( destListHeadPtr, NULL, attributeListPtr, NULL );
682 
683  /* Copy the nonce attribute from the source to the destination. We don't
684  copy anything else (i.e. we default to deny-all) to prevent the
685  requester from being able to insert arbitrary attributes into the
686  response */
687  attributeListPtr = findAttributeField( srcListPtr,
689  if( attributeListPtr != NULL )
690  {
691  return( copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
692  attributeListPtr, COPY_DIRECT ) );
693  }
694 
695  return( CRYPT_OK );
696  }
697 #endif /* USE_CERTVAL || USE_CERTREV */
698 
699 #ifdef USE_CERTREV
700 
701 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
702 int copyOCSPRequestAttributes( INOUT ATTRIBUTE_PTR **destListHeadPtr,
703  const ATTRIBUTE_PTR *srcListPtr )
704  {
705  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
706  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
707 
708  return( copyRTCSRequestAttributes( destListHeadPtr, srcListPtr ) );
709  }
710 
711 /* Copy attributes that are propagated from a revocation request to a CRL */
712 
713 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
714 int copyRevocationAttributes( INOUT ATTRIBUTE_PTR **destListHeadPtr,
715  const ATTRIBUTE_PTR *srcListPtr )
716  {
718  int status;
719 
720  assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
721  assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
722 
723  /* Copy the CRL reason and invalidity date attributes from the source to
724  the destination. We don't copy anything else (i.e. we default to
725  deny-all) to prevent the requester from being able to insert arbitrary
726  attributes into the CRL */
727  attributeListPtr = findAttribute( srcListPtr,
729  if( attributeListPtr != NULL )
730  {
731  status = copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
732  attributeListPtr, COPY_DIRECT );
733  if( cryptStatusError( status ) )
734  return( status );
735  }
736  attributeListPtr = findAttribute( srcListPtr,
738  if( attributeListPtr != NULL )
739  {
740  return( copyAttribute( ( ATTRIBUTE_LIST ** ) destListHeadPtr,
741  attributeListPtr, COPY_DIRECT ) );
742  }
743 
744  return( CRYPT_OK );
745  }
746 #endif /* USE_CERTREV */
747 #endif /* USE_CERTIFICATES */