24 #define MIN_SKID_SIZE 5
35 const
void *subjectDN;
36 int issuerDNsize, subjectDNsize;
38 const
void *serialNumber;
41 const
void *subjectKeyIdentifier;
43 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
45 const
void *issuerKeyIdentifier;
54 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
56 const
void *keyIdentifier;
64 #define matchDN( chainingInfo, chainInfo, type ) \
65 ( ( chainingInfo )->DNsize > 0 && \
66 ( chainingInfo )->DNsize == ( chainInfo )->type##DNsize && \
67 !memcmp( ( chainingInfo )->DN, ( chainInfo )->type##DN, \
68 ( chainInfo )->type##DNsize ) )
70 #define matchKeyID( chainingInfo, chainInfo, type ) \
71 ( ( chainingInfo )->keyIDsize > MIN_SKID_SIZE && \
72 ( chainingInfo )->keyIDsize == ( chainInfo )->type##KeyIDsize && \
73 !memcmp( ( chainingInfo )->keyIdentifier, \
74 ( chainInfo )->type##KeyIdentifier, \
75 ( chainInfo )->type##KeyIDsize ) )
77 #ifdef USE_CERTIFICATES
95 chainingInfo->DN = chainInfo->subjectDN;
96 chainingInfo->DNsize = chainInfo->subjectDNsize;
97 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
98 chainingInfo->keyIdentifier = chainInfo->subjectKeyIdentifier;
99 chainingInfo->keyIDsize = chainInfo->subjectKeyIDsize;
111 chainingInfo->DN = chainInfo->issuerDN;
112 chainingInfo->DNsize = chainInfo->issuerDNsize;
113 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
114 chainingInfo->keyIdentifier = chainInfo->issuerKeyIdentifier;
115 chainingInfo->keyIDsize = chainInfo->issuerKeyIDsize;
152 const BOOLEAN useStrictChaining )
160 if(
matchDN( chainingInfo, chainInfo, subject ) )
162 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
163 if(
matchKeyID( chainingInfo, chainInfo, subject ) )
168 if( useStrictChaining )
169 return( dnChains && keyIDchains );
172 return( dnChains || keyIDchains );
184 if(
matchDN( chainingInfo, chainInfo, issuer ) )
187 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
189 if(
matchKeyID( chainingInfo, chainInfo, issuer ) )
210 assert(
isReadPtr( attributePtrPtr,
sizeof(
void * ) ) );
211 assert(
isWritePtr( attributeLength,
sizeof(
int * ) ) );
217 *attributePtrPtr = NULL;
218 *attributeLength = 0;
223 if( attributePtr == NULL )
229 return( getAttributeDataPtr( attributePtr, (
void ** ) attributePtrPtr,
236 static
void freeCertChain(
IN_ARRAY( certChainSize ) \
239 const int certChainSize )
267 const int certChainSize )
277 memset( chainInfo, 0,
sizeof(
CHAIN_INFO ) * certChainSize );
289 (
void ** ) &certChainPtr,
294 chainInfo[ i ].subjectDN = certChainPtr->subjectDNptr;
296 chainInfo[ i ].issuerDN = certChainPtr->issuerDNptr;
298 chainInfo[ i ].serialNumber = certChainPtr->cCertCert->serialNumber;
299 chainInfo[ i ].serialNumberSize = certChainPtr->cCertCert->serialNumberLength;
300 status = getChainingAttribute( certChainPtr,
302 &chainInfo[ i ].subjectKeyIdentifier,
303 &chainInfo[ i ].subjectKeyIDsize );
309 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
310 status = getChainingAttribute( certChainPtr,
312 &chainInfo[ i ].issuerKeyIdentifier,
313 &chainInfo[ i ].issuerKeyIDsize );
322 ENSURES( i < MAX_CHAINLENGTH );
336 IN_RANGE( 1, MAX_CHAINLENGTH )
const int certChainSize )
339 BOOLEAN certUsed[ MAX_CHAINLENGTH + 8 ], moreMatches;
340 int lastCertPos, iterationCount;
344 REQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );
348 memset( certUsed, 0, MAX_CHAINLENGTH *
sizeof(
BOOLEAN ) );
349 getSubjectChainingInfo( &chainingInfo, &chainInfo[ 0 ] );
350 certUsed[ 0 ] =
TRUE;
359 for( moreMatches =
TRUE, iterationCount = 0;
374 if( !certUsed[ i ] && \
375 isIssuer( &chainingInfo, &chainInfo[ i ] ) )
377 getSubjectChainingInfo( &chainingInfo, &chainInfo[ i ] );
378 certUsed[ i ] =
TRUE;
384 ENSURES( i < MAX_CHAINLENGTH );
386 ENSURES( iterationCount < MAX_CHAINLENGTH );
388 return( lastCertPos );
396 static
int findIdentifiedLeafNode(
IN_ARRAY( certChainSize ) \
399 const int certChainSize,
406 int issuerDNsize, serialNumberSize;
410 assert(
isReadPtr( keyID, keyIDlength ) );
412 REQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );
413 REQUIRES( keyIDtype == CRYPT_IKEYID_KEYID || \
414 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
421 if( keyIDtype == CRYPT_IKEYID_KEYID )
426 chainInfo[ i ].subjectKeyIDsize == keyIDlength && \
427 !memcmp( chainInfo[ i ].subjectKeyIdentifier, keyID,
431 ENSURES( i < MAX_CHAINLENGTH );
437 sMemConnect( &stream, keyID, keyIDlength );
438 readSequence( &stream, NULL );
439 status = getStreamObjectLength( &stream, &issuerDNsize );
441 status = sMemGetDataBlock( &stream, &issuerDNptr, issuerDNsize );
444 sMemDisconnect( &stream );
447 sSkip( &stream, issuerDNsize );
448 status = readGenericHole( &stream, &serialNumberSize, 1,
BER_INTEGER );
450 status = sMemGetDataBlock( &stream, &serialNumber,
452 sMemDisconnect( &stream );
462 if( chainInfo[ i ].issuerDNsize > 0 && \
463 chainInfo[ i ].issuerDNsize == issuerDNsize && \
464 !memcmp( chainInfo[ i ].issuerDN, issuerDNptr,
466 compareSerialNumber( chainInfo[ i ].serialNumber,
467 chainInfo[ i ].serialNumberSize,
468 serialNumber, serialNumberSize ) )
471 ENSURES( i < MAX_CHAINLENGTH );
509 OUT_RANGE( 0, MAX_CHAINLENGTH )
int *orderedCertChainSize,
511 IN_RANGE( 1, MAX_CHAINLENGTH )
const int certChainSize,
512 IN_RANGE( 1, MAX_CHAINLENGTH )
const int leafCertEntry,
515 const BOOLEAN useStrictChaining )
519 BOOLEAN chainInfoValid[ MAX_CHAINLENGTH + 8 ], moreMatches;
520 const int maxMatchLevel = useStrictChaining ? 1 : 0;
521 int orderedChainIndex, iterationCount, i;
526 chainingInfo == NULL ) || \
530 REQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );
531 REQUIRES( leafCertEntry >= 0 && leafCertEntry <= certChainSize );
533 chainingInfo == NULL ) || \
535 chainingInfo != NULL ) );
538 *orderedCertChainSize = 0;
543 chainInfoValid[ i ] =
TRUE;
544 ENSURES( i < MAX_CHAINLENGTH );
545 chainInfoValid[ leafCertEntry ] =
FALSE;
552 getIssuerChainingInfo( &localChainingInfo, &chainInfo[ 0 ] );
553 orderedChain[ 0 ] = certChainStart;
554 chainInfoValid[ 0 ] =
FALSE;
555 orderedChainIndex = 1;
561 memcpy( &localChainingInfo, chainingInfo,
sizeof(
CHAINING_INFO ) );
562 orderedChainIndex = 0;
566 for( moreMatches =
TRUE, iterationCount = 0;
581 for( matchLevel = maxMatchLevel; \
582 !moreMatches && matchLevel >= 0; matchLevel-- )
587 if( !chainInfoValid[ i ] || \
588 !isSubject( &localChainingInfo, &chainInfo[ i ],
594 orderedChain[ orderedChainIndex++ ] = iCertChain[ i ];
595 getIssuerChainingInfo( &localChainingInfo, &chainInfo[ i ] );
596 chainInfoValid[ i ] =
FALSE;
600 ENSURES( i < MAX_CHAINLENGTH );
602 ENSURES( orderedChainIndex <= certChainSize && \
603 orderedChainIndex < MAX_CHAINLENGTH );
605 ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
611 if( chainInfoValid[ i ] )
614 ENSURES( i < MAX_CHAINLENGTH );
618 if( orderedChainIndex > 0 )
620 memcpy( iCertChain, orderedChain,
623 *orderedCertChainSize = orderedChainIndex;
634 IN_RANGE( 1, MAX_CHAINLENGTH )
const int certChainEnd,
642 int leafNodePos, newCertChainEnd, complianceLevel,
status;
648 keyID == NULL && keyIDlength == 0 ) || \
649 ( ( keyIDtype == CRYPT_IKEYID_KEYID || \
650 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
653 REQUIRES( certChainEnd > 0 && certChainEnd <= MAX_CHAINLENGTH );
655 keyID == NULL && keyIDlength == 0 ) || \
656 ( ( keyIDtype == CRYPT_IKEYID_KEYID || \
657 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
675 status = buildChainInfo( chainInfo, iCertChain, certChainEnd );
680 leafNodePos = findIdentifiedLeafNode( chainInfo, certChainEnd,
681 keyIDtype, keyID, keyIDlength );
684 leafNodePos = findLeafNode( chainInfo, certChainEnd );
686 return( leafNodePos );
687 ENSURES( leafNodePos >= 0 && leafNodePos < certChainEnd );
690 *iLeafCert = iCertChain[ leafNodePos ];
691 getIssuerChainingInfo( &chainingInfo, &chainInfo[ leafNodePos ] );
695 status = sortCertChain( iCertChain, &newCertChainEnd, chainInfo,
701 if( newCertChainEnd <= 0 )
710 #ifdef USE_CERTLEVEL_PKIX_FULL
739 (
void ** ) &certInfoPtr,
747 ENSURES( i < MAX_CHAINLENGTH );
754 (
void ** ) &certChainPtr,
758 memcpy( certChainPtr->cCertCert->chain, iCertChain,
760 certChainPtr->cCertCert->chainEnd = newCertChainEnd;
779 IN_RANGE( 0, MAX_CHAINLENGTH )
const int certChainLen,
788 REQUIRES_B( certChainLen >= 0 && certChainLen <= MAX_CHAINLENGTH );
807 if( !memcmp( certChainHashes[ i ],
808 certChainHashes[ certChainLen ], msgData.
length ) )
833 const int oldChainEnd = destCertChainInfo->
chainEnd;
849 if( isCertCollection )
863 ENSURES( i < MAX_CHAINLENGTH );
870 (
void ** ) &chainCertInfoPtr,
874 srcCertChainInfo = chainCertInfoPtr->cCertCert;
875 if( !isCertCollection || \
876 !isCertPresent( certChainHashes, destCertChainInfo->
chainEnd, \
879 if( destCertChainInfo->
chainEnd >= MAX_CHAINLENGTH )
885 destCertChainInfo->chain[ destCertChainInfo->
chainEnd++ ] = iChainCert;
898 if( isCertCollection && \
899 isCertPresent( certChainHashes, destCertChainInfo->
chainEnd,
900 srcCertChainInfo->chain[ i ] ) )
904 if( destCertChainInfo->
chainEnd >= MAX_CHAINLENGTH )
910 destCertChainInfo->chain[ destCertChainInfo->
chainEnd++ ] = iCopyCert;
912 ENSURES( i < MAX_CHAINLENGTH );
913 srcCertChainInfo = NULL;
920 DEBUG_DIAG((
"Maximum chain length %d exceeded", MAX_CHAINLENGTH ));
924 if( destCertChainInfo->
chainEnd > oldChainEnd )
926 freeCertChain( &destCertChainInfo->chain[ oldChainEnd ],
927 destCertChainInfo->
chainEnd - oldChainEnd );
938 if( isCertCollection )
947 if( oldChainEnd <= 0 )
956 status = buildChainInfo( chainInfo, destCertChainInfo->chain,
961 if( destCertChainInfo->
chainEnd > oldChainEnd )
963 freeCertChain( &destCertChainInfo->chain[ oldChainEnd ],
964 destCertChainInfo->
chainEnd - oldChainEnd );
969 return( sortCertChain( destCertChainInfo->chain, &destCertChainInfo->
chainEnd,
971 iChainCert, NULL,
FALSE ) );
983 static
int readCertChainWrapper(
INOUT STREAM *stream )
995 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
999 readConstructed( stream, NULL, 0 );
1000 readSequence( stream, NULL );
1007 status = readSet( stream, &length );
1010 if( integer < 1 || integer > 3 )
1013 sSkip( stream, length );
1023 readSequenceI( stream, &length );
1024 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
1043 return( readUniversal( stream ) );
1049 status = checkEOC( stream );
1052 if( status ==
FALSE )
1060 status = readConstructedI( stream, &innerLength, 0 );
1065 return( sSkip( stream, innerLength ) );
1079 const BOOLEAN isIndefiniteLength )
1089 type == CRYPT_ICERTTYPE_CMS_CERTSET || \
1090 type == CRYPT_ICERTTYPE_SSL_CERTCHAIN );
1097 if( type == CRYPT_ICERTTYPE_SSL_CERTCHAIN )
1099 status = sSkip( stream, 3 );
1105 status = getStreamObjectLength( stream, &length );
1117 if( type == CRYPT_ICERTTYPE_SSL_CERTCHAIN )
1120 int complianceLevel;
1129 status = sMemGetDataBlock( stream, &certDataPtr, length );
1132 checkObjectEncoding( certDataPtr, length ) ) )
1146 status = importCertFromStream( stream, iCryptCert, iCryptOwner,
1148 CRYPT_ICERTTYPE_DATAONLY : \
1156 if( isIndefiniteLength )
1158 status = checkEOC( stream );
1165 if( status ==
TRUE )
1189 int iterationCount,
status;
1194 keyIDlength == 0 ) || \
1195 ( ( keyIDtype == CRYPT_IKEYID_KEYID || \
1196 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
1203 type == CRYPT_ICERTTYPE_CMS_CERTSET || \
1204 type == CRYPT_ICERTTYPE_SSL_CERTCHAIN );
1206 keyID == NULL && keyIDlength == 0 ) || \
1207 ( ( keyIDtype == CRYPT_IKEYID_KEYID || \
1208 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
1219 status = readCertChainWrapper( stream );
1224 case CRYPT_ICERTTYPE_CMS_CERTSET:
1225 status = readConstructedI( stream, &certSequenceLength, 0 );
1228 case CRYPT_ICERTTYPE_SSL_CERTCHAIN:
1232 certSequenceLength = sMemDataLeft( stream );
1244 endPos = stell( stream ) + certSequenceLength;
1253 for( iterationCount = 0;
1256 iterationCount < FAILSAFE_ITERATIONS_MED;
1262 if( certChainEnd >= MAX_CHAINLENGTH )
1264 freeCertChain( iCertChain, certChainEnd );
1269 status = readSingleCert( stream, &iNewCert, iCryptOwner, type,
1275 if( certChainEnd > 0 )
1276 freeCertChain( iCertChain, certChainEnd );
1279 iCertChain[ certChainEnd++ ] = iNewCert;
1283 ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
1287 if( certChainEnd <= 0 )
1291 status = buildCertChain( iCryptCert, iCertChain, certChainEnd,
1292 keyIDtype, keyID, keyIDlength );
1295 freeCertChain( iCertChain, certChainEnd );
1309 IN_BUFFER( keyIDlength )
const void *keyID,
1317 int iterationCount,
status;
1320 assert(
isReadPtr( keyID, keyIDlength ) && \
1334 &stateInfo,
sizeof(
int ),
1340 iCertChain[ 0 ] = lastCert = getnextcertInfo.
cryptHandle;
1348 &stateInfo,
sizeof(
int ), chainOptions );
1349 for( iterationCount = 0;
1382 if( certChainEnd >= MAX_CHAINLENGTH )
1390 iCertChain[ certChainEnd++ ] = lastCert = getnextcertInfo.
cryptHandle;
1392 ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
1395 freeCertChain( iCertChain, certChainEnd );
1400 status = buildCertChain( iCertificate, iCertChain, certChainEnd,
1404 freeCertChain( iCertChain, certChainEnd );
1425 static
int sizeofCertPath(
const CERT_INFO *certInfoPtr,
1433 assert(
isWritePtr( certPathLength,
sizeof(
int ) ) );
1434 assert( certSizeInfo == NULL || \
1435 isWritePtr( certSizeInfo,
sizeof(
int ) * MAX_CHAINLENGTH ) );
1438 *certPathLength = 0;
1439 if( certSizeInfo != NULL )
1440 memset( certSizeInfo, 0,
sizeof(
int ) * MAX_CHAINLENGTH );
1449 if( certSizeInfo != NULL )
1463 length += msgData.
length;
1464 if( certSizeInfo != NULL )
1466 certSizeInfo[ i ] = msgData.
length;
1470 ENSURES( i < MAX_CHAINLENGTH );
1471 *certPathLength =
length;
1480 const int *certSizeInfo )
1488 assert( certSizeInfo == NULL || \
1489 isReadPtr( certSizeInfo,
sizeof(
int ) * MAX_CHAINLENGTH ) );
1497 if( certSizeInfo != NULL )
1502 status = swrite( stream, certInfoPtr->certificate,
1509 if( certSizeInfo != NULL )
1512 writeUint16( stream, certSizeInfo[ i ] );
1514 status = exportCertToStream( stream, certChainInfo->chain[ i ],
1517 ENSURES( i < MAX_CHAINLENGTH );
1540 int sizeofCertCollection(
const CERT_INFO *certInfoPtr,
1548 REQUIRES( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \
1549 certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \
1550 certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );
1556 if( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN )
1558 int certSizeInfo[ MAX_CHAINLENGTH + 8 ];
1560 status = sizeofCertPath( certInfoPtr, &length, certSizeInfo );
1565 status = sizeofCertPath( certInfoPtr, &length, NULL );
1568 status = length = sizeofObject( length );
1581 int certSizeInfo[ MAX_CHAINLENGTH + 8 ];
1582 int *certSizePtr = \
1583 ( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN ) ? \
1584 certSizeInfo : NULL;
1585 int certCollectionLength,
status;
1590 REQUIRES( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \
1591 certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \
1592 certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );
1594 status = sizeofCertPath( certInfoPtr, &certCollectionLength,
1598 switch( certFormatType )
1600 case CRYPT_ICERTFORMAT_CERTSET:
1601 writeConstructed( stream, certCollectionLength, 0 );
1604 case CRYPT_ICERTFORMAT_CERTSEQUENCE:
1605 writeSequence( stream, certCollectionLength );
1608 case CRYPT_ICERTFORMAT_SSL_CERTCHAIN:
1614 return( writeCertPath( stream, certInfoPtr, certSizePtr ) );
1621 int certSetLength, innerLength,
status;
1626 status = sizeofCertPath( certInfoPtr, &certSetLength, NULL );
1633 (
int ) sizeofObject( certSetLength ) + \
1634 ( int ) sizeofObject( 0 );
1637 writeSequence( stream,
1639 (
int ) sizeofObject( sizeofObject( innerLength ) ) );
1641 writeConstructed( stream, sizeofObject( innerLength ), 0 );
1642 writeSequence( stream, innerLength );
1646 writeSet( stream, 0 );
1649 writeConstructed( stream, certSetLength, 0 );
1650 status = writeCertPath( stream, certInfoPtr, NULL );
1652 status = writeSet( stream, 0 );