goto end;
}
- X509V3_set_ctx(&ext_ctx, issuer_cert, x, req, NULL, X509V3_CTX_REPLACE);
+ X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
+ /* prepare fallback for AKID, but only if issuer cert equals subject cert */
+ if (CAfile == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, privkey))
+ goto end;
+ }
if (extconf != NULL && !x509toreq) {
X509V3_set_nconf(&ext_ctx, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
ASN1_INTEGER *serial = NULL;
X509_EXTENSION *ext;
X509 *issuer_cert;
+ int same_issuer, ss;
AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
if (akeyid == NULL)
ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
goto err;
}
-
- if (keyid != 0) {
- /* prefer any pre-existing subject key identifier of the issuer cert */
+ same_issuer = ctx->subject_cert == ctx->issuer_cert;
+ ERR_set_mark();
+ if (ctx->issuer_pkey != NULL)
+ ss = X509_check_private_key(ctx->subject_cert, ctx->issuer_pkey);
+ else
+ ss = same_issuer;
+ ERR_pop_to_mark();
+
+ /* unless forced with "always", AKID is suppressed for self-signed certs */
+ if (keyid == 2 || (keyid == 1 && !ss)) {
+ /*
+ * prefer any pre-existing subject key identifier of the issuer cert
+ * except issuer cert is same as subject cert and is not self-signed
+ */
i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1);
- if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL)
+ if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL
+ && !(same_issuer && !ss))
ikeyid = X509V3_EXT_d2i(ext);
- if (ikeyid == NULL && ctx->issuer_pkey != NULL) { /* fallback */
- /* generate AKID from scratch, emulating s2i_skey_id(..., "hash") */
+ if (ikeyid == NULL && same_issuer && ctx->issuer_pkey != NULL) {
+ /* generate fallback AKID, emulating s2i_skey_id(..., "hash") */
X509_PUBKEY *pubkey = NULL;
if (X509_PUBKEY_set(&pubkey, ctx->issuer_pkey))
or both of them, separated by C<,>.
Either or both can have the option B<always>,
indicated by putting a colon C<:> between the value and this option.
+For self-signed certificates the AKID is suppressed unless B<always> is present.
By default the B<x509>, B<req>, and B<ca> apps behave as if
"none" was given for self-signed certificates and "keyid, issuer" otherwise.
-If B<keyid> is present, an attempt is made to compute the hash of the public key
-corresponding to the signing key in case the certificate is self-signed,
-or else to copy the subject key identifier (SKID) from the issuer certificate.
-If this fails and the option B<always> is present, an error is returned.
+If B<keyid> is present, an attempt is made to
+copy the subject key identifier (SKID) from the issuer certificate except if
+the issuer certificate is the same as the current one and it is not self-signed.
+The hash of the public key related to the signing key is taken as fallback
+if the issuer certificate is the same as the current certificate.
+If B<always> is present but no value can be obtained, an error is returned.
If B<issuer> is present, and in addition it has the option B<always> specified
or B<keyid> is not present,
$cert = "self-signed_v3_CA_both_KIDs.pem";
generate_cert($cert, @v3_ca, "-addext", "subjectKeyIdentifier = hash",
- "-addext", "authorityKeyIdentifier = keyid");
+ "-addext", "authorityKeyIdentifier = keyid:always");
cert_ext_has_n_different_lines($cert, 3, $SKID_AKID); # SKID == AKID
strict_verify($cert, 1);