Skip to content

Commit d9dc08b

Browse files
Fix empty AKID/SKID handling
in all kinds of self-signed and non-self-signed X509, CSR, CRLs. The default, when not defined by config for self-signed X509 is: subjectKeyIdentifier=hash authorityKeyIdentifier=none For non-self-signed X509 it is: subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer For CSR and CRLs the default is: subjectKeyIdentifier=none authorityKeyIdentifier=none When defined by config the SKID=none or AKID=none must delete any prior definition of the same OID.
1 parent 6715dde commit d9dc08b

File tree

14 files changed

+143
-80
lines changed

14 files changed

+143
-80
lines changed

apps/ca.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,13 +1691,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
16911691
ret, NULL /* no need to give req, needed info is in ret */,
16921692
NULL, X509V3_CTX_REPLACE);
16931693
/* prepare fallback for AKID, but only if issuer cert equals subject cert */
1694-
if (selfsign) {
1694+
if (selfsign && !cert_matches_key(ret, pkey)) {
16951695
if (!X509V3_set_issuer_pkey(&ext_ctx, pkey))
16961696
goto end;
1697-
if (!cert_matches_key(ret, pkey))
1698-
BIO_printf(bio_err,
1699-
"Warning: Signature key and public key of cert do not match\n");
1697+
BIO_printf(bio_err,
1698+
"Warning: Signature key and public key of cert do not match\n");
17001699
}
1700+
if (!add_X509_default_keyids(ret, pkey, &ext_ctx))
1701+
goto end;
17011702

17021703
/* Lets add the extensions, if there are any */
17031704
if (ext_sect) {

apps/include/apps.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ int init_gen_str(EVP_PKEY_CTX **pctx,
284284
const char *algname, ENGINE *e, int do_param,
285285
OSSL_LIB_CTX *libctx, const char *propq);
286286
int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey);
287+
int add_X509_default_keyids(X509 *x, EVP_PKEY *pkey, X509V3_CTX *ext_ctx);
287288
int do_X509_sign(X509 *x, int force_v1, EVP_PKEY *pkey, const char *md,
288289
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx);
289290
int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts);

apps/lib/apps.c

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,28 +2300,24 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
23002300
}
23012301

23022302
static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
2303-
const char *name, const char *value, int add_default)
2303+
const char *name, const char *value)
23042304
{
23052305
const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
23062306
X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value);
2307-
int idx, rv = 0;
2307+
ASN1_OCTET_STRING *encoded;
2308+
int disabled, idx, rv = 0;
23082309

23092310
if (new_ext == NULL)
23102311
return rv;
23112312

23122313
idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
23132314
if (idx >= 0) {
2314-
X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
2315-
ASN1_OCTET_STRING *encoded = X509_EXTENSION_get_data(found_ext);
2316-
int disabled = ASN1_STRING_length(encoded) <= 2; /* indicating "none" */
2317-
2318-
if (disabled) {
2319-
X509_delete_ext(cert, idx);
2320-
X509_EXTENSION_free(found_ext);
2321-
} /* else keep existing key identifier, which might be outdated */
2315+
/* keep existing key identifier, which might be outdated */
23222316
rv = 1;
23232317
} else {
2324-
rv = !add_default || X509_add_ext(cert, new_ext, -1);
2318+
encoded = X509_EXTENSION_get_data(new_ext);
2319+
disabled = ASN1_STRING_length(encoded) <= 2; /* indicating "none" */
2320+
rv = disabled || X509_add_ext(cert, new_ext, -1);
23252321
}
23262322
X509_EXTENSION_free(new_ext);
23272323
return rv;
@@ -2337,30 +2333,40 @@ int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey)
23372333
return match;
23382334
}
23392335

