~andersk/ubuntu/oneiric/openssl/spurious-reboot

« back to all changes in this revision

Viewing changes to crypto/x509/x509_cmp.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Martin
  • Date: 2004-05-24 17:02:29 UTC
  • Revision ID: james.westby@ubuntu.com-20040524170229-ixlo08bbbly0xied
Tags: upstream-0.9.7d
ImportĀ upstreamĀ versionĀ 0.9.7d

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* crypto/x509/x509_cmp.c */
 
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 
3
 * All rights reserved.
 
4
 *
 
5
 * This package is an SSL implementation written
 
6
 * by Eric Young (eay@cryptsoft.com).
 
7
 * The implementation was written so as to conform with Netscapes SSL.
 
8
 * 
 
9
 * This library is free for commercial and non-commercial use as long as
 
10
 * the following conditions are aheared to.  The following conditions
 
11
 * apply to all code found in this distribution, be it the RC4, RSA,
 
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 
13
 * included with this distribution is covered by the same copyright terms
 
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 
15
 * 
 
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
 
17
 * the code are not to be removed.
 
18
 * If this package is used in a product, Eric Young should be given attribution
 
19
 * as the author of the parts of the library used.
 
20
 * This can be in the form of a textual message at program startup or
 
21
 * in documentation (online or textual) provided with the package.
 
22
 * 
 
23
 * Redistribution and use in source and binary forms, with or without
 
24
 * modification, are permitted provided that the following conditions
 
25
 * are met:
 
26
 * 1. Redistributions of source code must retain the copyright
 
27
 *    notice, this list of conditions and the following disclaimer.
 
28
 * 2. Redistributions in binary form must reproduce the above copyright
 
29
 *    notice, this list of conditions and the following disclaimer in the
 
30
 *    documentation and/or other materials provided with the distribution.
 
31
 * 3. All advertising materials mentioning features or use of this software
 
32
 *    must display the following acknowledgement:
 
33
 *    "This product includes cryptographic software written by
 
34
 *     Eric Young (eay@cryptsoft.com)"
 
35
 *    The word 'cryptographic' can be left out if the rouines from the library
 
36
 *    being used are not cryptographic related :-).
 
37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 
38
 *    the apps directory (application code) you must include an acknowledgement:
 
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 
40
 * 
 
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
51
 * SUCH DAMAGE.
 
52
 * 
 
53
 * The licence and distribution terms for any publically available version or
 
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 
55
 * copied and put under another distribution licence
 
56
 * [including the GNU Public Licence.]
 
57
 */
 
58
 
 
59
#include <stdio.h>
 
60
#include <ctype.h>
 
61
#include "cryptlib.h"
 
62
#include <openssl/asn1.h>
 
63
#include <openssl/objects.h>
 
64
#include <openssl/x509.h>
 
65
#include <openssl/x509v3.h>
 
66
 
 
67
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
 
68
        {
 
69
        int i;
 
70
        X509_CINF *ai,*bi;
 
71
 
 
72
        ai=a->cert_info;
 
73
        bi=b->cert_info;
 
74
        i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
 
75
        if (i) return(i);
 
76
        return(X509_NAME_cmp(ai->issuer,bi->issuer));
 
77
        }
 
78
 
 
79
#ifndef OPENSSL_NO_MD5
 
80
unsigned long X509_issuer_and_serial_hash(X509 *a)
 
81
        {
 
82
        unsigned long ret=0;
 
83
        EVP_MD_CTX ctx;
 
84
        unsigned char md[16];
 
85
        char *f;
 
86
 
 
87
        EVP_MD_CTX_init(&ctx);
 
88
        f=X509_NAME_oneline(a->cert_info->issuer,NULL,0);
 
89
        ret=strlen(f);
 
90
        EVP_DigestInit_ex(&ctx, EVP_md5(), NULL);
 
91
        EVP_DigestUpdate(&ctx,(unsigned char *)f,ret);
 
92
        OPENSSL_free(f);
 
93
        EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data,
 
94
                (unsigned long)a->cert_info->serialNumber->length);
 
95
        EVP_DigestFinal_ex(&ctx,&(md[0]),NULL);
 
96
        ret=(   ((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
 
97
                ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
 
98
                )&0xffffffffL;
 
99
        EVP_MD_CTX_cleanup(&ctx);
 
100
        return(ret);
 
101
        }
 
102
#endif
 
103
        
 
104
int X509_issuer_name_cmp(const X509 *a, const X509 *b)
 
105
        {
 
106
        return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer));
 
107
        }
 
108
 
 
109
int X509_subject_name_cmp(const X509 *a, const X509 *b)
 
110
        {
 
111
        return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
 
112
        }
 
113
 
 
114
int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
 
115
        {
 
116
        return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
 
117
        }
 
118
 
 
119
X509_NAME *X509_get_issuer_name(X509 *a)
 
120
        {
 
121
        return(a->cert_info->issuer);
 
122
        }
 
123
 
 
124
unsigned long X509_issuer_name_hash(X509 *x)
 
125
        {
 
126
        return(X509_NAME_hash(x->cert_info->issuer));
 
127
        }
 
