]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
fecb3aae | 2 | * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. |
175b0942 | 3 | * |
4286ca47 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
175b0942 DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
ec577822 BM |
12 | #include <openssl/conf.h> |
13 | #include <openssl/asn1.h> | |
9d6b1ce6 | 14 | #include <openssl/asn1t.h> |
ec577822 | 15 | #include <openssl/x509v3.h> |
41e597a0 | 16 | #include "crypto/x509.h" |
df2ee0e2 | 17 | #include "ext_dat.h" |
175b0942 | 18 | |
ba404b5e | 19 | static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, |
0f113f3e MC |
20 | AUTHORITY_KEYID *akeyid, |
21 | STACK_OF(CONF_VALUE) | |
22 | *extlist); | |
ba404b5e | 23 | static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, |
0f113f3e MC |
24 | X509V3_CTX *ctx, |
25 | STACK_OF(CONF_VALUE) *values); | |
26 | ||
47864aea | 27 | const X509V3_EXT_METHOD ossl_v3_akey_id = { |
0f113f3e MC |
28 | NID_authority_key_identifier, |
29 | X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID), | |
30 | 0, 0, 0, 0, | |
31 | 0, 0, | |
32 | (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID, | |
33 | (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, | |
34 | 0, 0, | |
35 | NULL | |
36 | }; | |
175b0942 | 37 | |
ba404b5e | 38 | static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, |
0f113f3e MC |
39 | AUTHORITY_KEYID *akeyid, |
40 | STACK_OF(CONF_VALUE) | |
41 | *extlist) | |
175b0942 | 42 | { |
4b8a8bb7 MC |
43 | char *tmp = NULL; |
44 | STACK_OF(CONF_VALUE) *origextlist = extlist, *tmpextlist; | |
45 | ||
0f113f3e | 46 | if (akeyid->keyid) { |
a3ea35c2 | 47 | tmp = i2s_ASN1_OCTET_STRING(NULL, akeyid->keyid); |
17197a2f MC |
48 | if (tmp == NULL) { |
49 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); | |
50 | return NULL; | |
51 | } | |
4b8a8bb7 MC |
52 | if (!X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL, |
53 | tmp, &extlist)) { | |
54 | OPENSSL_free(tmp); | |
55 | ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB); | |
56 | goto err; | |
57 | } | |
0f113f3e MC |
58 | OPENSSL_free(tmp); |
59 | } | |
4b8a8bb7 MC |
60 | if (akeyid->issuer) { |
61 | tmpextlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); | |
62 | if (tmpextlist == NULL) { | |
63 | ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB); | |
64 | goto err; | |
65 | } | |
66 | extlist = tmpextlist; | |
67 | } | |
0f113f3e | 68 | if (akeyid->serial) { |
a3ea35c2 | 69 | tmp = i2s_ASN1_OCTET_STRING(NULL, akeyid->serial); |
17197a2f MC |
70 | if (tmp == NULL) { |
71 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); | |
4b8a8bb7 MC |
72 | goto err; |
73 | } | |
74 | if (!X509V3_add_value("serial", tmp, &extlist)) { | |
75 | OPENSSL_free(tmp); | |
76 | goto err; | |
17197a2f | 77 | } |
0f113f3e MC |
78 | OPENSSL_free(tmp); |
79 | } | |
80 | return extlist; | |
4b8a8bb7 MC |
81 | err: |
82 | if (origextlist == NULL) | |
83 | sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free); | |
84 | return NULL; | |
175b0942 DSH |
85 | } |
86 | ||
c80fd6b2 | 87 | /*- |
6e98b7f1 DDO |
88 | * Three explicit tags may be given, where 'keyid' and 'issuer' may be combined: |
89 | * 'none': do not add any authority key identifier. | |
90 | * 'keyid': use the issuer's subject keyid; the option 'always' means its is | |
91 | * an error if the issuer certificate doesn't have a subject key id. | |
92 | * 'issuer': use the issuer's cert issuer and serial number. The default is | |
93 | * to only use this if 'keyid' is not present. With the option 'always' | |
0be9747b DSH |
94 | * this is always included. |
95 | */ | |
6b691a5c | 96 | static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, |
0f113f3e MC |
97 | X509V3_CTX *ctx, |
98 | STACK_OF(CONF_VALUE) *values) | |
99 | { | |
100 | char keyid = 0, issuer = 0; | |
ec2bfb7d | 101 | int i, n = sk_CONF_VALUE_num(values); |
0f113f3e MC |
102 | CONF_VALUE *cnf; |
103 | ASN1_OCTET_STRING *ikeyid = NULL; | |
104 | X509_NAME *isname = NULL; | |
105 | GENERAL_NAMES *gens = NULL; | |
106 | GENERAL_NAME *gen = NULL; | |
107 | ASN1_INTEGER *serial = NULL; | |
108 | X509_EXTENSION *ext; | |
41e597a0 | 109 | X509 *issuer_cert; |
9bf1061c | 110 | int same_issuer, ss; |
8ca661ab DDO |
111 | AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new(); |
112 | ||
113 | if (akeyid == NULL) | |
114 | goto err; | |
0f113f3e | 115 | |
ec2bfb7d DDO |
116 | if (n == 1 && strcmp(sk_CONF_VALUE_value(values, 0)->name, "none") == 0) { |
117 | return akeyid; | |
118 | } | |
119 | ||
120 | for (i = 0; i < n; i++) { | |
0f113f3e | 121 | cnf = sk_CONF_VALUE_value(values, i); |
6e98b7f1 DDO |
122 | if (cnf->value != NULL && strcmp(cnf->value, "always") != 0) { |
123 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION, | |
124 | "name=%s option=%s", cnf->name, cnf->value); | |
125 | goto err; | |
126 | } | |
127 | if (strcmp(cnf->name, "keyid") == 0 && keyid == 0) { | |
0f113f3e | 128 | keyid = 1; |
6e98b7f1 | 129 | if (cnf->value != NULL) |
0f113f3e | 130 | keyid = 2; |
6e98b7f1 | 131 | } else if (strcmp(cnf->name, "issuer") == 0 && issuer == 0) { |
0f113f3e | 132 | issuer = 1; |
6e98b7f1 | 133 | if (cnf->value != NULL) |
0f113f3e | 134 | issuer = 2; |
6e98b7f1 DDO |
135 | } else if (strcmp(cnf->name, "none") == 0 |
136 | || strcmp(cnf->name, "keyid") == 0 | |
137 | || strcmp(cnf->name, "issuer") == 0) { | |
138 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_VALUE, | |
139 | "name=%s", cnf->name); | |
140 | goto err; | |
0f113f3e | 141 | } else { |
6e98b7f1 | 142 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_VALUE, |
a150f8e1 | 143 | "name=%s", cnf->name); |
8ca661ab | 144 | goto err; |
0f113f3e MC |
145 | } |
146 | } | |
147 | ||
2ed63033 | 148 | if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0) |
41e597a0 DDO |
149 | return akeyid; |
150 | ||
151 | if (ctx == NULL) { | |
152 | ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER); | |
153 | goto err; | |
154 | } | |
155 | if ((issuer_cert = ctx->issuer_cert) == NULL) { | |
9311d0c4 | 156 | ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_CERTIFICATE); |
8ca661ab | 157 | goto err; |
0f113f3e | 158 | } |
9bf1061c DDO |
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(); | |
0f113f3e | 166 | |
9bf1061c DDO |
167 | /* unless forced with "always", AKID is suppressed for self-signed certs */ |
168 | if (keyid == 2 || (keyid == 1 && !ss)) { | |
169 | /* | |
170 | * 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 | |
172 | */ | |
41e597a0 | 173 | i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1); |
9bf1061c | 174 | if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL |
adbd77f6 | 175 | && !(same_issuer && !ss)) { |
0f113f3e | 176 | ikeyid = X509V3_EXT_d2i(ext); |
adbd77f6 DDO |
177 | if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ { |
178 | ASN1_OCTET_STRING_free(ikeyid); | |
179 | ikeyid = NULL; | |
180 | } | |
181 | } | |
9bf1061c DDO |
182 | if (ikeyid == NULL && same_issuer && ctx->issuer_pkey != NULL) { |
183 | /* generate fallback AKID, emulating s2i_skey_id(..., "hash") */ | |
41e597a0 DDO |
184 | X509_PUBKEY *pubkey = NULL; |
185 | ||
186 | if (X509_PUBKEY_set(&pubkey, ctx->issuer_pkey)) | |
47864aea | 187 | ikeyid = ossl_x509_pubkey_hash(pubkey); |
41e597a0 DDO |
188 | X509_PUBKEY_free(pubkey); |
189 | } | |
adbd77f6 | 190 | if (keyid == 2 && ikeyid == NULL) { |
9311d0c4 | 191 | ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); |
8ca661ab | 192 | goto err; |
0f113f3e MC |
193 | } |
194 | } | |
195 | ||
adbd77f6 | 196 | if (issuer == 2 || (issuer == 1 && !ss && ikeyid == NULL)) { |
41e597a0 DDO |
197 | isname = X509_NAME_dup(X509_get_issuer_name(issuer_cert)); |
198 | serial = ASN1_INTEGER_dup(X509_get0_serialNumber(issuer_cert)); | |
199 | if (isname == NULL || serial == NULL) { | |
9311d0c4 | 200 | ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); |
0f113f3e MC |
201 | goto err; |
202 | } | |
203 | } | |
204 | ||
41e597a0 | 205 | if (isname != NULL) { |
75ebbd9a RS |
206 | if ((gens = sk_GENERAL_NAME_new_null()) == NULL |
207 | || (gen = GENERAL_NAME_new()) == NULL | |
0f113f3e | 208 | || !sk_GENERAL_NAME_push(gens, gen)) { |
9311d0c4 | 209 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
210 | goto err; |
211 | } | |
212 | gen->type = GEN_DIRNAME; | |
213 | gen->d.dirn = isname; | |
214 | } | |
215 | ||
216 | akeyid->issuer = gens; | |
97323d57 MC |
217 | gen = NULL; |
218 | gens = NULL; | |
0f113f3e MC |
219 | akeyid->serial = serial; |
220 | akeyid->keyid = ikeyid; | |
221 | ||
222 | return akeyid; | |
8382ec5d RL |
223 | |
224 | err: | |
97323d57 MC |
225 | sk_GENERAL_NAME_free(gens); |
226 | GENERAL_NAME_free(gen); | |
0f113f3e | 227 | X509_NAME_free(isname); |
f422a514 DSH |
228 | ASN1_INTEGER_free(serial); |
229 | ASN1_OCTET_STRING_free(ikeyid); | |
8ca661ab | 230 | AUTHORITY_KEYID_free(akeyid); |
0f113f3e MC |
231 | return NULL; |
232 | } |