X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fx509%2Fx509_cmp.c;h=2e444f28483e0f5b960249bd35d0f8b7b31b504a;hb=4b4f249e0d878d1037dc52d4fb96a657589ce5e5;hp=7dec3199cd7188dd9c979996d1572c93682b1d74;hpb=f73e07cf420ddad22b6148d8cbe28daf84ccae2d;p=oweals%2Fopenssl.git diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 7dec3199cd..2e444f2848 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -57,157 +57,175 @@ */ #include -#include -#include +#include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -int X509_issuer_and_serial_cmp(a,b) -X509 *a; -X509 *b; +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) { int i; X509_CINF *ai,*bi; ai=a->cert_info; bi=b->cert_info; - i=ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber); + i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber); if (i) return(i); return(X509_NAME_cmp(ai->issuer,bi->issuer)); } -#ifndef NO_MD5 -unsigned long X509_issuer_and_serial_hash(a) -X509 *a; +#ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_and_serial_hash(X509 *a) { unsigned long ret=0; - MD5_CTX ctx; + EVP_MD_CTX ctx; unsigned char md[16]; - char str[256]; + char *f; - X509_NAME_oneline(a->cert_info->issuer,str,256); - ret=strlen(str); - MD5_Init(&ctx); - MD5_Update(&ctx,(unsigned char *)str,ret); - MD5_Update(&ctx,(unsigned char *)a->cert_info->serialNumber->data, + EVP_MD_CTX_init(&ctx); + f=X509_NAME_oneline(a->cert_info->issuer,NULL,0); + ret=strlen(f); + EVP_DigestInit_ex(&ctx, EVP_md5(), NULL); + EVP_DigestUpdate(&ctx,(unsigned char *)f,ret); + OPENSSL_free(f); + EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data, (unsigned long)a->cert_info->serialNumber->length); - MD5_Final(&(md[0]),&ctx); + EVP_DigestFinal_ex(&ctx,&(md[0]),NULL); ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) )&0xffffffffL; + EVP_MD_CTX_cleanup(&ctx); return(ret); } #endif -int X509_issuer_name_cmp(a, b) -X509 *a; -X509 *b; +int X509_issuer_name_cmp(const X509 *a, const X509 *b) { return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer)); } -int X509_subject_name_cmp(a, b) -X509 *a; -X509 *b; +int X509_subject_name_cmp(const X509 *a, const X509 *b) { return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject)); } -int X509_CRL_cmp(a, b) -X509_CRL *a; -X509_CRL *b; +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) { return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer)); } -X509_NAME *X509_get_issuer_name(a) -X509 *a; +#ifndef OPENSSL_NO_SHA +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) + { + return memcmp(a->sha1_hash, b->sha1_hash, 20); + } +#endif + +X509_NAME *X509_get_issuer_name(X509 *a) { return(a->cert_info->issuer); } -unsigned long X509_issuer_name_hash(x) -X509 *x; +unsigned long X509_issuer_name_hash(X509 *x) { return(X509_NAME_hash(x->cert_info->issuer)); } -X509_NAME *X509_get_subject_name(a) -X509 *a; +X509_NAME *X509_get_subject_name(X509 *a) { return(a->cert_info->subject); } -ASN1_INTEGER *X509_get_serialNumber(a) -X509 *a; +ASN1_INTEGER *X509_get_serialNumber(X509 *a) { return(a->cert_info->serialNumber); } -unsigned long X509_subject_name_hash(x) -X509 *x; +unsigned long X509_subject_name_hash(X509 *x) { return(X509_NAME_hash(x->cert_info->subject)); } -int X509_NAME_cmp(a, b) -X509_NAME *a; -X509_NAME *b; +#ifndef OPENSSL_NO_SHA +/* Compare two certificates: they must be identical for + * this to work. NB: Although "cmp" operations are generally + * prototyped to take "const" arguments (eg. for use in + * STACKs), the way X509 handling is - these operations may + * involve ensuring the hashes are up-to-date and ensuring + * certain cert information is cached. So this is the point + * where the "depth-first" constification tree has to halt + * with an evil cast. + */ +int X509_cmp(const X509 *a, const X509 *b) +{ + /* ensure hash is valid */ + X509_check_purpose((X509 *)a, -1, 0); + X509_check_purpose((X509 *)b, -1, 0); + + return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); +} +#endif + + +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { - int i,j; - X509_NAME_ENTRY *na,*nb; + int ret; - if (sk_num(a->entries) != sk_num(b->entries)) - return(sk_num(a->entries)-sk_num(b->entries)); - for (i=sk_num(a->entries)-1; i>=0; i--) + /* Ensure canonical encoding is present and up to date */ + + if (!a->canon_enc || a->modified) { - na=(X509_NAME_ENTRY *)sk_value(a->entries,i); - nb=(X509_NAME_ENTRY *)sk_value(b->entries,i); - j=na->value->length-nb->value->length; - if (j) return(j); - j=memcmp(na->value->data,nb->value->data, - na->value->length); - if (j) return(j); - j=na->set-nb->set; - if (j) return(j); + ret = i2d_X509_NAME((X509_NAME *)a, NULL); + if (ret < 0) + return -2; } - /* We will check the object types after checking the values - * since the values will more often be different than the object - * types. */ - for (i=sk_num(a->entries)-1; i>=0; i--) + if (!b->canon_enc || b->modified) { - na=(X509_NAME_ENTRY *)sk_value(a->entries,i); - nb=(X509_NAME_ENTRY *)sk_value(b->entries,i); - j=OBJ_cmp(na->object,nb->object); - if (j) return(j); + ret = i2d_X509_NAME((X509_NAME *)b, NULL); + if (ret < 0) + return -2; } - return(0); + + ret = a->canon_enclen - b->canon_enclen; + + if (ret) + return ret; + + return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); + } -#ifndef NO_MD5 +unsigned long X509_NAME_hash(X509_NAME *x) + { + unsigned long ret=0; + unsigned char md[SHA_DIGEST_LENGTH]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x,NULL); + EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL); + + ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| + ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) + )&0xffffffffL; + return(ret); + } + + +#ifndef OPENSSL_NO_MD5 /* I now DER encode the name and hash it. Since I cache the DER encoding, - * this is reasonably effiecent. */ -unsigned long X509_NAME_hash(x) -X509_NAME *x; + * this is reasonably efficient. */ + +unsigned long X509_NAME_hash_old(X509_NAME *x) { unsigned long ret=0; unsigned char md[16]; - unsigned char str[256],*p,*pp; - int i; - - i=i2d_X509_NAME(x,NULL); - if (i > sizeof(str)) - p=Malloc(i); - else - p=str; - pp=p; - i2d_X509_NAME(x,&pp); - MD5((unsigned char *)p,i,&(md[0])); - if (p != str) Free(p); + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x,NULL); + EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL); ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) @@ -217,15 +235,15 @@ X509_NAME *x; #endif /* Search a stack of X509 for a match */ -X509 *X509_find_by_issuer_and_serial(sk,name,serial) -STACK_OF(X509) *sk; -X509_NAME *name; -ASN1_INTEGER *serial; +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial) { int i; X509_CINF cinf; X509 x,*x509=NULL; + if(!sk) return NULL; + x.cert_info= &cinf; cinf.serialNumber=serial; cinf.issuer=name; @@ -239,9 +257,7 @@ ASN1_INTEGER *serial; return(NULL); } -X509 *X509_find_by_subject(sk,name) -STACK_OF(X509) *sk; -X509_NAME *name; +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) { X509 *x509; int i; @@ -255,61 +271,47 @@ X509_NAME *name; return(NULL); } -EVP_PKEY *X509_get_pubkey(x) -X509 *x; +EVP_PKEY *X509_get_pubkey(X509 *x) { if ((x == NULL) || (x->cert_info == NULL)) return(NULL); return(X509_PUBKEY_get(x->cert_info->key)); } -int X509_check_private_key(x,k) -X509 *x; -EVP_PKEY *k; +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) + { + if(!x) return NULL; + return x->cert_info->key->public_key; + } + +int X509_check_private_key(X509 *x, EVP_PKEY *k) { - EVP_PKEY *xk=NULL; - int ok=0; + EVP_PKEY *xk; + int ret; xk=X509_get_pubkey(x); - if (xk->type != k->type) - { - SSLerr(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH); - goto err; - } - switch (k->type) + + if (xk) + ret = EVP_PKEY_cmp(xk, k); + else + ret = -2; + + switch (ret) { -#ifndef NO_RSA - case EVP_PKEY_RSA: - if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0 - || BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0) - { - SSLerr(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH); - goto err; - } + case 1: break; -#endif -#ifndef NO_DSA - case EVP_PKEY_DSA: - if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0) - { - SSLerr(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH); - goto err; - } + case 0: + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH); break; -#endif -#ifndef NO_DH - case EVP_PKEY_DH: - /* No idea */ - SSLerr(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY); - goto err; -#endif - default: - SSLerr(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE); - goto err; + case -1: + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE); } - - ok=1; -err: - EVP_PKEY_free(xk); - return(ok); + if (xk) + EVP_PKEY_free(xk); + if (ret > 0) + return 1; + return 0; }