128
 
 
129
X509_NAME *X509_get_subject_name(X509 *a)
 
130
        {
 
131
        return(a->cert_info->subject);
 
132
        }
 
133
 
 
134
ASN1_INTEGER *X509_get_serialNumber(X509 *a)
 
135
        {
 
136
        return(a->cert_info->serialNumber);
 
137
        }
 
138
 
 
139
unsigned long X509_subject_name_hash(X509 *x)
 
140
        {
 
141
        return(X509_NAME_hash(x->cert_info->subject));
 
142
        }
 
143
 
 
144
#ifndef OPENSSL_NO_SHA
 
145
/* Compare two certificates: they must be identical for
 
146
 * this to work. NB: Although "cmp" operations are generally
 
147
 * prototyped to take "const" arguments (eg. for use in
 
148
 * STACKs), the way X509 handling is - these operations may
 
149
 * involve ensuring the hashes are up-to-date and ensuring
 
150
 * certain cert information is cached. So this is the point
 
151
 * where the "depth-first" constification tree has to halt
 
152
 * with an evil cast.
 
153
 */
 
154
int X509_cmp(const X509 *a, const X509 *b)
 
155
{
 
156
        /* ensure hash is valid */
 
157
        X509_check_purpose((X509 *)a, -1, 0);
 
158
        X509_check_purpose((X509 *)b, -1, 0);
 
159
 
 
160
        return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
 
161
}
 
162
#endif
 
163
 
 
164
 
 
165
/* Case insensitive string comparision */
 
166
static int nocase_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
 
167
{
 
168
        int i;
 
169
 
 
170
        if (a->length != b->length)
 
171
                return (a->length - b->length);
 
172
 
 
173
        for (i=0; i<a->length; i++)
 
174
        {
 
175
                int ca, cb;
 
176
 
 
177
                ca = tolower(a->data[i]);
 
178
                cb = tolower(b->data[i]);
 
179
 
 
180
                if (ca != cb)
 
181
                        return(ca-cb);
 
182
        }
 
183
        return 0;
 
184
}
 
185
 
 
186
/* Case insensitive string comparision with space normalization 
 
187
 * Space normalization - ignore leading, trailing spaces, 
 
188
 *       multiple spaces between characters are replaced by single space  
 
189
 */
 
190
static int nocase_spacenorm_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
 
191
{
 
192
        unsigned char *pa = NULL, *pb = NULL;
 
193
        int la, lb;
 
194
        
 
195
        la = a->length;
 
196
        lb = b->length;
 
197
        pa = a->data;
 
198
        pb = b->data;
 
199
 
 
200
        /* skip leading spaces */
 
201
        while (la > 0 && isspace(*pa))
 
202
        {
 
203
                la--;
 
204
                pa++;
 
205
        }
 
206
        while (lb > 0 && isspace(*pb))
 
207
        {
 
208
                lb--;
 
209
                pb++;
 
210
        }
 
211
 
 
212
        /* skip trailing spaces */
 
213
        while (la > 0 && isspace(pa[la-1]))
 
214
                la--;
 
215
        while (lb > 0 && isspace(pb[lb-1]))
 
216
                lb--;
 
217
 
 
218
        /* compare strings with space normalization */
 
219
        while (la > 0 && lb > 0)
 
220
        {
 
221
                int ca, cb;
 
222
 
 
223
                /* compare character */
 
224
                ca = tolower(*pa);
 
225
                cb = tolower(*pb);
 
226
                if (ca != cb)
 
227
                        return (ca - cb);
 
228
 
 
229
                pa++; pb++;
 
230
                la--; lb--;
 
231
 
 
232
                if (la <= 0 || lb <= 0)
 
233
                        break;
 
234
 
 
235
                /* is white space next character ? */
 
236
                if (isspace(*pa) && isspace(*pb))
 
237
                {
 
238
                        /* skip remaining white spaces */
 
239
                        while (la > 0 && isspace(*pa))
 
240
                        {
 
241
                                la--;
 
242
                                pa++;
 
243
                        }
 
244
                        while (lb > 0 && isspace(*pb))
 
245
                        {
 
246
                                lb--;
 
247
                                pb++;
 
248
                        }
 
249
                }
 
250
        }
 
251
        if (la > 0 || lb > 0)
 
252
                return la - lb;
 
253
 
 
254
        return 0;
 
255
}
 
256
 
 
257
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
 
258
        {
 
259
        int i,j;
 
260
        X509_NAME_ENTRY *na,*nb;
 
261
 
 
262
        if (sk_X509_NAME_ENTRY_num(a->entries)
 
263
            != sk_X509_NAME_ENTRY_num(b->entries))
 
264
                return sk_X509_NAME_ENTRY_num(a->entries)
 
265
                  -sk_X509_NAME_ENTRY_num(b->entries);
 
266
        for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--)
 
