| 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 |