Skip to content

Commit 15fb99d

Browse files
Restore previous semantics of authorityKeyIdentifier=keyid
when the function X509V3_set_issuer_pkey is not used, since that would break code written for 1.1.1 and before, where e.g. X509V3_EXT_conf(NULL, &ctx, "authorityKeyIdentifier", "keyid,issuer"); was guaranteed to never fail and always generate a valid extension, and not an empty AKID. But due to the change, which happened between 1.1.1 and 3.0 that is no longer the case. Code written for 3.0 must use X509V3_set_issuer_pkey and detect the possible empty extensions, or use keyid:always and be prepared that it may be impossible to create this extension.
1 parent 7eb19ef commit 15fb99d

File tree

3 files changed

+105
-27
lines changed

3 files changed

+105
-27
lines changed

crypto/x509/v3_akid.c

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
107107
ASN1_INTEGER *serial = NULL;
108108
X509_EXTENSION *ext;
109109
X509 *issuer_cert;
110-
int same_issuer, ss;
110+
int self_signed = 0;
111111
AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
112112

113113
if (akeyid == NULL)
@@ -156,53 +156,50 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
156156
ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
157157
goto err;
158158
}
159-
same_issuer = ctx->subject_cert == ctx->issuer_cert;
160-
ERR_set_mark();
161-
if (ctx->issuer_pkey != NULL)
162-
ss = X509_check_private_key(ctx->subject_cert, ctx->issuer_pkey);
163-
else
164-
ss = same_issuer;
165-
ERR_pop_to_mark();
159+
160+
if (ctx->subject_cert != NULL && ctx->issuer_pkey != NULL) {
161+
ERR_set_mark();
162+
self_signed = X509_check_private_key(ctx->subject_cert,
163+
ctx->issuer_pkey);
164+
ERR_pop_to_mark();
165+
}
166166

167167
/* unless forced with "always", AKID is suppressed for self-signed certs */
168-
if (keyid == 2 || (keyid == 1 && !ss)) {
168+
if (keyid == 2 || (keyid == 1 && !self_signed)) {
169169
/*
170170
* prefer any pre-existing subject key identifier of the issuer cert
171-
* except issuer cert is same as subject cert and is not self-signed
171+
* except issuer cert is same as subject cert and private key is given
172172
*/
173-
i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1);
174-
if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL
175-
&& !(same_issuer && !ss)) {
176-
ikeyid = X509V3_EXT_d2i(ext);
177-
if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ {
178-
ASN1_OCTET_STRING_free(ikeyid);
179-
ikeyid = NULL;
180-
}
181-
}
182-
if (ikeyid == NULL && same_issuer && ctx->issuer_pkey != NULL) {
173+
if (ctx->subject_cert == issuer_cert && ctx->issuer_pkey != NULL) {
183174
/* generate fallback AKID, emulating s2i_skey_id(..., "hash") */
184175
X509_PUBKEY *pubkey = NULL;
185176

186177
if (X509_PUBKEY_set(&pubkey, ctx->issuer_pkey))
187178
ikeyid = ossl_x509_pubkey_hash(pubkey);
188179
X509_PUBKEY_free(pubkey);
180+
} else {
181+
i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1);
182+
if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL) {
183+
ikeyid = X509V3_EXT_d2i(ext);
184+
if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ {
185+
ASN1_OCTET_STRING_free(ikeyid);
186+
ikeyid = NULL;
187+
}
188+
}
189189
}
190190
if (keyid == 2 && ikeyid == NULL) {
191191
ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
192192
goto err;
193193
}
194194
}
195195