267
                {
 
268
                na=sk_X509_NAME_ENTRY_value(a->entries,i);
 
269
                nb=sk_X509_NAME_ENTRY_value(b->entries,i);
 
270
                j=na->value->type-nb->value->type;
 
271
                if (j) return(j);
 
272
                if (na->value->type == V_ASN1_PRINTABLESTRING)
 
273
                        j=nocase_spacenorm_cmp(na->value, nb->value);
 
274
                else if (na->value->type == V_ASN1_IA5STRING
 
275
                        && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress)
 
276
                        j=nocase_cmp(na->value, nb->value);
 
277
                else
 
278
                        {
 
279
                        j=na->value->length-nb->value->length;
 
280
                        if (j) return(j);
 
281
                        j=memcmp(na->value->data,nb->value->data,
 
282
                                na->value->length);
 
283
                        }
 
284
                if (j) return(j);
 
285
                j=na->set-nb->set;
 
286
                if (j) return(j);
 
287
                }
 
288
 
 
289
        /* We will check the object types after checking the values
 
290
         * since the values will more often be different than the object
 
291
         * types. */
 
292
        for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--)
 
293
                {
 
294
                na=sk_X509_NAME_ENTRY_value(a->entries,i);
 
295
                nb=sk_X509_NAME_ENTRY_value(b->entries,i);
 
296
                j=OBJ_cmp(na->object,nb->object);
 
297
                if (j) return(j);
 
298
                }
 
299
        return(0);
 
300
        }
 
301
 
 
302
#ifndef OPENSSL_NO_MD5
 
303
/* I now DER encode the name and hash it.  Since I cache the DER encoding,
 
304
 * this is reasonably efficient. */
 
305
unsigned long X509_NAME_hash(X509_NAME *x)
 
306
        {
 
307
        unsigned long ret=0;
 
308
        unsigned char md[16];
 
309
 
 
310
        /* Make sure X509_NAME structure contains valid cached encoding */
 
311
        i2d_X509_NAME(x,NULL);
 
312
        EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL);
 
313
 
 
314
        ret=(   ((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
 
315
                ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
 
316
                )&0xffffffffL;
 
317
        return(ret);
 
318
        }
 
319
#endif
 
320
 
 
321
/* Search a stack of X509 for a match */
 
322
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
 
323
                ASN1_INTEGER *serial)
 
324
        {
 
325
        int i;
 
326
        X509_CINF cinf;
 
327
        X509 x,*x509=NULL;
 
328
 
 
329
        if(!sk) return NULL;
 
330
 
 
331
        x.cert_info= &cinf;
 
332
        cinf.serialNumber=serial;
 
333
        cinf.issuer=name;
 
334
 
 
335
        for (i=0; i<sk_X509_num(sk); i++)
 
336
                {
 
337
                x509=sk_X509_value(sk,i);
 
338
                if (X509_issuer_and_serial_cmp(x509,&x) == 0)
 
339
                        return(x509);
 
340
                }
 
341
        return(NULL);
 
342
        }
 
343
 
 
344
X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
 
345
        {
 
346
        X509 *x509;
 
347
        int i;
 
348
 
 
349
        for (i=0; i<sk_X509_num(sk); i++)
 
350
                {
 
351
                x509=sk_X509_value(sk,i);
 
352
                if (X509_NAME_cmp(X509_get_subject_name(x509),name) == 0)
 
353
                        return(x509);
 
354
                }
 
355
        return(NULL);
 
356
        }
 
357
 
 
358
EVP_PKEY *X509_get_pubkey(X509 *x)
 
359
        {
 
360
        if ((x == NULL) || (x->cert_info == NULL))
 
361
                return(NULL);
 
362
        return(X509_PUBKEY_get(x->cert_info->key));
 
363
        }
 
364
 
 
365
ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
 
366
        {
 
367
        if(!x) return NULL;
 
368
        return x->cert_info->key->public_key;
 
369
        }
 
370
 
 
371
int X509_check_private_key(X509 *x, EVP_PKEY *k)
 
372
        {
 
373
        EVP_PKEY *xk=NULL;
 
374
        int ok=0;
 
375
 
 
376
        xk=X509_get_pubkey(x);
 
377
        if (xk->type != k->type)
 
378
            {
 
379
            X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH);
 
380
            goto err;
 
381
            }
 
382
        switch (k->type)
 
383
                {
 
384
#ifndef OPENSSL_NO_RSA
 
385
        case EVP_PKEY_RSA:
 
386
                if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0
 
387
                    || BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0)
 
388
                    {
 
389
                    X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);
 
390
                    goto err;
 
391
                    }
 
392
                break;
 
393
#endif
 
394
#ifndef OPENSSL_NO_DSA
 
395
        case EVP_PKEY_DSA:
 
396
                if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0)
 
397
                    {
 
398
                    X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);
 
399
                    goto err;
 
400
                    }
 
401
                break;
 
402
#endif
 
403
#ifndef OPENSSL_NO_DH
 
404
        case EVP_PKEY_DH:
 
405
                /* No idea */
 
406
                X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY);
 
407
                goto err;
 
408
#endif
 
409
        default:
 
410
                X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE);
 
411
                goto err;
 
412
                }
 
413
 
 
414
        ok=1;
 
415
err:
 
416
        EVP_PKEY_free(xk);
 
417
        return(ok);
 
418
        }