2340-
/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
2336+
/* Add default keyIDs as needed */
2337+
int add_X509_default_keyids(X509 *cert, EVP_PKEY *pkey, X509V3_CTX *ext_ctx)
2338+
{
2339+
int self_sign = 0;
2340+
int rv = 0;
2341+
2342+
/*
2343+
* Add default SKID before AKID such that AKID can make use of it
2344+
* in case the certificate is self-signed
2345+
*/
2346+
if (X509_get_extension_flags(cert) & EXFLAG_SI)
2347+
self_sign = cert_matches_key(cert, pkey);
2348+
/* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
2349+
if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash"))
2350+
goto end;
2351+
/* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
2352+
if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
2353+
self_sign ? "none" : "keyid, issuer"))
2354+
goto end;
2355+
rv = 1;
2356+
end:
2357+
return rv;
2358+
}
2359+
2360+
/* Ensure RFC 5280 compliance, and sign the cert info */
23412361
int do_X509_sign(X509 *cert, int force_v1, EVP_PKEY *pkey, const char *md,
23422362
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
23432363
{
23442364
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
2345-
int self_sign;
23462365
int rv = 0;
23472366

23482367
if (!force_v1) {
23492368
if (!X509_set_version(cert, X509_VERSION_3))
23502369
goto end;
2351-
2352-
/*
2353-
* Add default SKID before AKID such that AKID can make use of it
2354-
* in case the certificate is self-signed
2355-
*/
2356-
/* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
2357-
if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
2358-
goto end;
2359-
/* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
2360-
self_sign = cert_matches_key(cert, pkey);
2361-
if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
2362-
"keyid, issuer", !self_sign))
2363-
goto end;
23642370
}
23652371
/* May add further measures for ensuring RFC 5280 compliance, see #19805 */
23662372

apps/req.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -847,13 +847,14 @@ int req_main(int argc, char **argv)
847847
X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509,
848848
new_x509, NULL, NULL, X509V3_CTX_REPLACE);
849849
/* prepare fallback for AKID, but only if issuer cert == new_x509 */
850-
if (CAcert == NULL) {
850+
if (CAcert == NULL && !cert_matches_key(new_x509, issuer_key)) {
851851
if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key))
852852
goto end;
853-
if (!cert_matches_key(new_x509, issuer_key))
854-
BIO_printf(bio_err,
855-
"Warning: Signature key and public key of cert do not match\n");
853+
BIO_printf(bio_err,
854+
"Warning: Signature key and public key of cert do not match\n");
856855
}
856+
if (!x509v1 && !add_X509_default_keyids(new_x509, issuer_key, &ext_ctx))
857+
goto end;
857858
X509V3_set_nconf(&ext_ctx, req_conf);
858859

859860
/* Add extensions */

apps/x509.c

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -896,23 +896,6 @@ int x509_main(int argc, char **argv)
896896
}
897897
}
898898

899-
X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
900-
/* prepare fallback for AKID, but only if issuer cert equals subject cert */
901-
if (CAfile == NULL) {
902-
if (!X509V3_set_issuer_pkey(&ext_ctx, privkey))
903-
goto err;
904-
}
905-
if (extconf != NULL && !x509toreq) {
906-
X509V3_set_nconf(&ext_ctx, extconf);
907-
if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
908-
BIO_printf(bio_err,
909-
"Error adding extensions from section %s\n", extsect);
910-
goto err;
911-
}
912-
}
913-
914-
/* At this point the contents of the certificate x have been finished. */
915-
916899
pkey = X509_get0_pubkey(x);
917900
if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) {
918901
BIO_printf(bio_err, "Error getting public key\n");
@@ -930,6 +913,7 @@ int x509_main(int argc, char **argv)
930913
}
931914
if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL)
932915
goto err;
916+
X509V3_set_ctx(&ext_ctx, NULL, NULL, rq, NULL, X509V3_CTX_REPLACE);
933917
if (extconf != NULL) {
934918
X509V3_set_nconf(&ext_ctx, extconf);
935919
if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) {
@@ -964,9 +948,36 @@ int x509_main(int argc, char **argv)
964948
goto err;
965949
}
966950

