OLD | NEW |
1 /* crypto/x509/x509_cmp.c */ | 1 /* crypto/x509/x509_cmp.c */ |
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 * |
5 * This package is an SSL implementation written | 5 * This package is an SSL implementation written |
6 * by Eric Young (eay@cryptsoft.com). | 6 * by Eric Young (eay@cryptsoft.com). |
7 * The implementation was written so as to conform with Netscapes SSL. | 7 * The implementation was written so as to conform with Netscapes SSL. |
8 * | 8 * |
9 * This library is free for commercial and non-commercial use as long as | 9 * This library is free for commercial and non-commercial use as long as |
10 * the following conditions are aheared to. The following conditions | 10 * the following conditions are aheared to. The following conditions |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 int X509_subject_name_cmp(const X509 *a, const X509 *b) | 109 int X509_subject_name_cmp(const X509 *a, const X509 *b) |
110 { | 110 { |
111 return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject)); | 111 return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject)); |
112 } | 112 } |
113 | 113 |
114 int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) | 114 int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) |
115 { | 115 { |
116 return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer)); | 116 return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer)); |
117 } | 117 } |
118 | 118 |
| 119 #ifndef OPENSSL_NO_SHA |
| 120 int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) |
| 121 { |
| 122 return memcmp(a->sha1_hash, b->sha1_hash, 20); |
| 123 } |
| 124 #endif |
| 125 |
119 X509_NAME *X509_get_issuer_name(X509 *a) | 126 X509_NAME *X509_get_issuer_name(X509 *a) |
120 { | 127 { |
121 return(a->cert_info->issuer); | 128 return(a->cert_info->issuer); |
122 } | 129 } |
123 | 130 |
124 unsigned long X509_issuer_name_hash(X509 *x) | 131 unsigned long X509_issuer_name_hash(X509 *x) |
125 { | 132 { |
126 return(X509_NAME_hash(x->cert_info->issuer)); | 133 return(X509_NAME_hash(x->cert_info->issuer)); |
127 } | 134 } |
128 | 135 |
| 136 #ifndef OPENSSL_NO_MD5 |
| 137 unsigned long X509_issuer_name_hash_old(X509 *x) |
| 138 { |
| 139 return(X509_NAME_hash_old(x->cert_info->issuer)); |
| 140 } |
| 141 #endif |
| 142 |
129 X509_NAME *X509_get_subject_name(X509 *a) | 143 X509_NAME *X509_get_subject_name(X509 *a) |
130 { | 144 { |
131 return(a->cert_info->subject); | 145 return(a->cert_info->subject); |
132 } | 146 } |
133 | 147 |
134 ASN1_INTEGER *X509_get_serialNumber(X509 *a) | 148 ASN1_INTEGER *X509_get_serialNumber(X509 *a) |
135 { | 149 { |
136 return(a->cert_info->serialNumber); | 150 return(a->cert_info->serialNumber); |
137 } | 151 } |
138 | 152 |
139 unsigned long X509_subject_name_hash(X509 *x) | 153 unsigned long X509_subject_name_hash(X509 *x) |
140 { | 154 { |
141 return(X509_NAME_hash(x->cert_info->subject)); | 155 return(X509_NAME_hash(x->cert_info->subject)); |
142 } | 156 } |
143 | 157 |
| 158 #ifndef OPENSSL_NO_MD5 |
| 159 unsigned long X509_subject_name_hash_old(X509 *x) |
| 160 { |
| 161 return(X509_NAME_hash_old(x->cert_info->subject)); |
| 162 } |
| 163 #endif |
| 164 |
144 #ifndef OPENSSL_NO_SHA | 165 #ifndef OPENSSL_NO_SHA |
145 /* Compare two certificates: they must be identical for | 166 /* Compare two certificates: they must be identical for |
146 * this to work. NB: Although "cmp" operations are generally | 167 * this to work. NB: Although "cmp" operations are generally |
147 * prototyped to take "const" arguments (eg. for use in | 168 * prototyped to take "const" arguments (eg. for use in |
148 * STACKs), the way X509 handling is - these operations may | 169 * STACKs), the way X509 handling is - these operations may |
149 * involve ensuring the hashes are up-to-date and ensuring | 170 * involve ensuring the hashes are up-to-date and ensuring |
150 * certain cert information is cached. So this is the point | 171 * certain cert information is cached. So this is the point |
151 * where the "depth-first" constification tree has to halt | 172 * where the "depth-first" constification tree has to halt |
152 * with an evil cast. | 173 * with an evil cast. |
153 */ | 174 */ |
154 int X509_cmp(const X509 *a, const X509 *b) | 175 int X509_cmp(const X509 *a, const X509 *b) |
155 { | 176 { |
156 /* ensure hash is valid */ | 177 /* ensure hash is valid */ |
157 X509_check_purpose((X509 *)a, -1, 0); | 178 X509_check_purpose((X509 *)a, -1, 0); |
158 X509_check_purpose((X509 *)b, -1, 0); | 179 X509_check_purpose((X509 *)b, -1, 0); |
159 | 180 |
160 return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); | 181 return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); |
161 } | 182 } |
162 #endif | 183 #endif |
163 | 184 |
164 | 185 |
165 /* Case insensitive string comparision */ | 186 int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) |
166 static int nocase_cmp(const ASN1_STRING *a, const ASN1_STRING *b) | 187 » { |
167 { | 188 » int ret; |
168 » int i; | |
169 | 189 |
170 » if (a->length != b->length) | 190 » /* Ensure canonical encoding is present and up to date */ |
171 » » return (a->length - b->length); | |
172 | 191 |
173 » for (i=0; i<a->length; i++) | 192 » if (!a->canon_enc || a->modified) |
174 » { | 193 » » { |
175 » » int ca, cb; | 194 » » ret = i2d_X509_NAME((X509_NAME *)a, NULL); |
| 195 » » if (ret < 0) |
| 196 » » » return -2; |
| 197 » » } |
176 | 198 |
177 » » ca = tolower(a->data[i]); | 199 » if (!b->canon_enc || b->modified) |
178 » » cb = tolower(b->data[i]); | 200 » » { |
| 201 » » ret = i2d_X509_NAME((X509_NAME *)b, NULL); |
| 202 » » if (ret < 0) |
| 203 » » » return -2; |
| 204 » » } |
179 | 205 |
180 » » if (ca != cb) | 206 » ret = a->canon_enclen - b->canon_enclen; |
181 » » » return(ca-cb); | |
182 » } | |
183 » return 0; | |
184 } | |
185 | 207 |
186 /* Case insensitive string comparision with space normalization | 208 » if (ret) |
187 * Space normalization - ignore leading, trailing spaces, | 209 » » return ret; |
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 | 210 |
200 » /* skip leading spaces */ | 211 » return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); |
201 » while (la > 0 && isspace(*pa)) | 212 |
202 » { | |
203 » » la--; | |
204 » » pa++; | |
205 » } | |
206 » while (lb > 0 && isspace(*pb)) | |
207 » { | |
208 » » lb--; | |
209 » » pb++; | |
210 } | 213 } |
211 | 214 |
212 » /* skip trailing spaces */ | 215 unsigned long X509_NAME_hash(X509_NAME *x) |
213 » while (la > 0 && isspace(pa[la-1])) | 216 » { |
214 » » la--; | 217 » unsigned long ret=0; |
215 » while (lb > 0 && isspace(pb[lb-1])) | 218 » unsigned char md[SHA_DIGEST_LENGTH]; |
216 » » lb--; | |
217 | 219 |
218 » /* compare strings with space normalization */ | 220 » /* Make sure X509_NAME structure contains valid cached encoding */ |
219 » while (la > 0 && lb > 0) | 221 » i2d_X509_NAME(x,NULL); |
220 » { | 222 » EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL); |
221 » » int ca, cb; | |
222 | 223 |
223 » » /* compare character */ | 224 » ret=(» ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| |
224 » » ca = tolower(*pa); | 225 » » ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) |
225 » » cb = tolower(*pb); | 226 » » )&0xffffffffL; |
226 » » if (ca != cb) | 227 » return(ret); |
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 static int asn1_string_memcmp(ASN1_STRING *a, ASN1_STRING *b) | |
258 » { | |
259 » int j; | |
260 » j = a->length - b->length; | |
261 » if (j) | |
262 » » return j; | |
263 » return memcmp(a->data, b->data, a->length); | |
264 } | 228 } |
265 | 229 |
266 #define STR_TYPE_CMP (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_UTF8STRING) | |
267 | |
268 int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) | |
269 { | |
270 int i,j; | |
271 X509_NAME_ENTRY *na,*nb; | |
272 | |
273 unsigned long nabit, nbbit; | |
274 | |
275 j = sk_X509_NAME_ENTRY_num(a->entries) | |
276 - sk_X509_NAME_ENTRY_num(b->entries); | |
277 if (j) | |
278 return j; | |
279 for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) | |
280 { | |
281 na=sk_X509_NAME_ENTRY_value(a->entries,i); | |
282 nb=sk_X509_NAME_ENTRY_value(b->entries,i); | |
283 j=na->value->type-nb->value->type; | |
284 if (j) | |
285 { | |
286 nabit = ASN1_tag2bit(na->value->type); | |
287 nbbit = ASN1_tag2bit(nb->value->type); | |
288 if (!(nabit & STR_TYPE_CMP) || | |
289 !(nbbit & STR_TYPE_CMP)) | |
290 return j; | |
291 if (!asn1_string_memcmp(na->value, nb->value)) | |
292 j = 0; | |
293 } | |
294 else if (na->value->type == V_ASN1_PRINTABLESTRING) | |
295 j=nocase_spacenorm_cmp(na->value, nb->value); | |
296 else if (na->value->type == V_ASN1_IA5STRING | |
297 && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress) | |
298 j=nocase_cmp(na->value, nb->value); | |
299 else | |
300 j = asn1_string_memcmp(na->value, nb->value); | |
301 if (j) return(j); | |
302 j=na->set-nb->set; | |
303 if (j) return(j); | |
304 } | |
305 | |
306 /* We will check the object types after checking the values | |
307 * since the values will more often be different than the object | |
308 * types. */ | |
309 for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) | |
310 { | |
311 na=sk_X509_NAME_ENTRY_value(a->entries,i); | |
312 nb=sk_X509_NAME_ENTRY_value(b->entries,i); | |
313 j=OBJ_cmp(na->object,nb->object); | |
314 if (j) return(j); | |
315 } | |
316 return(0); | |
317 } | |
318 | 230 |
319 #ifndef OPENSSL_NO_MD5 | 231 #ifndef OPENSSL_NO_MD5 |
320 /* I now DER encode the name and hash it. Since I cache the DER encoding, | 232 /* I now DER encode the name and hash it. Since I cache the DER encoding, |
321 * this is reasonably efficient. */ | 233 * this is reasonably efficient. */ |
322 unsigned long X509_NAME_hash(X509_NAME *x) | 234 |
| 235 unsigned long X509_NAME_hash_old(X509_NAME *x) |
323 { | 236 { |
324 unsigned long ret=0; | 237 unsigned long ret=0; |
325 unsigned char md[16]; | 238 unsigned char md[16]; |
326 EVP_MD_CTX md_ctx; | |
327 | 239 |
328 /* Make sure X509_NAME structure contains valid cached encoding */ | 240 /* Make sure X509_NAME structure contains valid cached encoding */ |
329 i2d_X509_NAME(x,NULL); | 241 i2d_X509_NAME(x,NULL); |
330 » EVP_MD_CTX_init(&md_ctx); | 242 » EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL); |
331 » EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); | |
332 » EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL); | |
333 » EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length); | |
334 » EVP_DigestFinal_ex(&md_ctx,md,NULL); | |
335 » EVP_MD_CTX_cleanup(&md_ctx); | |
336 | 243 |
337 ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| | 244 ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| |
338 ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) | 245 ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) |
339 )&0xffffffffL; | 246 )&0xffffffffL; |
340 return(ret); | 247 return(ret); |
341 } | 248 } |
342 #endif | 249 #endif |
343 | 250 |
344 /* Search a stack of X509 for a match */ | 251 /* Search a stack of X509 for a match */ |
345 X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, | 252 X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 } | 293 } |
387 | 294 |
388 ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) | 295 ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) |
389 { | 296 { |
390 if(!x) return NULL; | 297 if(!x) return NULL; |
391 return x->cert_info->key->public_key; | 298 return x->cert_info->key->public_key; |
392 } | 299 } |
393 | 300 |
394 int X509_check_private_key(X509 *x, EVP_PKEY *k) | 301 int X509_check_private_key(X509 *x, EVP_PKEY *k) |
395 { | 302 { |
396 » EVP_PKEY *xk=NULL; | 303 » EVP_PKEY *xk; |
397 » int ok=0; | 304 » int ret; |
398 | 305 |
399 xk=X509_get_pubkey(x); | 306 xk=X509_get_pubkey(x); |
400 » switch (EVP_PKEY_cmp(xk, k)) | 307 |
| 308 » if (xk) |
| 309 » » ret = EVP_PKEY_cmp(xk, k); |
| 310 » else |
| 311 » » ret = -2; |
| 312 |
| 313 » switch (ret) |
401 { | 314 { |
402 case 1: | 315 case 1: |
403 ok=1; | |
404 break; | 316 break; |
405 case 0: | 317 case 0: |
406 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH
); | 318 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH
); |
407 break; | 319 break; |
408 case -1: | 320 case -1: |
409 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH); | 321 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH); |
410 break; | 322 break; |
411 case -2: | 323 case -2: |
412 #ifndef OPENSSL_NO_EC | |
413 if (k->type == EVP_PKEY_EC) | |
414 { | |
415 X509err(X509_F_X509_CHECK_PRIVATE_KEY, ERR_R_EC_LIB); | |
416 break; | |
417 } | |
418 #endif | |
419 #ifndef OPENSSL_NO_DH | |
420 if (k->type == EVP_PKEY_DH) | |
421 { | |
422 /* No idea */ | |
423 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_
DH_KEY); | |
424 break; | |
425 } | |
426 #endif | |
427 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE); | 324 X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE); |
428 } | 325 } |
429 | 326 » if (xk) |
430 » EVP_PKEY_free(xk); | 327 » » EVP_PKEY_free(xk); |
431 » return(ok); | 328 » if (ret > 0) |
| 329 » » return 1; |
| 330 » return 0; |
432 } | 331 } |
OLD | NEW |