summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-06-17 05:31:26 +0000
committertb <>2024-06-17 05:31:26 +0000
commit1cce7a8778d5b86a020d7d0546bc2401506d5117 (patch)
tree528a222420b347d3261eacb9ebc8744a2aea9e43 /src
parent8d9a11036e953db2041151dae4ab5fd4c82a8608 (diff)
downloadopenbsd-1cce7a8778d5b86a020d7d0546bc2401506d5117.tar.gz
openbsd-1cce7a8778d5b86a020d7d0546bc2401506d5117.tar.bz2
openbsd-1cce7a8778d5b86a020d7d0546bc2401506d5117.zip
Rewrite X509V3_get_d2i()
This API is wrapped by nine *_get{,1}_ext_d2i() functions and they all have the same defect: if an idx variable is passed in, multiple extensions are handled incorrectly. Clean up the mess that was the current implementation by replacing the reimplementation of X509v3_get_ext_by_NID() with extra twists by actual calls to the real thing. This way the madness is implemented explicitly and can be explained in comments. The code still gets shorter. In brief: always call this API with a known nid, pass crit, and a NULL idx. If NULL is returned, crit != -1 is an error (malformed cert or allocation failure). ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/x509/x509_lib.c103
1 files changed, 47 insertions, 56 deletions
diff --git a/src/lib/libcrypto/x509/x509_lib.c b/src/lib/libcrypto/x509/x509_lib.c
index 4347875885..161e638427 100644
--- a/src/lib/libcrypto/x509/x509_lib.c
+++ b/src/lib/libcrypto/x509/x509_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_lib.c,v 1.21 2024/05/28 15:40:38 tb Exp $ */ 1/* $OpenBSD: x509_lib.c,v 1.22 2024/06/17 05:31:26 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 1999. 3 * project 1999.
4 */ 4 */
@@ -178,69 +178,60 @@ X509V3_EXT_d2i(X509_EXTENSION *ext)
178} 178}
179LCRYPTO_ALIAS(X509V3_EXT_d2i); 179LCRYPTO_ALIAS(X509V3_EXT_d2i);
180 180
181/* Get critical flag and decoded version of extension from a NID. 181/*
182 * The "idx" variable returns the last found extension and can 182 * This API is only safe to call with known nid, crit != NULL and idx == NULL.
183 * be used to retrieve multiple extensions of the same NID. 183 * On NULL return, crit acts as a failure indicator: crit == -1 means an
184 * However multiple extensions with the same NID is usually 184 * extension of type nid was not present, crit != -1 is fatal: crit == -2
185 * due to a badly encoded certificate so if idx is NULL we 185 * means multiple extensions of type nid are present; if crit is 0 or 1, this
186 * choke if multiple extensions exist. 186 * implies the extension was found but could not be decoded.
187 * The "crit" variable is set to the critical value.
188 * The return value is the decoded extension or NULL on
189 * error. The actual error can have several different causes,
190 * the value of *crit reflects the cause:
191 * >= 0, extension found but not decoded (reflects critical value).
192 * -1 extension not found.
193 * -2 extension occurs more than once.
194 */ 187 */
195 188
196void * 189void *
197X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx) 190X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
198{ 191{
199 int lastpos, i; 192 X509_EXTENSION *ext;
200 X509_EXTENSION *ex, *found_ex = NULL; 193 int lastpos = idx == NULL ? -1 : *idx;
201 194
202 if (!x) { 195 if (crit != NULL)
203 if (idx) 196 *crit = -1;
204 *idx = -1; 197 if (idx != NULL)
205 if (crit) 198 *idx = -1;
206 *crit = -1; 199
200 /*
201 * Nothing to do if no extensions, unknown nid, or missing extension.
202 */
203
204 if (x == NULL)
205 return NULL;
206 if ((lastpos = X509v3_get_ext_by_NID(x, nid, lastpos)) < 0)
207 return NULL;
208 if ((ext = X509v3_get_ext(x, lastpos)) == NULL)
209 return NULL;
210
211 /*
212 * API madness. Only check for a second extension of type nid if
213 * idx == NULL. Indicate this by setting *crit to -2. If idx != NULL,
214 * don't care and set *idx to the index of the first extension found.
215 */
216
217 if (idx == NULL && X509v3_get_ext_by_NID(x, nid, lastpos) > 0) {
218 if (crit != NULL)
219 *crit = -2;
207 return NULL; 220 return NULL;
208 }
209 if (idx)
210 lastpos = *idx + 1;
211 else
212 lastpos = 0;
213 if (lastpos < 0)
214 lastpos = 0;
215 for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
216 ex = sk_X509_EXTENSION_value(x, i);
217 if (OBJ_obj2nid(ex->object) == nid) {
218 if (idx) {
219 *idx = i;
220 found_ex = ex;
221 break;
222 } else if (found_ex) {
223 /* Found more than one */
224 if (crit)
225 *crit = -2;
226 return NULL;
227 }
228 found_ex = ex;
229 }
230 }
231 if (found_ex) {
232 /* Found it */
233 if (crit)
234 *crit = X509_EXTENSION_get_critical(found_ex);
235 return X509V3_EXT_d2i(found_ex);
236 } 221 }
237 222
238 /* Extension not found */ 223 /*
239 if (idx) 224 * Another beautiful API detail: *crit will be set to 0 or 1, so if the
240 *idx = -1; 225 * extension fails to decode, we can deduce this from return value NULL
241 if (crit) 226 * and crit != -1.
242 *crit = -1; 227 */
243 return NULL; 228
229 if (crit != NULL)
230 *crit = X509_EXTENSION_get_critical(ext);
231 if (idx != NULL)
232 *idx = lastpos;
233
234 return X509V3_EXT_d2i(ext);
244} 235}
245LCRYPTO_ALIAS(X509V3_get_d2i); 236LCRYPTO_ALIAS(X509V3_get_d2i);
246 237