951+
X509V3_set_ctx(&ext_ctx, xca, x, NULL, NULL, X509V3_CTX_REPLACE);
952+
if (!add_X509_default_keyids(x, CAkey, &ext_ctx))
953+
goto err;
954+
if (extconf != NULL) {
955+
X509V3_set_nconf(&ext_ctx, extconf);
956+
if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
957+
BIO_printf(bio_err,
958+
"Error adding extensions from section %s\n", extsect);
959+
goto err;
960+
}
961+
}
967962
if (!do_X509_sign(x, 0, CAkey, digest, sigopts, &ext_ctx))
968963
goto err;
969964
} else if (privkey != NULL) {
965+
X509V3_set_ctx(&ext_ctx, x, x, NULL, NULL, X509V3_CTX_REPLACE);
966+
/* prepare fallback for AKID, but only if issuer cert equals subject cert */
967+
if (!cert_matches_key(x, privkey)) {
968+
if (!X509V3_set_issuer_pkey(&ext_ctx, privkey))
969+
goto err;
970+
}
971+
if (!add_X509_default_keyids(x, privkey, &ext_ctx))
972+
goto err;
973+
if (extconf != NULL) {
974+
X509V3_set_nconf(&ext_ctx, extconf);
975+
if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
976+
BIO_printf(bio_err,
977+
"Error adding extensions from section %s\n", extsect);
978+
goto err;
979+
}
980+
}
970981
if (!do_X509_sign(x, 0, privkey, digest, sigopts, &ext_ctx))
971982
goto err;
972983
}

crypto/cmp/cmp_msg.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ X509_PUBKEY *OSSL_CMP_MSG_get0_certreq_publickey(const OSSL_CMP_MSG *msg)
127127
static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
128128
{
129129
X509_EXTENSION *ext;
130+
int idx;
130131
int res;
131132

132133
if (!ossl_assert(pexts != NULL)) /* pointer to var must not be NULL */
@@ -135,6 +136,9 @@ static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
135136
if ((ext = X509V3_EXT_i2d(nid, crit, ex)) == NULL)
136137
return 0;
137138

139+
while ((idx = X509v3_get_ext_by_NID(*pexts, nid, -1)) >= 0)
140+
X509_EXTENSION_free(X509v3_delete_ext(*pexts, idx));
141+
138142
res = X509v3_add_ext(pexts, ext, 0) != NULL;
139143
X509_EXTENSION_free(ext);
140144
return res;
@@ -327,6 +331,8 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
327331
if (ctx->p10CSR != NULL
328332
&& (exts = X509_REQ_get_extensions(ctx->p10CSR)) == NULL)
329333
goto err;
334+
if (exts == NULL && (exts = sk_X509_EXTENSION_new_null()) == NULL)
335+
goto err;
330336
if (!ctx->SubjectAltName_nodefault && !HAS_SAN(ctx) && refcert != NULL
331337
&& (default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
332338
NID_subject_alt_name, NULL, NULL))

crypto/x509/v3_akid.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,8 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
171171
X509_PUBKEY_free(pubkey);
172172
} else {
173173
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) {
174+
if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL)
175175
ikeyid = X509V3_EXT_d2i(ext);
176-
if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ {
177-
ASN1_OCTET_STRING_free(ikeyid);
178-
ikeyid = NULL;
179-
}
180-
}
181176
}
182177
if (keyid == 2 && ikeyid == NULL) {
183178
ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);

