1 /****************************************************************************
2 * *
3 * Certificate Write Preparation Routines *
4 * Copyright Peter Gutmann 1996-2008 *
5 * *
6 ****************************************************************************/
7
8 #if defined( INC_ALL )
9 #include "cert.h"
10 #include "asn1_ext.h"
11 #else
12 #include "cert/cert.h"
13 #include "enc_dec/asn1_ext.h"
14 #endif /* Compiler-specific includes */
15
16 /* Before we encode a certificate object we have to perform various final
17 setup actions and check that the object is ready for encoding. The setup
18 operations and checks for the different object types are:
19
20 | Cert | Attr | P10 |Cr.Req |Rv.Req
21 ------------+-------+-------+-------+-------+-------+
22 STDATTR | X[1]| | | | | Setup
23 ISSUERATTR | X | X | | | | action
24 ISSUERDN | X | X | | | |
25 VALPERIOD | X | X | | | |
26 VALINFO | | | | | |
27 REVINFO | | | | | |
28 ------------+-------+-------+-------+-------+-------+
29 SPKI | X | | X | X | | Check
30 DN | X | X | | | |
31 DN_PART | | | X | X | |
32 ISSUERDN | X | X | | | X |
33 ISSUERCRTDN | | | | | |
34 NON_SELFSD | X | X | | | |
35 SERIALNO | X | X | | | X |
36 REVENTRIES | | | | | |
37 ------------+-------+-------+-------+-------+-------+
38
39 |RTCS Rq|RTCS Rs|OCSP Rq|OCSP Rs| CRL |CRLentr|
40 ------------+-------+-------+-------+-------+-------+-------+
41 STDATTR | | | | | | | Setup
42 ISSUERATTR | | | | | X | | action
43 ISSUERDN | | | | | X | |
44 VALPERIOD | | | | | | |
45 VALINFO | X | | | | | |
46 REVINFO | | | X | | X | X |
47 ------------+-------+-------+-------+-------+-------+-------+
48 SPKI | | | | | | | Check
49 DN | | | | X | | |
50 DN_PART | | | | | | |
51 ISSUERDN | | | | | X | |
52 ISSUERCRTDN | | | | | X | |
53 NON_SELFSD | | | | | | |
54 SERIALNO | | | | | | |
55 VALENTRIES | X | | | | | |
56 REVENTRIES | | | X | X | | |
57 ------------+-------+-------+-------+-------+-------+-------+
58
59 We have to be careful here to avoid race conditions when some of the
60 checks depend on setup actions having been performed first but some of
61 the setup actions require that checks be performed first. The noted
62 exceptions are:
63
64 [1] Requires that the SPKI check be performed first since STDATTR
65 evaluates keyUsage from the SPKI */
66
67 #ifdef USE_CERTIFICATES
68
69 /****************************************************************************
70 * *
71 * Utility Functions *
72 * *
73 ****************************************************************************/
74
75 /* Add standard X.509v3 extensions to a certificate if they're not already
76 present. This function simply adds the required extensions, it doesn't
77 check for consistency with existing extensions which is done later by
78 checkAttributes() and checkCert() */
79
80 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
addStandardExtensions(INOUT CERT_INFO * certInfoPtr)81 static int addStandardExtensions( INOUT CERT_INFO *certInfoPtr )
82 {
83 BOOLEAN isCA = FALSE;
84 int keyUsage, extKeyUsage, value, status;
85
86 assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
87
88 /* Get the implicit keyUsage flags (based on any extended key usage
89 extensions present) and explicit key usage flags, which we use to
90 extend the basic keyUsage flags if required */
91 status = getKeyUsageFromExtKeyUsage( certInfoPtr, &extKeyUsage,
92 &certInfoPtr->errorLocus, &certInfoPtr->errorType );
93 if( cryptStatusError( status ) )
94 return( status );
95 status = getAttributeFieldValue( certInfoPtr->attributes,
96 CRYPT_CERTINFO_KEYUSAGE,
97 CRYPT_ATTRIBUTE_NONE, &keyUsage );
98 if( cryptStatusError( status ) )
99 {
100 if( status != CRYPT_ERROR_NOTFOUND )
101 return( status );
102
103 /* There's no keyUsage attribute present, mark the value as being
104 not set so that we explicitly set it later */
105 keyUsage = CRYPT_ERROR;
106 }
107
108 /* If there's an explicit key usage present, make sure that it's
109 consistent with the implicit key usage flags derived from the
110 extended key usage. We mask out the nonRepudiation bit for reasons
111 given in chk_cert.c.
112
113 This check is also performed by checkCert(), however we need to
114 explicitly perform it here as well since we need to add a key usage
115 to match the extKeyUsage before calling checkCert() if one wasn't
116 explicitly set or checkCert() will reject the certificate because of
117 the inconsistent keyUsage */
118 if( keyUsage > 0 )
119 {
120 const int effectiveKeyUsage = \
121 extKeyUsage & ~CRYPT_KEYUSAGE_NONREPUDIATION;
122
123 if( ( keyUsage & effectiveKeyUsage ) != effectiveKeyUsage )
124 {
125 setErrorInfo( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,
126 CRYPT_ERRTYPE_CONSTRAINT );
127 return( CRYPT_ERROR_INVALID );
128 }
129 }
130
131 /* Check whether this is a CA certificate. If there's no
132 basicConstraints attribute present, add one and make it a non-CA
133 certificate */
134 status = getAttributeFieldValue( certInfoPtr->attributes,
135 CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE,
136 &value );
137 if( cryptStatusOK( status ) )
138 isCA = ( value > 0 ) ? TRUE : FALSE;
139 else
140 {
141 status = addCertComponent( certInfoPtr, CRYPT_CERTINFO_CA, FALSE );
142 if( cryptStatusError( status ) )
143 return( status );
144 }
145
146 /* If there's no explicit keyUsage information present add it based on
147 various implicit information. We also add key feature information
148 which is used to help automate key management, for example to inhibit
149 speculative reads of keys held in removable tokens, which can result
150 in spurious insert-token dialogs being presented to the user outside
151 the control of cryptlib if the token isn't present */
152 if( keyUsage <= 0 )
153 {
154 /* If there's no implicit key usage present and it's not a CA (for
155 which we don't want to set things like encryption flags for the
156 CA certificate), set the key usage flags based on the
157 capabilities of the associated context. Because no-one can
158 figure out what the nonRepudiation flag signifies we don't set
159 this, if the user wants it they have to specify it explicitly.
160 Similarly we don't try and set the keyAgreement encipher/decipher-
161 only flags, which were tacked on as variants of keyAgreement long
162 after the basic keyAgreement flag was defined */
163 if( extKeyUsage <= 0 && !isCA )
164 {
165 keyUsage = 0; /* Reset key usage */
166 if( certInfoPtr->iPubkeyContext != CRYPT_ERROR )
167 {
168 /* There's a context present, check its capabilities. This
169 has the advantage that it takes into account any ACLs
170 that may exist for the key */
171 if( cryptStatusOK( \
172 krnlSendMessage( certInfoPtr->iPubkeyContext,
173 IMESSAGE_CHECK, NULL,
174 MESSAGE_CHECK_PKC_SIGCHECK ) ) )
175 keyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE;
176 if( cryptStatusOK( \
177 krnlSendMessage( certInfoPtr->iPubkeyContext,
178 IMESSAGE_CHECK, NULL,
179 MESSAGE_CHECK_PKC_ENCRYPT ) ) )
180 keyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;
181 if( cryptStatusOK( \
182 krnlSendMessage( certInfoPtr->iPubkeyContext,
183 IMESSAGE_CHECK, NULL,
184 MESSAGE_CHECK_PKC_KA_EXPORT ) ) || \
185 cryptStatusOK( \
186 krnlSendMessage( certInfoPtr->iPubkeyContext,
187 IMESSAGE_CHECK, NULL,
188 MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
189 keyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;
190 }
191 else
192 {
193 /* There's no context present (the key is present as encoded
194 data), assume we can do whatever the algorithm allows */
195 if( isSigAlgo( certInfoPtr->publicKeyAlgo ) )
196 keyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE;
197 if( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )
198 keyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;
199 if( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )
200 keyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;
201 }
202 }
203 else
204 {
205 /* There's an extended key usage set but no basic keyUsage, make
206 the keyUsage consistent with the usage flags derived from the
207 extended usage */
208 keyUsage = extKeyUsage;
209
210 /* If it's a CA key, make sure that it's a signing key and
211 enable its use for certification-related purposes*/
212 if( isCA )
213 {
214 BOOLEAN usageOK;
215
216 if( certInfoPtr->iPubkeyContext != CRYPT_ERROR )
217 {
218 usageOK = cryptStatusOK( \
219 krnlSendMessage( certInfoPtr->iPubkeyContext,
220 IMESSAGE_CHECK, NULL,
221 MESSAGE_CHECK_PKC_SIGCHECK ) );
222 }
223 else
224 usageOK = isSigAlgo( certInfoPtr->publicKeyAlgo );
225 if( !usageOK )
226 {
227 setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CA,
228 CRYPT_ERRTYPE_CONSTRAINT );
229 return( CRYPT_ERROR_INVALID );
230 }
231 keyUsage |= KEYUSAGE_CA;
232 }
233 }
234 ENSURES( keyUsage > CRYPT_KEYUSAGE_NONE && \
235 keyUsage < CRYPT_KEYUSAGE_LAST );
236 status = addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,
237 keyUsage );
238 if( cryptStatusError( status ) )
239 return( status );
240 }
241 if( certInfoPtr->publicKeyFeatures > 0 )
242 {
243 /* This is a bitstring so we only add it if there are feature flags
244 present to avoid writing zero-length values */
245 status = addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYFEATURES,
246 certInfoPtr->publicKeyFeatures );
247 if( cryptStatusError( status ) && status != CRYPT_ERROR_INITED )
248 return( status );
249 }
250
251 /* Add the subjectKeyIdentifier */
252 #if 0 /* 10/12/12 To test situations where keyID != sKID, enable the
253 following code */
254 {
255 BYTE buffer[ 128 ];
256
257 memcpy( buffer, certInfoPtr->publicKeyID, KEYID_SIZE );
258 memset( buffer, 0xFF, KEYID_SIZE / 2 );
259 return( addCertComponentString( certInfoPtr,
260 CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,
261 buffer, KEYID_SIZE ) );
262 }
263 #endif /* 0 */
264 return( addCertComponentString( certInfoPtr,
265 CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,
266 certInfoPtr->publicKeyID, KEYID_SIZE ) );
267 }
268
269 /****************************************************************************
270 * *
271 * Pre-encode Checking Functions *
272 * *
273 ****************************************************************************/
274
275 /* Check whether an empty DN is permitted in a certificate. This is a PKIX
276 peculiarity that causes severe problems for virtually all certificate-
277 using protocols so we only allow it at a compliance level of
278 CRYPT_COMPLIANCELEVEL_PKIX_FULL */
279
280 #ifdef USE_CERTLEVEL_PKIX_FULL
281
282 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
checkEmptyDnOK(INOUT CERT_INFO * subjectCertInfoPtr)283 static BOOLEAN checkEmptyDnOK( INOUT CERT_INFO *subjectCertInfoPtr )
284 {
285 ATTRIBUTE_PTR *attributePtr;
286 int value, complianceLevel, status;
287
288 assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
289
290 /* PKIX allows empty subject DNs if a subject altName is present,
291 however creating certificates like this breaks every certificate-
292 using protocol supported by cryptlib so we only allow it at the
293 highest compliance level */
294 if( cryptStatusError( \
295 krnlSendMessage( subjectCertInfoPtr->ownerHandle,
296 IMESSAGE_GETATTRIBUTE, &complianceLevel,
297 CRYPT_OPTION_CERT_COMPLIANCELEVEL ) ) || \
298 complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL )
299 {
300 /* We only allow this behaviour at the highest compliance level */
301 return( FALSE );
302 }
303
304 /* We also have to be very careful to ensure that the empty subject
305 DN can't end up becoming an empty issuer DN, which can occur if it's
306 a self-signed certificate */
307 if( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED )
308 {
309 /* We can't have an empty issuer (== subject) DN */
310 return( FALSE );
311 }
312
313 /* In addition if it's a CA certificate then the subject DN can't be
314 empty, for obvious reasons */
315 status = getAttributeFieldValue( subjectCertInfoPtr->attributes,
316 CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE,
317 &value );
318 if( cryptStatusOK( status ) && value > 0 )
319 {
320 /* It's a CA certificate, the subject DN can't be empty */
321 return( FALSE );
322 }
323
324 /* Finally, if there's no subject DN present then there has to be an
325 altName present to take its place */
326 attributePtr = findAttributeField( subjectCertInfoPtr->attributes,
327 CRYPT_CERTINFO_SUBJECTALTNAME,
328 CRYPT_ATTRIBUTE_NONE );
329 if( attributePtr == NULL )
330 {
331 /* Either a subject DN or subject altName must be present */
332 return( FALSE );
333 }
334
335 /* There's a subject altName present but no subject DN, mark the altName
336 as critical */
337 setAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL, 0 );
338
339 return( TRUE );
340 }
341 #endif /* USE_CERTLEVEL_PKIX_FULL */
342
343 /* Perform any final setup actions that add default and issuer-contributed
344 attributes */
345
346 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
preEncodeCertificate(INOUT CERT_INFO * subjectCertInfoPtr,IN_OPT const CERT_INFO * issuerCertInfoPtr,IN_FLAGS (PRE_SET)const int actions)347 int preEncodeCertificate( INOUT CERT_INFO *subjectCertInfoPtr,
348 IN_OPT const CERT_INFO *issuerCertInfoPtr,
349 IN_FLAGS( PRE_SET ) const int actions )
350 {
351 int status;
352
353 assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
354 assert( ( issuerCertInfoPtr == NULL ) || \
355 isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
356
357 REQUIRES( actions >= PRE_SET_NONE && \
358 actions <= PRE_SET_FLAG_MAX );
359 REQUIRES( ( ( actions & ( PRE_SET_ISSUERATTR | PRE_SET_ISSUERDN | \
360 PRE_SET_VALIDITYPERIOD ) ) && \
361 issuerCertInfoPtr != NULL ) || \
362 !( actions & ( PRE_SET_ISSUERATTR | PRE_SET_ISSUERDN | \
363 PRE_SET_VALIDITYPERIOD ) ) );
364
365 /* If it's a >= v3 certificate add the standard X.509v3 extensions if
366 these aren't already present */
367 if( actions & PRE_SET_STANDARDATTR )
368 {
369 /* Setting the standard attributes requires the presence of a public
370 key to get keyUsage information from, so we have to check this
371 before we can add any attributes. This would normally be checked
372 as part of the range of checking performedin
373 preCheckCertificate(), but that isn't called until the pre-
374 encoding functions here have been performed */
375 if( subjectCertInfoPtr->publicKeyInfo == NULL )
376 {
377 setErrorInfo( subjectCertInfoPtr,
378 CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
379 CRYPT_ERRTYPE_ATTR_ABSENT );
380 return( CRYPT_ERROR_NOTINITED );
381 }
382
383 /* Attributes are only allowed with version 3 certificates */
384 if( subjectCertInfoPtr->version >= X509_V3 )
385 {
386 status = addStandardExtensions( subjectCertInfoPtr );
387 if( cryptStatusError( status ) )
388 return( status );
389 }
390 }
391
392 /* Copy any required extensions from the issuer to the subject
393 certificate if necessary */
394 if( actions & PRE_SET_ISSUERATTR )
395 {
396 ANALYSER_HINT( issuerCertInfoPtr != NULL );
397
398 if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
399 {
400 status = copyIssuerAttributes( &subjectCertInfoPtr->attributes,
401 issuerCertInfoPtr->attributes,
402 subjectCertInfoPtr->type,
403 &subjectCertInfoPtr->errorLocus,
404 &subjectCertInfoPtr->errorType );
405 if( cryptStatusError( status ) )
406 return( status );
407 }
408 }
409
410 /* Copy the issuer DN if this isn't already present */
411 if( actions & PRE_SET_ISSUERDN )
412 {
413 ANALYSER_HINT( issuerCertInfoPtr != NULL );
414
415 if( subjectCertInfoPtr->issuerName == NULL )
416 {
417 status = copyDN( &subjectCertInfoPtr->issuerName,
418 issuerCertInfoPtr->subjectName );
419 if( cryptStatusError( status ) )
420 return( status );
421 }
422 }
423
424 /* Constrain the subject validity period to be within the issuer
425 validity period */
426 if( actions & PRE_SET_VALIDITYPERIOD )
427 {
428 ANALYSER_HINT( issuerCertInfoPtr != NULL );
429
430 if( subjectCertInfoPtr->startTime < issuerCertInfoPtr->startTime )
431 subjectCertInfoPtr->startTime = issuerCertInfoPtr->startTime;
432 if( subjectCertInfoPtr->endTime > issuerCertInfoPtr->endTime )
433 subjectCertInfoPtr->endTime = issuerCertInfoPtr->endTime;
434 }
435
436 #ifdef USE_CERTVAL
437 /* If it's an RTCS response, prepare the certificate status list entries
438 prior to encoding them */
439 if( actions & PRE_SET_VALINFO )
440 {
441 status = prepareValidityEntries( subjectCertInfoPtr->cCertVal->validityInfo,
442 &subjectCertInfoPtr->cCertVal->currentValidity,
443 &subjectCertInfoPtr->errorLocus,
444 &subjectCertInfoPtr->errorType );
445 if( cryptStatusError( status ) )
446 return( status );
447 }
448 #endif /* USE_CERTVAL */
449
450 #ifdef USE_CERTREV
451 /* If it's a CRL or OCSP response, prepare the revocation list entries
452 prior to encoding them */
453 if( actions & PRE_SET_REVINFO )
454 {
455 REVOCATION_INFO *revocationErrorEntry;
456 const BOOLEAN isCrlEntry = \
457 ( ( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CRL ) && \
458 !( actions & PRE_SET_ISSUERDN ) ) ? TRUE : FALSE;
459
460 status = prepareRevocationEntries( subjectCertInfoPtr->cCertRev->revocations,
461 subjectCertInfoPtr->cCertRev->revocationTime,
462 &revocationErrorEntry, isCrlEntry,
463 &subjectCertInfoPtr->errorLocus,
464 &subjectCertInfoPtr->errorType );
465 if( cryptStatusError( status ) )
466 {
467 /* If there was an error and we're processing an entire
468 revocation list, select the entry that caused the problem */
469 if( !isCrlEntry )
470 {
471 subjectCertInfoPtr->cCertRev->currentRevocation = \
472 revocationErrorEntry;
473 }
474 return( status );
475 }
476 }
477 #endif /* USE_CERTREV */
478
479 return( CRYPT_OK );
480 }
481
482 /* Check that a certificate object is reading for encoding */
483
484 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
preCheckCertificate(INOUT CERT_INFO * subjectCertInfoPtr,IN_OPT const CERT_INFO * issuerCertInfoPtr,IN_FLAGS (PRE_CHECK)const int actions,IN_FLAGS_Z (PRE)const int flags)485 int preCheckCertificate( INOUT CERT_INFO *subjectCertInfoPtr,
486 IN_OPT const CERT_INFO *issuerCertInfoPtr,
487 IN_FLAGS( PRE_CHECK ) const int actions,
488 IN_FLAGS_Z( PRE ) const int flags )
489 {
490 int status;
491
492 assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
493 assert( ( issuerCertInfoPtr == NULL ) || \
494 isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
495
496 REQUIRES( actions >= PRE_CHECK_NONE && \
497 actions <= PRE_CHECK_FLAG_MAX );
498 REQUIRES( flags == PRE_FLAG_NONE || \
499 flags == PRE_FLAG_DN_IN_ISSUERCERT );
500 REQUIRES( ( ( actions & ( PRE_CHECK_ISSUERCERTDN | \
501 PRE_CHECK_NONSELFSIGNED_DN ) ) && \
502 issuerCertInfoPtr != NULL ) || \
503 !( actions & ( PRE_CHECK_ISSUERCERTDN | \
504 PRE_CHECK_NONSELFSIGNED_DN ) ) );
505 /* We can't impose a complete set of preconditions on the
506 issuer certificate because some issuer attributes like the
507 issuer DN may already be present in the subject
508 certificate */
509
510 /* Make sure that there's public-key information present */
511 if( actions & PRE_CHECK_SPKI )
512 {
513 if( subjectCertInfoPtr->publicKeyInfo == NULL )
514 {
515 setErrorInfo( subjectCertInfoPtr,
516 CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
517 CRYPT_ERRTYPE_ATTR_ABSENT );
518 return( CRYPT_ERROR_NOTINITED );
519 }
520 }
521
522 /* Make sure that there's a full DN present */
523 if( actions & PRE_CHECK_DN )
524 {
525 status = checkDN( subjectCertInfoPtr->subjectName,
526 CHECKDN_FLAG_COUNTRY | CHECKDN_FLAG_COMMONNAME,
527 &subjectCertInfoPtr->errorLocus,
528 &subjectCertInfoPtr->errorType );
529 if( cryptStatusError( status ) )
530 {
531 #ifdef USE_CERTLEVEL_PKIX_FULL
532 /* In some very special cases an empty DN is permitted so we
533 only return an error if this really isn't allowed */
534 if( status != CRYPT_ERROR_NOTINITED || \
535 !checkEmptyDnOK( subjectCertInfoPtr ) )
536 #endif /* USE_CERTLEVEL_PKIX_FULL */
537 return( status );
538 }
539 }
540
541 /* Make sure that there's at least a partial DN present (some CA's will
542 fill the upper portion of the DN themselves so at a minimum all that
543 we really need is a CommonName) */
544 if( actions & PRE_CHECK_DN_PARTIAL )
545 {
546 status = checkDN( subjectCertInfoPtr->subjectName,
547 CHECKDN_FLAG_COMMONNAME,
548 &subjectCertInfoPtr->errorLocus,
549 &subjectCertInfoPtr->errorType );
550 if( cryptStatusError( status ) )
551 return( status );
552 }
553
554 /* Make sure that there's an issuer DN present */
555 if( actions & PRE_CHECK_ISSUERDN )
556 {
557 if( flags & PRE_FLAG_DN_IN_ISSUERCERT )
558 {
559 if( issuerCertInfoPtr == NULL || \
560 issuerCertInfoPtr->subjectDNptr == NULL || \
561 issuerCertInfoPtr->subjectDNsize < 1 )
562 {
563 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
564 CRYPT_ERRTYPE_ATTR_ABSENT );
565 return( CRYPT_ERROR_NOTINITED );
566 }
567 }
568 else
569 {
570 /* The issuer DN can be present either in pre-encoded form (if
571 it was copied from an issuer certificate) or as a full DN (if
572 it's a self-signed certificate), so we check for the presence
573 of either */
574 if( ( subjectCertInfoPtr->issuerName == NULL ) &&
575 ( subjectCertInfoPtr->issuerDNptr == NULL || \
576 subjectCertInfoPtr->issuerDNsize < 1 ) )
577 {
578 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
579 CRYPT_ERRTYPE_ATTR_ABSENT );
580 return( CRYPT_ERROR_NOTINITED );
581 }
582 }
583 }
584
585 /* If it's a CRL, compare the revoked certificate issuer DN and signer
586 DN to make sure that we're not trying to revoke someone else's
587 certificates, and prepare the revocation entries */
588 if( actions & PRE_CHECK_ISSUERCERTDN )
589 {
590 ANALYSER_HINT( issuerCertInfoPtr != NULL );
591
592 if( !compareDN( subjectCertInfoPtr->issuerName,
593 issuerCertInfoPtr->subjectName, FALSE, NULL ) )
594 {
595 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
596 CRYPT_ERRTYPE_ATTR_VALUE );
597 return( CRYPT_ERROR_INVALID );
598 }
599 }
600
601 /* If we're creating a non-self-signed certificate check whether the
602 subject's DN is the same as the issuer's DN. If this is the case
603 then the resulting object would appear to be self-signed so we
604 disallow it */
605 if( actions & PRE_CHECK_NONSELFSIGNED_DN )
606 {
607 ANALYSER_HINT( issuerCertInfoPtr != NULL );
608
609 if( compareDN( issuerCertInfoPtr->subjectName,
610 subjectCertInfoPtr->subjectName, FALSE, NULL ) )
611 {
612 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,
613 CRYPT_ERRTYPE_ISSUERCONSTRAINT );
614 return( CRYPT_ERROR_INVALID );
615 }
616 }
617
618 /* Check that the serial number is present */
619 if( actions & PRE_CHECK_SERIALNO )
620 {
621 #ifdef USE_CERTREQ
622 if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
623 {
624 if( subjectCertInfoPtr->cCertReq->serialNumberLength <= 0 )
625 {
626 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,
627 CRYPT_ERRTYPE_ATTR_ABSENT );
628 return( CRYPT_ERROR_NOTINITED );
629 }
630 }
631 else
632 #endif /* USE_CERTREQ */
633 {
634 if( subjectCertInfoPtr->cCertCert->serialNumberLength <= 0 )
635 {
636 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,
637 CRYPT_ERRTYPE_ATTR_ABSENT );
638 return( CRYPT_ERROR_NOTINITED );
639 }
640 }
641 }
642
643 /* Check that the validity/revocation information is present */
644 #ifdef USE_CERTVAL
645 if( actions & PRE_CHECK_VALENTRIES )
646 {
647 if( subjectCertInfoPtr->cCertVal->validityInfo == NULL )
648 {
649 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
650 CRYPT_ERRTYPE_ATTR_ABSENT );
651 return( CRYPT_ERROR_NOTINITED );
652 }
653 }
654 #endif /* USE_CERTVAL */
655 #ifdef USE_CERTREV
656 if( actions & PRE_CHECK_REVENTRIES )
657 {
658 if( subjectCertInfoPtr->cCertRev->revocations == NULL )
659 {
660 setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
661 CRYPT_ERRTYPE_ATTR_ABSENT );
662 return( CRYPT_ERROR_NOTINITED );
663 }
664 }
665 #endif /* USE_CERTREV */
666
667 /* Now that we've set up the attributes, perform the remainder of the
668 checks. Because RTCS is a CMS standard rather than PKIX the RTCS
669 attributes are CMS rather than certificate attributes */
670 if( subjectCertInfoPtr->attributes != NULL )
671 {
672 status = checkAttributes( ( subjectCertInfoPtr->type == \
673 CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
674 ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,
675 subjectCertInfoPtr->attributes,
676 &subjectCertInfoPtr->errorLocus,
677 &subjectCertInfoPtr->errorType );
678 if( cryptStatusError( status ) )
679 return( status );
680 }
681 status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr, FALSE,
682 &subjectCertInfoPtr->errorLocus,
683 &subjectCertInfoPtr->errorType );
684 if( cryptStatusError( status ) )
685 return( status );
686
687 /* If it's a certificate or certificate chain remember that it's been
688 checked at full compliance level (or at least as full as we're
689 configured for). This short-circuits the need to perform excessive
690 levels of checking if the caller wants to re-check it after it's
691 been signed */
692 if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
693 subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
694 {
695 subjectCertInfoPtr->cCertCert->maxCheckLevel = \
696 CRYPT_COMPLIANCELEVEL_PKIX_FULL;
697 }
698
699 return( status );
700 }
701 #endif /* USE_CERTIFICATES */
702