155714Skris/* crypto/x509/x509_cmp.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
60109998Smarkm#include <ctype.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/asn1.h>
6355714Skris#include <openssl/objects.h>
6455714Skris#include <openssl/x509.h>
6559191Skris#include <openssl/x509v3.h>
6655714Skris
6768651Skrisint X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
68280304Sjkim{
69280304Sjkim    int i;
70280304Sjkim    X509_CINF *ai, *bi;
7155714Skris
72280304Sjkim    ai = a->cert_info;
73280304Sjkim    bi = b->cert_info;
74280304Sjkim    i = M_ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber);
75280304Sjkim    if (i)
76280304Sjkim        return (i);
77280304Sjkim    return (X509_NAME_cmp(ai->issuer, bi->issuer));
78280304Sjkim}
7955714Skris
80109998Smarkm#ifndef OPENSSL_NO_MD5
8155714Skrisunsigned long X509_issuer_and_serial_hash(X509 *a)
82280304Sjkim{
83280304Sjkim    unsigned long ret = 0;
84280304Sjkim    EVP_MD_CTX ctx;
85280304Sjkim    unsigned char md[16];
86280304Sjkim    char *f;
8755714Skris
88280304Sjkim    EVP_MD_CTX_init(&ctx);
89280304Sjkim    f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0);
90280304Sjkim    if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
91280304Sjkim        goto err;
92280304Sjkim    if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f)))
93280304Sjkim        goto err;
94280304Sjkim    OPENSSL_free(f);
95280304Sjkim    if (!EVP_DigestUpdate
96280304Sjkim        (&ctx, (unsigned char *)a->cert_info->serialNumber->data,
97280304Sjkim         (unsigned long)a->cert_info->serialNumber->length))
98280304Sjkim        goto err;
99280304Sjkim    if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL))
100280304Sjkim        goto err;
101280304Sjkim    ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
102280304Sjkim           ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
103280304Sjkim        ) & 0xffffffffL;
104280304Sjkim err:
105280304Sjkim    EVP_MD_CTX_cleanup(&ctx);
106280304Sjkim    return (ret);
107280304Sjkim}
10855714Skris#endif
109280304Sjkim
11068651Skrisint X509_issuer_name_cmp(const X509 *a, const X509 *b)
111280304Sjkim{
112280304Sjkim    return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer));
113280304Sjkim}
11455714Skris
11568651Skrisint X509_subject_name_cmp(const X509 *a, const X509 *b)
116280304Sjkim{
117280304Sjkim    return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject));
118280304Sjkim}
11955714Skris
12068651Skrisint X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
121280304Sjkim{
122280304Sjkim    return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer));
123280304Sjkim}
12455714Skris
125238405Sjkim#ifndef OPENSSL_NO_SHA
126238405Sjkimint X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
127280304Sjkim{
128280304Sjkim    return memcmp(a->sha1_hash, b->sha1_hash, 20);
129280304Sjkim}
130238405Sjkim#endif
131238405Sjkim
13255714SkrisX509_NAME *X509_get_issuer_name(X509 *a)
133280304Sjkim{
134280304Sjkim    return (a->cert_info->issuer);
135280304Sjkim}
13655714Skris
13755714Skrisunsigned long X509_issuer_name_hash(X509 *x)
138280304Sjkim{
139280304Sjkim    return (X509_NAME_hash(x->cert_info->issuer));
140280304Sjkim}
14155714Skris
142238405Sjkim#ifndef OPENSSL_NO_MD5
143238405Sjkimunsigned long X509_issuer_name_hash_old(X509 *x)
144280304Sjkim{
145280304Sjkim    return (X509_NAME_hash_old(x->cert_info->issuer));
146280304Sjkim}
147238405Sjkim#endif
148238405Sjkim
14955714SkrisX509_NAME *X509_get_subject_name(X509 *a)
150280304Sjkim{
151280304Sjkim    return (a->cert_info->subject);
152280304Sjkim}
15355714Skris
15455714SkrisASN1_INTEGER *X509_get_serialNumber(X509 *a)
155280304Sjkim{
156280304Sjkim    return (a->cert_info->serialNumber);
157280304Sjkim}
15855714Skris
15955714Skrisunsigned long X509_subject_name_hash(X509 *x)
160280304Sjkim{
161280304Sjkim    return (X509_NAME_hash(x->cert_info->subject));
162280304Sjkim}
16355714Skris
164238405Sjkim#ifndef OPENSSL_NO_MD5
165238405Sjkimunsigned long X509_subject_name_hash_old(X509 *x)
166280304Sjkim{
167280304Sjkim    return (X509_NAME_hash_old(x->cert_info->subject));
168280304Sjkim}
169238405Sjkim#endif
170238405Sjkim
171109998Smarkm#ifndef OPENSSL_NO_SHA
172280304Sjkim/*
173280304Sjkim * Compare two certificates: they must be identical for this to work. NB:
174280304Sjkim * Although "cmp" operations are generally prototyped to take "const"
175280304Sjkim * arguments (eg. for use in STACKs), the way X509 handling is - these
176280304Sjkim * operations may involve ensuring the hashes are up-to-date and ensuring
177280304Sjkim * certain cert information is cached. So this is the point where the
178280304Sjkim * "depth-first" constification tree has to halt with an evil cast.
17959191Skris */
18068651Skrisint X509_cmp(const X509 *a, const X509 *b)
18159191Skris{
182291721Sjkim    int rv;
183291721Sjkim
184280304Sjkim    /* ensure hash is valid */
185280304Sjkim    X509_check_purpose((X509 *)a, -1, 0);
186280304Sjkim    X509_check_purpose((X509 *)b, -1, 0);
18759191Skris
188291721Sjkim    rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
189291721Sjkim    if (rv)
190291721Sjkim        return rv;
191291721Sjkim    /* Check for match against stored encoding too */
192291721Sjkim    if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) {
193291721Sjkim        rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
194291721Sjkim        if (rv)
195291721Sjkim            return rv;
196291721Sjkim        return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
197291721Sjkim                      a->cert_info->enc.len);
198291721Sjkim    }
199291721Sjkim    return rv;
20059191Skris}
20159191Skris#endif
20259191Skris
203238405Sjkimint X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
204280304Sjkim{
205280304Sjkim    int ret;
206109998Smarkm
207280304Sjkim    /* Ensure canonical encoding is present and up to date */
208109998Smarkm
209280304Sjkim    if (!a->canon_enc || a->modified) {
210280304Sjkim        ret = i2d_X509_NAME((X509_NAME *)a, NULL);
211280304Sjkim        if (ret < 0)
212280304Sjkim            return -2;
213280304Sjkim    }
214109998Smarkm
215280304Sjkim    if (!b->canon_enc || b->modified) {
216280304Sjkim        ret = i2d_X509_NAME((X509_NAME *)b, NULL);
217280304Sjkim        if (ret < 0)
218280304Sjkim            return -2;
219280304Sjkim    }
220109998Smarkm
221280304Sjkim    ret = a->canon_enclen - b->canon_enclen;
222109998Smarkm
223280304Sjkim    if (ret)
224280304Sjkim        return ret;
225109998Smarkm
226280304Sjkim    return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
227109998Smarkm
228280304Sjkim}
229109998Smarkm
230238405Sjkimunsigned long X509_NAME_hash(X509_NAME *x)
231280304Sjkim{
232280304Sjkim    unsigned long ret = 0;
233280304Sjkim    unsigned char md[SHA_DIGEST_LENGTH];
234160814Ssimon
235280304Sjkim    /* Make sure X509_NAME structure contains valid cached encoding */
236280304Sjkim    i2d_X509_NAME(x, NULL);
237280304Sjkim    if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
238280304Sjkim                    NULL))
239280304Sjkim        return 0;
240160814Ssimon
241280304Sjkim    ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
242280304Sjkim           ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
243280304Sjkim        ) & 0xffffffffL;
244280304Sjkim    return (ret);
245280304Sjkim}
24655714Skris
247109998Smarkm#ifndef OPENSSL_NO_MD5
248280304Sjkim/*
249280304Sjkim * I now DER encode the name and hash it.  Since I cache the DER encoding,
250280304Sjkim * this is reasonably efficient.
251280304Sjkim */
252238405Sjkim
253238405Sjkimunsigned long X509_NAME_hash_old(X509_NAME *x)
254280304Sjkim{
255280304Sjkim    EVP_MD_CTX md_ctx;
256280304Sjkim    unsigned long ret = 0;
257280304Sjkim    unsigned char md[16];
25855714Skris
259280304Sjkim    /* Make sure X509_NAME structure contains valid cached encoding */
260280304Sjkim    i2d_X509_NAME(x, NULL);
261280304Sjkim    EVP_MD_CTX_init(&md_ctx);
262280304Sjkim    EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
263280304Sjkim    if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
264280304Sjkim        && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
265280304Sjkim        && EVP_DigestFinal_ex(&md_ctx, md, NULL))
266280304Sjkim        ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
267280304Sjkim               ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
268280304Sjkim            ) & 0xffffffffL;
269280304Sjkim    EVP_MD_CTX_cleanup(&md_ctx);
27055714Skris
271280304Sjkim    return (ret);
272280304Sjkim}
27355714Skris#endif
27455714Skris
27555714Skris/* Search a stack of X509 for a match */
27655714SkrisX509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
277280304Sjkim                                     ASN1_INTEGER *serial)
278280304Sjkim{
279280304Sjkim    int i;
280280304Sjkim    X509_CINF cinf;
281280304Sjkim    X509 x, *x509 = NULL;
28255714Skris
283280304Sjkim    if (!sk)
284280304Sjkim        return NULL;
28559191Skris
286280304Sjkim    x.cert_info = &cinf;
287280304Sjkim    cinf.serialNumber = serial;
288280304Sjkim    cinf.issuer = name;
28955714Skris
290280304Sjkim    for (i = 0; i < sk_X509_num(sk); i++) {
291280304Sjkim        x509 = sk_X509_value(sk, i);
292280304Sjkim        if (X509_issuer_and_serial_cmp(x509, &x) == 0)
293280304Sjkim            return (x509);
294280304Sjkim    }
295280304Sjkim    return (NULL);
296280304Sjkim}
29755714Skris
29855714SkrisX509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
299280304Sjkim{
300280304Sjkim    X509 *x509;
301280304Sjkim    int i;
30255714Skris
303280304Sjkim    for (i = 0; i < sk_X509_num(sk); i++) {
304280304Sjkim        x509 = sk_X509_value(sk, i);
305280304Sjkim        if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
306280304Sjkim            return (x509);
307280304Sjkim    }
308280304Sjkim    return (NULL);
309280304Sjkim}
31055714Skris
31155714SkrisEVP_PKEY *X509_get_pubkey(X509 *x)
312280304Sjkim{
313280304Sjkim    if ((x == NULL) || (x->cert_info == NULL))
314280304Sjkim        return (NULL);
315280304Sjkim    return (X509_PUBKEY_get(x->cert_info->key));
316280304Sjkim}
31755714Skris
318109998SmarkmASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
319280304Sjkim{
320280304Sjkim    if (!x)
321280304Sjkim        return NULL;
322280304Sjkim    return x->cert_info->key->public_key;
323280304Sjkim}
324109998Smarkm
32555714Skrisint X509_check_private_key(X509 *x, EVP_PKEY *k)
326280304Sjkim{
327280304Sjkim    EVP_PKEY *xk;
328280304Sjkim    int ret;
32955714Skris
330280304Sjkim    xk = X509_get_pubkey(x);
331238405Sjkim
332280304Sjkim    if (xk)
333280304Sjkim        ret = EVP_PKEY_cmp(xk, k);
334280304Sjkim    else
335280304Sjkim        ret = -2;
336238405Sjkim
337280304Sjkim    switch (ret) {
338280304Sjkim    case 1:
339280304Sjkim        break;
340280304Sjkim    case 0:
341280304Sjkim        X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH);
342280304Sjkim        break;
343280304Sjkim    case -1:
344280304Sjkim        X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
345280304Sjkim        break;
346280304Sjkim    case -2:
347280304Sjkim        X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
348280304Sjkim    }
349280304Sjkim    if (xk)
350280304Sjkim        EVP_PKEY_free(xk);
351280304Sjkim    if (ret > 0)
352280304Sjkim        return 1;
353280304Sjkim    return 0;
354280304Sjkim}
355