summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorguenther <>2014-08-08 04:53:43 +0000
committerguenther <>2014-08-08 04:53:43 +0000
commitc6985e683db078656f9f4ec499be1ef35bdce285 (patch)
tree3d49e2ab368dd2c4623345f392a9a87627e2d9ff /src/lib
parent32554492a8d665d7c0517b374f2ea31089caa176 (diff)
downloadopenbsd-c6985e683db078656f9f4ec499be1ef35bdce285.tar.gz
openbsd-c6985e683db078656f9f4ec499be1ef35bdce285.tar.bz2
openbsd-c6985e683db078656f9f4ec499be1ef35bdce285.zip
Fix CVE-2014-3508, pretty printing and OID validation:
- make sure the output buffer is always NUL terminated if buf_len was initially greater than zero. - reject OIDs that are too long, too short, or not in proper base-127 Based on https://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=0042fb5fd1c9d257d713b15a1f45da05cf5c1c87 ok bcook@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/asn1/a_object.c31
-rw-r--r--src/lib/libcrypto/objects/obj_dat.c9
-rw-r--r--src/lib/libssl/src/crypto/asn1/a_object.c31
-rw-r--r--src/lib/libssl/src/crypto/objects/obj_dat.c9
4 files changed, 56 insertions, 24 deletions
diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c
index 863aa6a226..2cb5a0097b 100644
--- a/src/lib/libcrypto/asn1/a_object.c
+++ b/src/lib/libcrypto/asn1/a_object.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_object.c,v 1.22 2014/07/12 16:03:36 miod Exp $ */ 1/* $OpenBSD: a_object.c,v 1.23 2014/08/08 04:53:43 guenther Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -281,12 +281,23 @@ c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
281 ASN1_OBJECT *ret = NULL; 281 ASN1_OBJECT *ret = NULL;
282 const unsigned char *p; 282 const unsigned char *p;
283 unsigned char *data; 283 unsigned char *data;
284 int i; 284 int i, length;
285 285
286 /* Sanity check OID encoding: can't have leading 0x80 in 286 /*
287 * subidentifiers, see: X.690 8.19.2 287 * Sanity check OID encoding:
288 * - need at least one content octet
289 * - MSB must be clear in the last octet
290 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
288 */ 291 */
289 for (i = 0, p = *pp; i < len; i++, p++) { 292 if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
293 p[len - 1] & 0x80) {
294 ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
295 return (NULL);
296 }
297
298 /* Now 0 < len <= INT_MAX, so the cast is safe. */
299 length = (int)len;
300 for (i = 0; i < length; i++, p++) {
290 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { 301 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
291 ASN1err(ASN1_F_C2I_ASN1_OBJECT, 302 ASN1err(ASN1_F_C2I_ASN1_OBJECT,
292 ASN1_R_INVALID_OBJECT_ENCODING); 303 ASN1_R_INVALID_OBJECT_ENCODING);
@@ -308,24 +319,24 @@ c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
308 data = (unsigned char *)ret->data; 319 data = (unsigned char *)ret->data;
309 ret->data = NULL; 320 ret->data = NULL;
310 /* once detached we can change it */ 321 /* once detached we can change it */
311 if ((data == NULL) || (ret->length < len)) { 322 if ((data == NULL) || (ret->length < length)) {
312 ret->length = 0; 323 ret->length = 0;
313 free(data); 324 free(data);
314 data = malloc(len ? len : 1); 325 data = malloc(length);
315 if (data == NULL) { 326 if (data == NULL) {
316 i = ERR_R_MALLOC_FAILURE; 327 i = ERR_R_MALLOC_FAILURE;
317 goto err; 328 goto err;
318 } 329 }
319 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 330 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
320 } 331 }
321 memcpy(data, p, len); 332 memcpy(data, p, length);
322 /* reattach data to object, after which it remains const */ 333 /* reattach data to object, after which it remains const */
323 ret->data = data; 334 ret->data = data;
324 ret->length = (int)len; 335 ret->length = length;
325 ret->sn = NULL; 336 ret->sn = NULL;
326 ret->ln = NULL; 337 ret->ln = NULL;
327 /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ 338 /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
328 p += len; 339 p += length;
329 340
330 if (a != NULL) 341 if (a != NULL)
331 (*a) = ret; 342 (*a) = ret;
diff --git a/src/lib/libcrypto/objects/obj_dat.c b/src/lib/libcrypto/objects/obj_dat.c
index 071febba52..15c298e333 100644
--- a/src/lib/libcrypto/objects/obj_dat.c
+++ b/src/lib/libcrypto/objects/obj_dat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: obj_dat.c,v 1.30 2014/07/11 08:44:49 jsing Exp $ */ 1/* $OpenBSD: obj_dat.c,v 1.31 2014/08/08 04:53:43 guenther Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -495,6 +495,10 @@ OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
495 unsigned long l; 495 unsigned long l;
496 const unsigned char *p; 496 const unsigned char *p;
497 497
498 /* Ensure that, at every state, |buf| is NUL-terminated. */
499 if (buf_len > 0)
500 buf[0] = '\0';
501
498 if ((a == NULL) || (a->data == NULL)) 502 if ((a == NULL) || (a->data == NULL))
499 goto err; 503 goto err;
500 504
@@ -554,8 +558,9 @@ OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
554 i = (int)(l / 40); 558 i = (int)(l / 40);
555 l -= (long)(i * 40); 559 l -= (long)(i * 40);
556 } 560 }
557 if (buf_len > 0) { 561 if (buf_len > 1) {
558 *buf++ = i + '0'; 562 *buf++ = i + '0';
563 *buf = '\0';
559 buf_len--; 564 buf_len--;
560 } 565 }
561 ret++; 566 ret++;
diff --git a/src/lib/libssl/src/crypto/asn1/a_object.c b/src/lib/libssl/src/crypto/asn1/a_object.c
index 863aa6a226..2cb5a0097b 100644
--- a/src/lib/libssl/src/crypto/asn1/a_object.c
+++ b/src/lib/libssl/src/crypto/asn1/a_object.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_object.c,v 1.22 2014/07/12 16:03:36 miod Exp $ */ 1/* $OpenBSD: a_object.c,v 1.23 2014/08/08 04:53:43 guenther Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -281,12 +281,23 @@ c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
281 ASN1_OBJECT *ret = NULL; 281 ASN1_OBJECT *ret = NULL;
282 const unsigned char *p; 282 const unsigned char *p;
283 unsigned char *data; 283 unsigned char *data;
284 int i; 284 int i, length;
285 285
286 /* Sanity check OID encoding: can't have leading 0x80 in 286 /*
287 * subidentifiers, see: X.690 8.19.2 287 * Sanity check OID encoding:
288 * - need at least one content octet
289 * - MSB must be clear in the last octet
290 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
288 */ 291 */
289 for (i = 0, p = *pp; i < len; i++, p++) { 292 if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
293 p[len - 1] & 0x80) {
294 ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
295 return (NULL);
296 }
297
298 /* Now 0 < len <= INT_MAX, so the cast is safe. */
299 length = (int)len;
300 for (i = 0; i < length; i++, p++) {
290 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { 301 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
291 ASN1err(ASN1_F_C2I_ASN1_OBJECT, 302 ASN1err(ASN1_F_C2I_ASN1_OBJECT,
292 ASN1_R_INVALID_OBJECT_ENCODING); 303 ASN1_R_INVALID_OBJECT_ENCODING);
@@ -308,24 +319,24 @@ c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
308 data = (unsigned char *)ret->data; 319 data = (unsigned char *)ret->data;
309 ret->data = NULL; 320 ret->data = NULL;
310 /* once detached we can change it */ 321 /* once detached we can change it */
311 if ((data == NULL) || (ret->length < len)) { 322 if ((data == NULL) || (ret->length < length)) {
312 ret->length = 0; 323 ret->length = 0;
313 free(data); 324 free(data);
314 data = malloc(len ? len : 1); 325 data = malloc(length);
315 if (data == NULL) { 326 if (data == NULL) {
316 i = ERR_R_MALLOC_FAILURE; 327 i = ERR_R_MALLOC_FAILURE;
317 goto err; 328 goto err;
318 } 329 }
319 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 330 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
320 } 331 }
321 memcpy(data, p, len); 332 memcpy(data, p, length);
322 /* reattach data to object, after which it remains const */ 333 /* reattach data to object, after which it remains const */
323 ret->data = data; 334 ret->data = data;
324 ret->length = (int)len; 335 ret->length = length;
325 ret->sn = NULL; 336 ret->sn = NULL;
326 ret->ln = NULL; 337 ret->ln = NULL;
327 /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ 338 /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
328 p += len; 339 p += length;
329 340
330 if (a != NULL) 341 if (a != NULL)
331 (*a) = ret; 342 (*a) = ret;
diff --git a/src/lib/libssl/src/crypto/objects/obj_dat.c b/src/lib/libssl/src/crypto/objects/obj_dat.c
index 071febba52..15c298e333 100644
--- a/src/lib/libssl/src/crypto/objects/obj_dat.c
+++ b/src/lib/libssl/src/crypto/objects/obj_dat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: obj_dat.c,v 1.30 2014/07/11 08:44:49 jsing Exp $ */ 1/* $OpenBSD: obj_dat.c,v 1.31 2014/08/08 04:53:43 guenther Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -495,6 +495,10 @@ OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
495 unsigned long l; 495 unsigned long l;
496 const unsigned char *p; 496 const unsigned char *p;
497 497
498 /* Ensure that, at every state, |buf| is NUL-terminated. */
499 if (buf_len > 0)
500 buf[0] = '\0';
501
498 if ((a == NULL) || (a->data == NULL)) 502 if ((a == NULL) || (a->data == NULL))
499 goto err; 503 goto err;
500 504
@@ -554,8 +558,9 @@ OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
554 i = (int)(l / 40); 558 i = (int)(l / 40);
555 l -= (long)(i * 40); 559 l -= (long)(i * 40);
556 } 560 }
557 if (buf_len > 0) { 561 if (buf_len > 1) {
558 *buf++ = i + '0'; 562 *buf++ = i + '0';
563 *buf = '\0';
559 buf_len--; 564 buf_len--;
560 } 565 }
561 ret++; 566 ret++;