-
-int X509_issuer_name_cmp(a, b)
-X509 *a;
-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;
- {
- return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
- }
-
-int X509_CRL_cmp(a, b)
-X509_CRL *a;
-X509_CRL *b;
- {
- return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
- }
-
-X509_NAME *X509_get_issuer_name(a)
-X509 *a;
- {
- return(a->cert_info->issuer);
- }
-
-unsigned long X509_issuer_name_hash(x)
-X509 *x;
- {
- return(X509_NAME_hash(x->cert_info->issuer));
- }
-
-X509_NAME *X509_get_subject_name(a)
-X509 *a;
- {
- return(a->cert_info->subject);
- }
-
-ASN1_INTEGER *X509_get_serialNumber(a)
-X509 *a;
- {
- return(a->cert_info->serialNumber);
- }
-
-unsigned long X509_subject_name_hash(x)
-X509 *x;
- {
- return(X509_NAME_hash(x->cert_info->subject));
- }
-
-int X509_NAME_cmp(a, b)
-X509_NAME *a;
-X509_NAME *b;
- {
- int i,j;
- X509_NAME_ENTRY *na,*nb;
-
- 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--)
- {
- 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);
- }
-
- /* 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--)
- {
- 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);
- }
- return(0);
- }
-
-#ifndef 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;
- {
- 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);
-
- ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
- ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
- )&0xffffffffL;
- return(ret);
- }
+
+X509_NAME *X509_get_subject_name(const X509 *a)
+{
+ return a->cert_info.subject;
+}
+
+ASN1_INTEGER *X509_get_serialNumber(X509 *a)
+{
+ return &a->cert_info.serialNumber;
+}
+
+const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
+{
+ return &a->cert_info.serialNumber;
+}
+
+unsigned long X509_subject_name_hash(X509 *x)
+{
+ return X509_NAME_hash(x->cert_info.subject);
+}
+
+#ifndef OPENSSL_NO_MD5
+unsigned long X509_subject_name_hash_old(X509 *x)
+{
+ return X509_NAME_hash_old(x->cert_info.subject);
+}
+#endif
+
+/*
+ * 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)
+{
+ int rv;
+
+ /* ensure hash is valid */
+ if (X509_check_purpose((X509 *)a, -1, 0) != 1)
+ return -2;
+ if (X509_check_purpose((X509 *)b, -1, 0) != 1)
+ return -2;
+
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ if (rv)
+ return rv;
+ /* Check for match against stored encoding too */
+ if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
+ if (a->cert_info.enc.len < b->cert_info.enc.len)
+ return -1;
+ if (a->cert_info.enc.len > b->cert_info.enc.len)
+ return 1;
+ return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc,
+ a->cert_info.enc.len);
+ }
+ return rv;
+}
+
+int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
+{
+ int ret;
+
+ /* Ensure canonical encoding is present and up to date */
+
+ if (!a->canon_enc || a->modified) {
+ ret = i2d_X509_NAME((X509_NAME *)a, NULL);
+ if (ret < 0)
+ return -2;
+ }
+
+ if (!b->canon_enc || b->modified) {
+ ret = i2d_X509_NAME((X509_NAME *)b, NULL);
+ if (ret < 0)
+ return -2;
+ }
+
+ ret = a->canon_enclen - b->canon_enclen;
+
+ if (ret != 0 || a->canon_enclen == 0)
+ return ret;
+
+ return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+
+}
+
+unsigned long X509_NAME_hash(const 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);
+ if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
+ NULL))
+ return 0;
+
+ 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 efficient.
+ */
+
+unsigned long X509_NAME_hash_old(const X509_NAME *x)
+{
+ EVP_MD *md5 = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "-fips");
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+ unsigned long ret = 0;
+ unsigned char md[16];
+
+ if (md5 == NULL || md_ctx == NULL)
+ goto end;
+
+ /* Make sure X509_NAME structure contains valid cached encoding */
+ i2d_X509_NAME(x, NULL);
+ if (EVP_DigestInit_ex(md_ctx, md5, NULL)
+ && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
+ && EVP_DigestFinal_ex(md_ctx, md, NULL))
+ ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+ ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+ ) & 0xffffffffL;
+
+ end:
+ EVP_MD_CTX_free(md_ctx);
+ EVP_MD_free(md5);
+
+ return ret;
+}