196-
if (issuer == 2 || (issuer == 1 && !ss && ikeyid == NULL)) {
196+
if (issuer == 2 || (issuer == 1 && ikeyid == NULL && !self_signed)) {
197197
isname = X509_NAME_dup(X509_get_issuer_name(issuer_cert));
198198
serial = ASN1_INTEGER_dup(X509_get0_serialNumber(issuer_cert));
199199
if (isname == NULL || serial == NULL) {
200200
ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
201201
goto err;
202202
}
203-
}
204-
205-
if (isname != NULL) {
206203
if ((gens = sk_GENERAL_NAME_new_null()) == NULL
207204
|| (gen = GENERAL_NAME_new()) == NULL) {
208205
ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
@@ -217,8 +214,6 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
217214
}
218215

219216
akeyid->issuer = gens;
220-
gen = NULL;
221-
gens = NULL;
222217
akeyid->serial = serial;
223218
akeyid->keyid = ikeyid;
224219

doc/man5/x509v3_config.pod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,17 @@ or both of them, separated by C<,>.
208208
Either or both can have the option B<always>,
209209
indicated by putting a colon C<:> between the value and this option.
210210
For self-signed certificates the AKID is suppressed unless B<always> is present.
211+
In order to find out, if the certificate is about to be self-signed, the
212+
private key as given by B<X509V3_set_issuer_pkey> is compared to the
213+
public key in the subject_certificate.
214+
When there is no private key available, the AKID will not be suppressed.
211215

212216
By default the B<x509>, B<req>, and B<ca> apps behave as if B<none> was given
213217
for self-signed certificates and B<keyid>C<,> B<issuer> otherwise.
214218

215219
If B<keyid> is present, an attempt is made to
216220
copy the subject key identifier (SKID) from the issuer certificate except if
217-
the issuer certificate is the same as the current one and it is not self-signed.
221+
the issuer certificate does not have the subject key identifier extension.
218222
The hash of the public key related to the signing key is taken as fallback
219223
if the issuer certificate is the same as the current certificate.
220224
If B<always> is present but no value can be obtained, an error is returned.

test/x509_test.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define OPENSSL_SUPPRESS_DEPRECATED /* EVP_PKEY_get1/set1_RSA */
1111

1212
#include <openssl/x509.h>
13+
#include <openssl/x509v3.h>
1314
#include <openssl/asn1.h>
1415
#include <openssl/evp.h>
1516
#include <openssl/rsa.h>
@@ -282,6 +283,83 @@ static int test_x509_revoked_delete_last_extension(void)
282283
return ret;
283284
}
284285

286+
static int test_x509_old_abi_compat_mode_extension(void)
287+
{
288+
static const unsigned char commonName[] = "test";
289+
X509 *x = NULL;
290+
X509_NAME *subject = NULL;
291+
X509_NAME_ENTRY *name_entry = NULL;
292+
X509_EXTENSION *ext = NULL;
293+
X509V3_CTX ctx;
294+
const STACK_OF(X509_EXTENSION) *exts;
295+
ASN1_OCTET_STRING *encoded;
296+
int ret = 0;
297+
298+
if (!TEST_ptr(x = X509_new())
299+
|| !TEST_int_eq(X509_set_version(x, X509_VERSION_3), 1)
300+
|| !TEST_int_eq(ASN1_INTEGER_set(X509_get_serialNumber(x), 1), 1)
301+
|| !TEST_ptr(subject = X509_NAME_new()))
302+
goto err;
303+
304+
name_entry = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName,
305+
MBSTRING_ASC, commonName, -1);
306+
if (!TEST_ptr(name_entry)
307+
|| !TEST_int_eq(X509_NAME_add_entry(subject, name_entry, -1, 0), 1)
308+
|| !TEST_int_eq(X509_set_subject_name(x, subject), 1)
309+
|| !TEST_int_eq(X509_set_issuer_name(x, subject), 1)
310+
|| !TEST_ptr(X509_gmtime_adj(X509_getm_notBefore(x), 0))
311+
|| !TEST_ptr(X509_gmtime_adj(X509_getm_notAfter(x), 24 * 3600))
312+
|| !TEST_int_eq(X509_set_pubkey(x, pubkey), 1))
313+
goto err;
314+
315+
X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
316+
/*
317+
* By not calling X509V3_set_issuer_pkey(&ctx, privkey);
318+
* here, we are exempt from the 3.x convention, regarding
319+
* the authorityKeyIdentifier=keyid,issuer which may return
320+
* an empty extension for self signed certificates.
321+
* Therefore an empty extension cannot be produced here.
322+
*/
323+
if (!TEST_ptr(ext = X509V3_EXT_conf(NULL, &ctx, "subjectKeyIdentifier",
324+
"hash"))
325+
|| !TEST_int_eq(X509_add_ext(x, ext, -1), 1))
326+
goto err;
327+
328+
X509_EXTENSION_free(ext);
329+
if (!TEST_ptr(ext = X509V3_EXT_conf(NULL, &ctx, "authorityKeyIdentifier",
330+
"keyid,issuer"))
331+
|| !TEST_int_eq(X509_add_ext(x, ext, -1), 1))
332+
goto err;
333+
334+
if (!TEST_int_gt(X509_sign(x, privkey, signmd), 0)
335+
|| !TEST_int_gt(X509_verify(x, pubkey), 0))
336+
goto err;
337+
338+
exts = X509_get0_extensions(x);
339+
if (!TEST_ptr(exts)
340+
|| !TEST_int_eq(sk_X509_EXTENSION_num(exts), 2))
341+
goto err;
342+
343+
encoded = X509_EXTENSION_get_data(X509v3_get_ext(exts, 0));
344+
if (!TEST_ptr(encoded)
345+
|| !TEST_int_gt(ASN1_STRING_length(encoded), 2))
346+
goto err;
347+
348+
encoded = X509_EXTENSION_get_data(X509v3_get_ext(exts, 1));
349+
if (!TEST_ptr(encoded)
350+
|| !TEST_int_gt(ASN1_STRING_length(encoded), 2))
351+
goto err;
352+
353+
ret = 1;
354+
355+
err:
356+
X509_NAME_ENTRY_free(name_entry);
357+
X509_NAME_free(subject);
358+
X509_EXTENSION_free(ext);
359+
X509_free(x);
360+
return ret;
361+
}
362+
285363
OPT_TEST_DECLARE_USAGE("<pss-self-signed-cert.pem>\n")
286364

287365
int setup_tests(void)
@@ -319,6 +397,7 @@ int setup_tests(void)
319397
ADD_TEST(test_x509_delete_last_extension);
320398
ADD_TEST(test_x509_crl_delete_last_extension);
321399
ADD_TEST(test_x509_revoked_delete_last_extension);
400+
ADD_TEST(test_x509_old_abi_compat_mode_extension);
322401
return 1;
323402
}
324403

0 commit comments

Comments
 (0)