crypto/x509/v3_conf.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,18 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
340340
val->name, val->value)) == NULL)
341341
return 0;
342342
if (sk != NULL) {
343-
if (ctx->flags == X509V3_CTX_REPLACE)
343+
if ((ctx->flags & X509V3_CTX_REPLACE) != 0)
344344
delete_ext(*sk, ext);
345-
if (X509v3_add_ext(sk, ext, -1) == NULL) {
346-
X509_EXTENSION_free(ext);
347-
return 0;
345+
if ((ctx->flags & X509V3_CTX_REPLACE) == 0
346+
|| ctx->subject_req != NULL || (i != akid && i != skid)
347+
|| ASN1_STRING_length(X509_EXTENSION_get_data(ext)) > 2) {
348+
if (X509v3_add_ext(sk, ext, -1) == NULL) {
349+
X509_EXTENSION_free(ext);
350+
return 0;
351+
}
352+
} else if (*sk != NULL && sk_X509_EXTENSION_num(*sk) == 0) {
353+
sk_X509_EXTENSION_free(*sk);
354+
*sk = NULL;
348355
}
349356
}
350357
X509_EXTENSION_free(ext);

crypto/x509/x509_req.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(const X509_REQ *req)
160160

161161
/*
162162
* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
163-
* in case we want to create a non standard one.
163+
* in case we want to create a non standard one. If there are already
164+
* extensions with the same OID, replace them with the new ones.
164165
*/
165166
int X509_REQ_add_extensions_nid(X509_REQ *req,
166167
const STACK_OF(X509_EXTENSION) *exts, int nid)
@@ -178,24 +179,32 @@ int X509_REQ_add_extensions_nid(X509_REQ *req,
178179
if (loc != -1) {
179180
if ((mod_exts = get_extensions_by_nid(req, nid)) == NULL)
180181
return 0;
181-
if (X509v3_add_extensions(&mod_exts, exts) == NULL)
182-
goto end;
182+
} else {
183+
if ((mod_exts = sk_X509_EXTENSION_new_null()) == NULL)
184+
return 0;
183185
}
184186

185-
/* Generate encoding of extensions */
186-
extlen = ASN1_item_i2d((const ASN1_VALUE *)
187-
(mod_exts == NULL ? exts : mod_exts),
188-
&ext, ASN1_ITEM_rptr(X509_EXTENSIONS));
189-
if (extlen <= 0)
187+
if (X509v3_add_extensions(&mod_exts, exts) == NULL)
190188
goto end;
191-
if (mod_exts != NULL) {
189+
190+
if (loc != -1) {
192191
X509_ATTRIBUTE *att = X509at_delete_attr(req->req_info.attributes, loc);
193192

194193
if (att == NULL)
195194
goto end;
196195
X509_ATTRIBUTE_free(att);
197196
}
198197

198+
if (sk_X509_EXTENSION_num(mod_exts) == 0) {
199+
rv = 1;
200+
goto end;
201+
}
202+
203+
/* Generate encoding of extensions */
204+
extlen = ASN1_item_i2d((const ASN1_VALUE *)mod_exts,
205+
&ext, ASN1_ITEM_rptr(X509_EXTENSIONS));
206+
if (extlen <= 0)
207+
goto end;
199208
rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen);
200209
OPENSSL_free(ext);
201210

crypto/x509/x509_v3.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ STACK_OF(X509_EXTENSION) *X509v3_add_extensions(STACK_OF(X509_EXTENSION) **targe
156156
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
157157
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
158158
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
159+
ASN1_OCTET_STRING *encoded = X509_EXTENSION_get_data(ext);
159160
int idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
160161

161162
/* Does extension exist in target? */
@@ -166,6 +167,15 @@ STACK_OF(X509_EXTENSION) *X509v3_add_extensions(STACK_OF(X509_EXTENSION) **targe
166167
idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
167168
} while (idx != -1);
168169
}
170+
switch (OBJ_obj2nid(obj)) {
171+
case NID_subject_key_identifier:
172+
case NID_authority_key_identifier:
173+
if (ASN1_STRING_length(encoded) <= 2) /* indicating "none" */
174+
continue;
175+
break;
176+
default:
177+
break;
178+
}
169179
if (!X509v3_add_ext(target, ext, -1))
170180
return NULL;
171181
}

0 commit comments

Comments
 (0)