Skip to content

Commit 684400c

Browse files
committed
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@openssl.org>
1 parent 32b07f5 commit 684400c

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

Diff for: CHANGES

+37
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,43 @@
659659

660660
Changes between 1.0.1j and 1.0.1k [xx XXX xxxx]
661661

662+
*) Fix various certificate fingerprint issues.
663+
664+
By using non-DER or invalid encodings outside the signed portion of a
665+
certificate the fingerprint can be changed without breaking the signature.
666+
Although no details of the signed portion of the certificate can be changed
667+
this can cause problems with some applications: e.g. those using the
668+
certificate fingerprint for blacklists.
669+
670+
1. Reject signatures with non zero unused bits.
671+
672+
If the BIT STRING containing the signature has non zero unused bits reject
673+
the signature. All current signature algorithms require zero unused bits.
674+
675+
2. Check certificate algorithm consistency.
676+
677+
Check the AlgorithmIdentifier inside TBS matches the one in the
678+
certificate signature. NB: this will result in signature failure
679+
errors for some broken certificates.
680+
681+
Thanks to Konrad Kraszewski from Google for reporting this issue.
682+
683+
3. Check DSA/ECDSA signatures use DER.
684+
685+
Reencode DSA/ECDSA signatures and compare with the original received
686+
signature. Return an error if there is a mismatch.
687+
688+
This will reject various cases including garbage after signature
689+
(thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
690+
program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
691+
(negative or with leading zeroes).
692+
693+
Further analysis was conducted and fixes were developed by Stephen Henson
694+
of the OpenSSL core team.
695+
696+
(CVE-2014-8275)
697+
[Steve Henson]
698+
662699
*) Do not resume sessions on the server if the negotiated protocol
663700
version does not match the session's version. Resuming with a different
664701
version, while not strictly forbidden by the RFC, is of questionable

Diff for: crypto/asn1/a_verify.c

+12
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
9090
ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
9191
goto err;
9292
}
93+
94+
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
95+
{
96+
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
97+
goto err;
98+
}
9399

94100
inl=i2d(data,NULL);
95101
buf_in=OPENSSL_malloc((unsigned int)inl);
@@ -150,6 +156,12 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
150156
return -1;
151157
}
152158

159+
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
160+
{
161+
ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
162+
return -1;
163+
}
164+
153165
EVP_MD_CTX_init(&ctx);
154166

155167
/* Convert signature OID into digest and public key OIDs */

Diff for: crypto/dsa/dsa_asn1.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,25 @@ int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
177177
const unsigned char *sigbuf, int siglen, DSA *dsa)
178178
{
179179
DSA_SIG *s;
180+
const unsigned char *p = sigbuf;
181+
unsigned char *der = NULL;
182+
int derlen = -1;
180183
int ret=-1;
181184

182185
s = DSA_SIG_new();
183186
if (s == NULL) return(ret);
184-
if (d2i_DSA_SIG(&s,&sigbuf,siglen) == NULL) goto err;
187+
if (d2i_DSA_SIG(&s,&p,siglen) == NULL) goto err;
188+
/* Ensure signature uses DER and doesn't have trailing garbage */
189+
derlen = i2d_DSA_SIG(s, &der);
190+
if (derlen != siglen || memcmp(sigbuf, der, derlen))
191+
goto err;
185192
ret=DSA_do_verify(dgst,dgst_len,s,dsa);
186193
err:
194+
if (derlen > 0)
195+
{
196+
OPENSSL_cleanse(der, derlen);
197+
OPENSSL_free(der);
198+
}
187199
DSA_SIG_free(s);
188200
return(ret);
189201
}

Diff for: crypto/ecdsa/ecs_vrf.c

+14-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
*/
5858

5959
#include "ecs_locl.h"
60+
#include "cryptlib.h"
6061
#ifndef OPENSSL_NO_ENGINE
6162
#include <openssl/engine.h>
6263
#endif
@@ -86,13 +87,25 @@ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len,
8687
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
8788
{
8889
ECDSA_SIG *s;
90+
const unsigned char *p = sigbuf;
91+
unsigned char *der = NULL;
92+
int derlen = -1;
8993
int ret=-1;
9094

9195
s = ECDSA_SIG_new();
9296
if (s == NULL) return(ret);
93-
if (d2i_ECDSA_SIG(&s, &sigbuf, sig_len) == NULL) goto err;
97+
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err;
98+
/* Ensure signature uses DER and doesn't have trailing garbage */
99+
derlen = i2d_ECDSA_SIG(s, &der);
100+
if (derlen != sig_len || memcmp(sigbuf, der, derlen))
101+
goto err;
94102
ret=ECDSA_do_verify(dgst, dgst_len, s, eckey);
95103
err:
104+
if (derlen > 0)
105+
{
106+
OPENSSL_cleanse(der, derlen);
107+
OPENSSL_free(der);
108+
}
96109
ECDSA_SIG_free(s);
97110
return(ret);
98111
}

Diff for: crypto/x509/x_all.c

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373

7474
int X509_verify(X509 *a, EVP_PKEY *r)
7575
{
76+
if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
77+
return 0;
7678
return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
7779
a->signature,a->cert_info,r));
7880
}

0 commit comments

Comments
 (0)