[openssl-commits] [openssl] OpenSSL source code branch OpenSSL_0_9_8-stable updated. OpenSSL_0_9_8zc-21-gec2fede
Dr. Stephen Henson
steve at openssl.org
Mon Jan 5 16:47:52 UTC 2015
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "OpenSSL source code".
The branch, OpenSSL_0_9_8-stable has been updated
via ec2fede9467ae1a65f452d3a39f7fbc4891d9285 (commit)
via 63f3c9e715955f0cdc83698d8a3dfb1b80064407 (commit)
via c22e2dd6e52899926d1f1ee3a2b5b9570d03130f (commit)
from 7fae32f6d69baf27ef69d92499c59c8a3277f3e3 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ec2fede9467ae1a65f452d3a39f7fbc4891d9285
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Sat Dec 20 15:09:50 2014 +0000
Fix various certificate fingerprint issues.
By using non-DER or invalid encodings outside the signed portion of a
certificate the fingerprint can be changed without breaking the signature.
Although no details of the signed portion of the certificate can be changed
this can cause problems with some applications: e.g. those using the
certificate fingerprint for blacklists.
1. Reject signatures with non zero unused bits.
If the BIT STRING containing the signature has non zero unused bits reject
the signature. All current signature algorithms require zero unused bits.
2. Check certificate algorithm consistency.
Check the AlgorithmIdentifier inside TBS matches the one in the
certificate signature. NB: this will result in signature failure
errors for some broken certificates.
3. Check DSA/ECDSA signatures use DER.
Reencode DSA/ECDSA signatures and compare with the original received
signature. Return an error if there is a mismatch.
This will reject various cases including garbage after signature
(thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
(negative or with leading zeroes).
CVE-2014-8275
Reviewed-by: Emilia Käsper <emilia at openssl.org>
(cherry picked from commit 208a6012be3077d83df4475f32dd1b1446f3a02e)
Conflicts:
crypto/dsa/dsa_vrf.c
commit 63f3c9e715955f0cdc83698d8a3dfb1b80064407
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Mon Jan 5 15:35:55 2015 +0000
Update ordinals.
Reviewed-by: Emilia Käsper <emilia at openssl.org>
commit c22e2dd6e52899926d1f1ee3a2b5b9570d03130f
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Sun Dec 14 23:14:15 2014 +0000
Add ASN1_TYPE_cmp and X509_ALGOR_cmp.
(these are needed for certificate fingerprint fixes)
Reviewed-by: Emilia Käsper <emilia at openssl.org>
-----------------------------------------------------------------------
Summary of changes:
CHANGES | 37 ++++++++++++++++++++++++++++++++++++-
crypto/asn1/a_type.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
crypto/asn1/a_verify.c | 12 ++++++++++++
crypto/asn1/asn1.h | 1 +
crypto/asn1/x_algor.c | 10 ++++++++++
crypto/dsa/dsa_asn1.c | 16 ++++++++++++++--
crypto/ecdsa/ecs_vrf.c | 15 ++++++++++++++-
crypto/x509/x509.h | 1 +
crypto/x509/x_all.c | 2 ++
util/libeay.num | 2 ++
10 files changed, 138 insertions(+), 4 deletions(-)
diff --git a/CHANGES b/CHANGES
index d236eea..60a4596 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,7 +4,42 @@
Changes between 0.9.8zc and 0.9.8zd [xx XXX xxxx]
- *)
+ *) Fix various certificate fingerprint issues.
+
+ By using non-DER or invalid encodings outside the signed portion of a
+ certificate the fingerprint can be changed without breaking the signature.
+ Although no details of the signed portion of the certificate can be changed
+ this can cause problems with some applications: e.g. those using the
+ certificate fingerprint for blacklists.
+
+ 1. Reject signatures with non zero unused bits.
+
+ If the BIT STRING containing the signature has non zero unused bits reject
+ the signature. All current signature algorithms require zero unused bits.
+
+ 2. Check certificate algorithm consistency.
+
+ Check the AlgorithmIdentifier inside TBS matches the one in the
+ certificate signature. NB: this will result in signature failure
+ errors for some broken certificates.
+
+ Thanks to Konrad Kraszewski from Google for reporting this issue.
+
+ 3. Check DSA/ECDSA signatures use DER.
+
+ Reencode DSA/ECDSA signatures and compare with the original received
+ signature. Return an error if there is a mismatch.
+
+ This will reject various cases including garbage after signature
+ (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
+ program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
+ (negative or with leading zeroes).
+
+ Further analysis was conducted and fixes were developed by Stephen Henson
+ of the OpenSSL core team.
+
+ (CVE-2014-8275)
+ [Steve Henson]
Changes between 0.9.8zb and 0.9.8zc [15 Oct 2014]
diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c
index 36becea..b7a95ad 100644
--- a/crypto/asn1/a_type.c
+++ b/crypto/asn1/a_type.c
@@ -108,3 +108,49 @@ int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
IMPLEMENT_STACK_OF(ASN1_TYPE)
IMPLEMENT_ASN1_SET_OF(ASN1_TYPE)
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
+ {
+ int result = -1;
+
+ if (!a || !b || a->type != b->type) return -1;
+
+ switch (a->type)
+ {
+ case V_ASN1_OBJECT:
+ result = OBJ_cmp(a->value.object, b->value.object);
+ break;
+ case V_ASN1_NULL:
+ result = 0; /* They do not have content. */
+ break;
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_ENUMERATED:
+ case V_ASN1_BIT_STRING:
+ case V_ASN1_OCTET_STRING:
+ case V_ASN1_SEQUENCE:
+ case V_ASN1_SET:
+ case V_ASN1_NUMERICSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_VIDEOTEXSTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ case V_ASN1_GRAPHICSTRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_OTHER:
+ default:
+ result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
+ (ASN1_STRING *) b->value.ptr);
+ break;
+ }
+
+ return result;
+ }
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index 7ded69b..3ef363d 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -89,6 +89,12 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
+
+ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
+ {
+ ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ goto err;
+ }
inl=i2d(data,NULL);
buf_in=OPENSSL_malloc((unsigned int)inl);
@@ -144,6 +150,12 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat
return -1;
}
+ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
+ {
+ ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ return -1;
+ }
+
EVP_MD_CTX_init(&ctx);
i=OBJ_obj2nid(a->algorithm);
type=EVP_get_digestbyname(OBJ_nid2sn(i));
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index aeb3f4c..bd7af2d 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -769,6 +769,7 @@ DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
int ASN1_TYPE_get(ASN1_TYPE *a);
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
ASN1_OBJECT * ASN1_OBJECT_new(void );
void ASN1_OBJECT_free(ASN1_OBJECT *a);
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
index 99e5342..acc41ba 100644
--- a/crypto/asn1/x_algor.c
+++ b/crypto/asn1/x_algor.c
@@ -128,3 +128,13 @@ void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
}
}
+int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
+ {
+ int rv;
+ rv = OBJ_cmp(a->algorithm, b->algorithm);
+ if (rv)
+ return rv;
+ if (!a->parameter && !b->parameter)
+ return 0;
+ return ASN1_TYPE_cmp(a->parameter, b->parameter);
+ }
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
index bc7d7a0..08d4772 100644
--- a/crypto/dsa/dsa_asn1.c
+++ b/crypto/dsa/dsa_asn1.c
@@ -200,7 +200,11 @@ int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int siglen, DSA *dsa)
{
DSA_SIG *s;
+ const unsigned char *p = sigbuf;
+ unsigned char *der = NULL;
+ int derlen = -1;
int ret=-1;
+
#ifdef OPENSSL_FIPS
if(FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW))
{
@@ -211,10 +215,18 @@ int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
s = DSA_SIG_new();
if (s == NULL) return(ret);
- if (d2i_DSA_SIG(&s,&sigbuf,siglen) == NULL) goto err;
+ if (d2i_DSA_SIG(&s,&p,siglen) == NULL) goto err;
+ /* Ensure signature uses DER and doesn't have trailing garbage */
+ derlen = i2d_DSA_SIG(s, &der);
+ if (derlen != siglen || memcmp(sigbuf, der, derlen))
+ goto err;
ret=DSA_do_verify(dgst,dgst_len,s,dsa);
err:
+ if (derlen > 0)
+ {
+ OPENSSL_cleanse(der, derlen);
+ OPENSSL_free(der);
+ }
DSA_SIG_free(s);
return(ret);
}
-
diff --git a/crypto/ecdsa/ecs_vrf.c b/crypto/ecdsa/ecs_vrf.c
index ef9acf7..2836efe 100644
--- a/crypto/ecdsa/ecs_vrf.c
+++ b/crypto/ecdsa/ecs_vrf.c
@@ -57,6 +57,7 @@
*/
#include "ecs_locl.h"
+#include "cryptlib.h"
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
@@ -84,13 +85,25 @@ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
{
ECDSA_SIG *s;
+ const unsigned char *p = sigbuf;
+ unsigned char *der = NULL;
+ int derlen = -1;
int ret=-1;
s = ECDSA_SIG_new();
if (s == NULL) return(ret);
- if (d2i_ECDSA_SIG(&s, &sigbuf, sig_len) == NULL) goto err;
+ if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err;
+ /* Ensure signature uses DER and doesn't have trailing garbage */
+ derlen = i2d_ECDSA_SIG(s, &der);
+ if (derlen != sig_len || memcmp(sigbuf, der, derlen))
+ goto err;
ret=ECDSA_do_verify(dgst, dgst_len, s, eckey);
err:
+ if (derlen > 0)
+ {
+ OPENSSL_cleanse(der, derlen);
+ OPENSSL_free(der);
+ }
ECDSA_SIG_free(s);
return(ret);
}
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index c34689a..e77ee69 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -870,6 +870,7 @@ X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
X509_ALGOR *algor);
+int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
X509_NAME *X509_NAME_dup(X509_NAME *xn);
X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index c7b07f7..f4c68fc 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -73,6 +73,8 @@
int X509_verify(X509 *a, EVP_PKEY *r)
{
+ if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
+ return 0;
return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
a->signature,a->cert_info,r));
}
diff --git a/util/libeay.num b/util/libeay.num
index f3b7776..b2f9e45 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -1807,6 +1807,7 @@ ASN1_UTCTIME_get 2350 NOEXIST::FUNCTION:
X509_REQ_digest 2362 EXIST::FUNCTION:EVP
X509_CRL_digest 2391 EXIST::FUNCTION:EVP
d2i_ASN1_SET_OF_PKCS7 2397 NOEXIST::FUNCTION:
+X509_ALGOR_cmp 2398 EXIST::FUNCTION:
EVP_CIPHER_CTX_set_key_length 2399 EXIST::FUNCTION:
EVP_CIPHER_CTX_ctrl 2400 EXIST::FUNCTION:
BN_mod_exp_mont_word 2401 EXIST::FUNCTION:
@@ -3730,3 +3731,4 @@ JPAKE_STEP2_init 4113 EXIST::FUNCTION:JPAKE
pqueue_size 4114 EXIST::FUNCTION:
OPENSSL_uni2asc 4115 EXIST:NETWARE:FUNCTION:
OPENSSL_asc2uni 4116 EXIST:NETWARE:FUNCTION:
+ASN1_TYPE_cmp 4428 EXIST::FUNCTION:
hooks/post-receive
--
OpenSSL source code
More information about the openssl-commits
mailing list