Skip to content

Commit a1b86ec

Browse files
Extended attr cert verification; fix failing on any attr cert extension
1 parent 31cfe39 commit a1b86ec

File tree

7 files changed

+241
-174
lines changed

7 files changed

+241
-174
lines changed

apps/acert.c

Lines changed: 5 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -180,130 +180,6 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
180180
return 0;
181181
}
182182

183-
static int X509_ACERT_verify_cert (X509_ACERT *acert, X509 *holder, X509 *issuer) {
184-
int ret = 0;
185-
OSSL_ISSUER_SERIAL *basecertid;
186-
const GENERAL_NAMES *holder_ent;
187-
const X509_NAME *entity;
188-
AUTHORITY_KEYID *akid;
189-
190-
int holder_verified = 0;
191-
192-
if (ossl_x509_check_acert_exts(acert) != X509_V_OK)
193-
goto out;
194-
195-
/*
196-
* Check that holder cert matches attribute cert holder field.
197-
* This can be done withi *either* the baseCertificateId or the
198-
* entityName. RFC 5755 recommends that only one option is used
199-
* for a given AC, but in case both are present, baseCertificateId
200-
* takes precedence.
201-
*/
202-
if ((basecertid = X509_ACERT_get0_holder_baseCertId(acert)) != NULL) {
203-
if (X509_NAME_cmp(OSSL_ISSUER_SERIAL_get0_issuer(basecertid),
204-
X509_get_issuer_name(holder)) != 0
205-
|| ASN1_STRING_cmp(OSSL_ISSUER_SERIAL_get0_serial(basecertid),
206-
X509_get0_serialNumber(holder)) != 0) {
207-
goto out;
208-
}
209-
holder_verified = 1;
210-
}
211-
212-
if (holder_verified == 0
213-
&& (holder_ent = X509_ACERT_get0_holder_entityName(acert)) != NULL
214-
&& sk_GENERAL_NAME_num(holder_ent) >= 1) {
215-
GENERAL_NAMES *holderAltNames;
216-
GENERAL_NAME *entName = sk_GENERAL_NAME_value(holder_ent, 0);
217-
int i;
218-
219-
if (entName->type == GEN_DIRNAME
220-
&& X509_NAME_cmp(entName->d.directoryName, X509_get_subject_name(holder)) == 0)
221-
holder_verified = 1;
222-
223-
if (holder_verified == 0
224-
&& (holderAltNames = X509_get_ext_d2i(holder, NID_subject_alt_name,
225-
NULL, NULL)) != NULL) {
226-
for (i = 0; i < sk_GENERAL_NAME_num(holderAltNames); i++) {
227-
GENERAL_NAME *name = sk_GENERAL_NAME_value(holderAltNames, i);
228-
229-
if (GENERAL_NAME_cmp(name, entName) == 0) {
230-
holder_verified = 1;
231-
break;
232-
}
233-
}
234-
}
235-
}
236-
237-
if (holder_verified == 0) {
238-
ERR_raise(ERR_LIB_X509, X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
239-
goto out;
240-
}
241-
242-
/*
243-
* Check that issuer cert matches attribute cert issuer field,
244-
* and AKID if present.
245-
*/
246-
if ((entity = X509_ACERT_get0_issuerName(acert)) == NULL
247-
|| X509_NAME_cmp(entity, X509_get_subject_name(issuer)) != 0) {
248-
ERR_raise(ERR_LIB_X509, X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
249-
goto out;
250-
}
251-
252-
/*
253-
* Check that the issuer satisfies the AC issuer profile in
254-
* RFC 5755 Section 4.5. This will also cache the attached
255-
* X509v3 extensions, which must be done before calling
256-
* X509_check_akid() and X509_check_ca() to get valid results.
257-
*/
258-
if ((X509_get_key_usage(issuer) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
259-
ERR_raise(ERR_LIB_X509, X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
260-
goto out;
261-
}
262-
263-
/* TODO: wrap this in X509_ACERT_get_ext_d2i) */
264-
if ((akid = X509V3_get_d2i(acert->acinfo->extensions,
265-
NID_authority_key_identifier, NULL, NULL))
266-
!= NULL) {
267-
if (X509_check_akid(issuer, akid))
268-
goto out;
269-
}
270-
271-
if (X509_ACERT_verify(acert, X509_get0_pubkey(issuer)) <= 0) {
272-
ERR_raise(ERR_LIB_X509, X509_V_ERR_CERT_SIGNATURE_FAILURE);
273-
goto out;
274-
}
275-
276-
/*
277-
* extensions have been cached by X509_get_key_usage(), so X509_check_ca()
278-
* can't fail and will only return 0 if `issuer` is not a CA.
279-
*
280-
* It does not seem to be specified in ITU Recommendation X.509, but IETF
281-
* RFC 5755 states in Section 4.5 that an AC issuer MUST NOT be a PKC
282-
* issuer.
283-
*
284-
* In my opinion, however, validation should simply be ambivalent.
285-
*/
286-
// if (X509_check_ca(issuer) != 0) {
287-
// ERR_raise(ERR_LIB_X509, X509_V_ERR_INVALID_NON_CA);
288-
// goto out;
289-
// }
290-
291-
if (X509_cmp_time(X509_ACERT_get0_notBefore(acert), NULL) > 0) {
292-
ERR_raise(ERR_LIB_X509, X509_V_ERR_CERT_NOT_YET_VALID);
293-
goto out;
294-
}
295-
296-
if (X509_cmp_time(X509_ACERT_get0_notAfter(acert), NULL) < 0) {
297-
ERR_raise(ERR_LIB_X509, X509_V_ERR_CERT_HAS_EXPIRED);
298-
goto out;
299-
}
300-
301-
ret = 1;
302-
303-
out:
304-
return ret;
305-
}
306-
307183
int acert_main(int argc, char **argv)
308184
{
309185
ASN1_INTEGER *serial = NULL;
@@ -691,12 +567,13 @@ int acert_main(int argc, char **argv)
691567
BIO_printf(bio_err, "Holder certificate could not be loaded.\n");
692568
goto end;
693569
}
694-
if (X509_ACERT_verify_cert(acert, holder, AAcert) <= 0) {
695-
ERR_print_errors(bio_err);
696-
BIO_printf(bio_err, "Attribute certificate verification failed.\n");
570+
ret = X509_attr_cert_verify_ex(acert, AAcert, holder, NULL, 0);
571+
if (ret != X509_V_OK) {
572+
BIO_printf(bio_err, "Attribute certificate is invalid.\n");
697573
goto end;
574+
} else {
575+
BIO_printf(bio_err, "Attribute certificate is valid.\n");
698576
}
699-
BIO_printf(bio_err, "Attribute certificate is valid.\n");
700577
}
701578

702579
if (noout && !text) {

0 commit comments

Comments
 (0)