mirror of https://github.com/openssl/openssl.git
				
				
				
			CMS_add0_cert: if cert already present, do not throw error but ignore it
Also add checks on failing cert/CRL up_ref calls; improve coding style. Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/19199)
This commit is contained in:
		
							parent
							
								
									6f9e531003
								
							
						
					
					
						commit
						65def9de80
					
				|  | @ -168,6 +168,13 @@ OpenSSL 3.2 | ||||||
| 
 | 
 | ||||||
|    *David von Oheimb* |    *David von Oheimb* | ||||||
| 
 | 
 | ||||||
|  |  * `CMS_add0_cert()` and `CMS_add1_cert()` no more throw an error | ||||||
|  |    if a certificate to be added is already present. | ||||||
|  |  * `CMS_sign_ex()` and `CMS_sign()` now ignore any duplicate certificates | ||||||
|  |    in their `certs` argument and no longer throw an error for them. | ||||||
|  | 
 | ||||||
|  |    *David von Oheimb* | ||||||
|  | 
 | ||||||
|  * Fixed and extended `util/check-format.pl` for checking adherence to the |  * Fixed and extended `util/check-format.pl` for checking adherence to the | ||||||
|    coding style <https://www.openssl.org/policies/technical/coding-style.html>. |    coding style <https://www.openssl.org/policies/technical/coding-style.html>. | ||||||
|    The checks are meanwhile more complete and yield fewer false positives. |    The checks are meanwhile more complete and yield fewer false positives. | ||||||
|  |  | ||||||
|  | @ -537,9 +537,9 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) | ||||||
|     for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { |     for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | ||||||
|         cch = sk_CMS_CertificateChoices_value(*pcerts, i); |         cch = sk_CMS_CertificateChoices_value(*pcerts, i); | ||||||
|         if (cch->type == CMS_CERTCHOICE_CERT) { |         if (cch->type == CMS_CERTCHOICE_CERT) { | ||||||
|             if (!X509_cmp(cch->d.certificate, cert)) { |             if (X509_cmp(cch->d.certificate, cert) == 0) { | ||||||
|                 ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT); |                 X509_free(cert); | ||||||
|                 return 0; |                 return 1; /* cert already present */ | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -553,11 +553,12 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) | ||||||
| 
 | 
 | ||||||
| int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) | int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) | ||||||
| { | { | ||||||
|     int r; |     if (!X509_up_ref(cert)) | ||||||
|     r = CMS_add0_cert(cms, cert); |         return 0; | ||||||
|     if (r > 0) |     if (CMS_add0_cert(cms, cert)) | ||||||
|         X509_up_ref(cert); |         return 1; | ||||||
|     return r; |     X509_free(cert); | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static STACK_OF(CMS_RevocationInfoChoice) | static STACK_OF(CMS_RevocationInfoChoice) | ||||||
|  | @ -609,9 +610,9 @@ CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) | ||||||
| 
 | 
 | ||||||
| int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) | int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) | ||||||
| { | { | ||||||
|     CMS_RevocationInfoChoice *rch; |     CMS_RevocationInfoChoice *rch = CMS_add0_RevocationInfoChoice(cms); | ||||||
|     rch = CMS_add0_RevocationInfoChoice(cms); | 
 | ||||||
|     if (!rch) |     if (rch == NULL) | ||||||
|         return 0; |         return 0; | ||||||
|     rch->type = CMS_REVCHOICE_CRL; |     rch->type = CMS_REVCHOICE_CRL; | ||||||
|     rch->d.crl = crl; |     rch->d.crl = crl; | ||||||
|  | @ -665,16 +666,15 @@ STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) | ||||||
|     for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { |     for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { | ||||||
|         rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); |         rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); | ||||||
|         if (rch->type == 0) { |         if (rch->type == 0) { | ||||||
|             if (!crls) { |             if (crls == NULL) { | ||||||
|                 crls = sk_X509_CRL_new_null(); |                 if ((crls = sk_X509_CRL_new_null()) == NULL) | ||||||
|                 if (!crls) |  | ||||||
|                     return NULL; |                     return NULL; | ||||||
|             } |             } | ||||||
|             if (!sk_X509_CRL_push(crls, rch->d.crl)) { |             if (!sk_X509_CRL_push(crls, rch->d.crl) | ||||||
|  |                     || !X509_CRL_up_ref(rch->d.crl)) { | ||||||
|                 sk_X509_CRL_pop_free(crls, X509_CRL_free); |                 sk_X509_CRL_pop_free(crls, X509_CRL_free); | ||||||
|                 return NULL; |                 return NULL; | ||||||
|             } |             } | ||||||
|             X509_CRL_up_ref(rch->d.crl); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return crls; |     return crls; | ||||||
|  |  | ||||||
|  | @ -20,7 +20,13 @@ CMS_add0_crl, CMS_add1_crl, CMS_get1_crls | ||||||
| 
 | 
 | ||||||
| =head1 DESCRIPTION | =head1 DESCRIPTION | ||||||
| 
 | 
 | ||||||
| CMS_add0_cert() and CMS_add1_cert() add certificate I<cert> to I<cms>. | CMS_add0_cert() and CMS_add1_cert() add certificate I<cert> to I<cms> | ||||||
|  | unless it is already present. | ||||||
|  | This is used by L<CMS_sign_ex()> and L<CMS_sign()> and may be used before | ||||||
|  | calling L<CMS_verify()> to help chain building in certificate validation. | ||||||
|  | As the 0 implies, CMS_add0_cert() adds I<cert> internally to I<cms> | ||||||
|  | and on success it must not be freed up by the caller. | ||||||
|  | In contrast, the caller of CMS_add1_cert() must free I<cert>. | ||||||
| I<cms> must be of type signed data or (authenticated) enveloped data. | I<cms> must be of type signed data or (authenticated) enveloped data. | ||||||
| For signed data, such a certificate can be used when signing or verifying | For signed data, such a certificate can be used when signing or verifying | ||||||
| to fill in the signer certificate or to provide an extra CA certificate | to fill in the signer certificate or to provide an extra CA certificate | ||||||
|  | @ -30,7 +36,8 @@ CMS_get1_certs() returns all certificates in I<cms>. | ||||||
| 
 | 
 | ||||||
| CMS_add0_crl() and CMS_add1_crl() add CRL I<crl> to I<cms>. | CMS_add0_crl() and CMS_add1_crl() add CRL I<crl> to I<cms>. | ||||||
| I<cms> must be of type signed data or (authenticated) enveloped data. | I<cms> must be of type signed data or (authenticated) enveloped data. | ||||||
| For signed data, such a CRL may be used in certificate validation. | For signed data, such a CRL may be used in certificate validation | ||||||
|  | with L<CMS_verify()>. | ||||||
| It may be given both for inclusion when signing a CMS message | It may be given both for inclusion when signing a CMS message | ||||||
| and when verifying a signed CMS message. | and when verifying a signed CMS message. | ||||||
| 
 | 
 | ||||||
|  | @ -45,13 +52,6 @@ For signed data, certificates and CRLs are added to the I<certificates> and | ||||||
| I<crls> fields of SignedData structure. | I<crls> fields of SignedData structure. | ||||||
| For enveloped data they are added to B<OriginatorInfo>. | For enveloped data they are added to B<OriginatorInfo>. | ||||||
| 
 | 
 | ||||||
| As the 0 implies, CMS_add0_cert() adds I<cert> internally to I<cms> and it |  | ||||||
| must not be freed up after the call as opposed to CMS_add1_cert() where I<cert> |  | ||||||
| must be freed up. |  | ||||||
| 
 |  | ||||||
| The same certificate or CRL must not be added to the same cms structure more |  | ||||||
| than once. |  | ||||||
| 
 |  | ||||||
| =head1 RETURN VALUES | =head1 RETURN VALUES | ||||||
| 
 | 
 | ||||||
| CMS_add0_cert(), CMS_add1_cert() and CMS_add0_crl() and CMS_add1_crl() return | CMS_add0_cert(), CMS_add1_cert() and CMS_add0_crl() and CMS_add1_crl() return | ||||||
|  | @ -64,9 +64,14 @@ in practice is if the I<cms> type is invalid. | ||||||
| =head1 SEE ALSO | =head1 SEE ALSO | ||||||
| 
 | 
 | ||||||
| L<ERR_get_error(3)>, | L<ERR_get_error(3)>, | ||||||
| L<CMS_sign(3)>, | L<CMS_sign(3)>, L<CMS_sign_ex(3)>, L<CMS_verify(3)>, | ||||||
| L<CMS_encrypt(3)> | L<CMS_encrypt(3)> | ||||||
| 
 | 
 | ||||||
|  | =head1 HISTORY | ||||||
|  | 
 | ||||||
|  | CMS_add0_cert() and CMS_add1_cert() have been changed in OpenSSL 3.2 | ||||||
|  | not to throw an error if a certificate to be added is already present. | ||||||
|  | 
 | ||||||
| =head1 COPYRIGHT | =head1 COPYRIGHT | ||||||
| 
 | 
 | ||||||
| Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. | Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  | ||||||
|  | @ -130,6 +130,9 @@ it is supported for embedded data in OpenSSL 1.0.0 and later. | ||||||
| 
 | 
 | ||||||
| The CMS_sign_ex() method was added in OpenSSL 3.0. | The CMS_sign_ex() method was added in OpenSSL 3.0. | ||||||
| 
 | 
 | ||||||
|  | Since OpenSSL 3.2, CMS_sign_ex() and CMS_sign() ignore any duplicate | ||||||
|  | certificates in their I<certs> argument and no longer throw an error for them. | ||||||
|  | 
 | ||||||
| =head1 COPYRIGHT | =head1 COPYRIGHT | ||||||
| 
 | 
 | ||||||
| Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. | Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ it operates on B<CMS SignedData> input in the I<sd> argument, | ||||||
| it has some additional parameters described next, | it has some additional parameters described next, | ||||||
| and on success it returns the verfied content as a memory BIO. | and on success it returns the verfied content as a memory BIO. | ||||||
| The optional I<extra> parameter may be used to provide untrusted CA | The optional I<extra> parameter may be used to provide untrusted CA | ||||||
| certificates that may be helpful for chain building in certificate valiation. | certificates that may be helpful for chain building in certificate validation. | ||||||
| This list of certificates must not contain duplicates. | This list of certificates must not contain duplicates. | ||||||
| The optional I<crls> parameter may be used to provide extra CRLs. | The optional I<crls> parameter may be used to provide extra CRLs. | ||||||
| Also the list of CRLs must not contain duplicates. | Also the list of CRLs must not contain duplicates. | ||||||
|  |  | ||||||
|  | @ -88,6 +88,19 @@ static int test_encrypt_decrypt_aes_256_gcm(void) | ||||||
|     return test_encrypt_decrypt(EVP_aes_256_gcm()); |     return test_encrypt_decrypt(EVP_aes_256_gcm()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int test_CMS_add1_cert(void) | ||||||
|  | { | ||||||
|  |     CMS_ContentInfo *cms = NULL; | ||||||
|  |     int ret = 0; | ||||||
|  | 
 | ||||||
|  |     ret = TEST_ptr(cms = CMS_ContentInfo_new()) | ||||||
|  |         && TEST_ptr(CMS_add1_signer(cms, cert, privkey, NULL, 0)) | ||||||
|  |         && TEST_true(CMS_add1_cert(cms, cert)); /* add cert again */ | ||||||
|  | 
 | ||||||
|  |     CMS_ContentInfo_free(cms); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int test_d2i_CMS_bio_NULL(void) | static int test_d2i_CMS_bio_NULL(void) | ||||||
| { | { | ||||||
|     BIO *bio, *content = NULL; |     BIO *bio, *content = NULL; | ||||||
|  | @ -413,6 +426,7 @@ int setup_tests(void) | ||||||
|     ADD_TEST(test_encrypt_decrypt_aes_128_gcm); |     ADD_TEST(test_encrypt_decrypt_aes_128_gcm); | ||||||
|     ADD_TEST(test_encrypt_decrypt_aes_192_gcm); |     ADD_TEST(test_encrypt_decrypt_aes_192_gcm); | ||||||
|     ADD_TEST(test_encrypt_decrypt_aes_256_gcm); |     ADD_TEST(test_encrypt_decrypt_aes_256_gcm); | ||||||
|  |     ADD_TEST(test_CMS_add1_cert); | ||||||
|     ADD_TEST(test_d2i_CMS_bio_NULL); |     ADD_TEST(test_d2i_CMS_bio_NULL); | ||||||
|     ADD_ALL_TESTS(test_d2i_CMS_decode, 2); |     ADD_ALL_TESTS(test_d2i_CMS_decode, 2); | ||||||
|     return 1; |     return 1; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue