/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
unsigned long ret = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned char md[16];
- char *f;
+ char *f = NULL;
+ EVP_MD *digest = NULL;
if (ctx == NULL)
goto err;
f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
- if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL))
+ if (f == NULL)
+ goto err;
+ digest = EVP_MD_fetch(a->libctx, SN_md5, a->propq);
+ if (digest == NULL)
+ goto err;
+
+ if (!EVP_DigestInit_ex(ctx, digest, NULL))
goto err;
if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f)))
goto err;
- OPENSSL_free(f);
if (!EVP_DigestUpdate
(ctx, (unsigned char *)a->cert_info.serialNumber.data,
(unsigned long)a->cert_info.serialNumber.length))
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
err:
+ OPENSSL_free(f);
+ EVP_MD_free(digest);
EVP_MD_CTX_free(ctx);
return ret;
}
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
- int rv = memcmp(a->sha1_hash, b->sha1_hash, 20);
+ int rv;
+
+ if ((a->flags & EXFLAG_NO_FINGERPRINT) == 0
+ && (b->flags & EXFLAG_NO_FINGERPRINT) == 0)
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ else
+ return -2;
return rv < 0 ? -1 : rv > 0;
}
*/
int X509_cmp(const X509 *a, const X509 *b)
{
- int rv;
+ int rv = 0;
if (a == b) /* for efficiency */
return 0;
- /* 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);
+ /* attempt to compute cert hash */
+ (void)X509_check_purpose((X509 *)a, -1, 0);
+ (void)X509_check_purpose((X509 *)b, -1, 0);
+
+ if ((a->ex_flags & EXFLAG_NO_FINGERPRINT) == 0
+ && (b->ex_flags & EXFLAG_NO_FINGERPRINT) == 0)
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv != 0)
return rv < 0 ? -1 : 1;
+
/* 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 rv < 0 ? -1 : rv > 0;
}
-int X509_add_cert_new(STACK_OF(X509) **sk, X509 *cert, int flags)
+int ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags)
{
- if (*sk == NULL
- && (*sk = sk_X509_new_null()) == NULL) {
- ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
return 0;
}
- return X509_add_cert(*sk, cert, flags);
+ return X509_add_cert(*p_sk, cert, flags);
}
int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags)
return 1;
}
}
- if ((flags & X509_ADD_FLAG_NO_SS) != 0 && X509_self_signed(cert, 0))
- return 1;
+ if ((flags & X509_ADD_FLAG_NO_SS) != 0) {
+ int ret = X509_self_signed(cert, 0);
+
+ if (ret != 0)
+ return ret > 0 ? 1 : 0;
+ }
if (!sk_X509_insert(sk, cert,
(flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) {
- ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
return 0;
}
if ((flags & X509_ADD_FLAG_UP_REF) != 0)
}
int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags)
-/* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
+/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
+{
+ if (sk == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return ossl_x509_add_certs_new(&sk, certs, flags);
+}
+
+int ossl_x509_add_certs_new(STACK_OF(X509) **p_sk, STACK_OF(X509) *certs,
+ int flags)
+/* compiler would allow 'const' for the certs, yet they may get up-ref'ed */
{
- int n = sk_X509_num(certs); /* certs may be NULL */
+ int n = sk_X509_num(certs /* may be NULL */);
int i;
for (i = 0; i < n; i++) {
int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i;
/* if prepend, add certs in reverse order to keep original order */
- if (!X509_add_cert(sk, sk_X509_value(certs, j), flags))
+ if (!ossl_x509_add_cert_new(p_sk, sk_X509_value(certs, j), flags))
return 0;
}
return 1;
return -1;
/* Ensure canonical encoding is present and up to date */
- if (!a->canon_enc || a->modified) {
+ if (a->canon_enc == NULL || a->modified) {
ret = i2d_X509_NAME((X509_NAME *)a, NULL);
if (ret < 0)
return -2;
}
- if (!b->canon_enc || b->modified) {
+ if (b->canon_enc == NULL || 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)
+ if (ret == 0 && a->canon_enclen == 0)
+ return 0;
+
+ if (ret == 0) {
+ if (a->canon_enc == NULL || b->canon_enc == NULL)
+ return -2;
ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+ }
return ret < 0 ? -1 : ret > 0;
}
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+ int i2d_ret;
/* Make sure X509_NAME structure contains valid cached encoding */
- i2d_X509_NAME(x, NULL);
+ i2d_ret = i2d_X509_NAME(x, NULL);
if (ok != NULL)
*ok = 0;
- if (sha1 != NULL
+ if (i2d_ret >= 0 && sha1 != NULL
&& EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
goto end;
/* Make sure X509_NAME structure contains valid cached encoding */
- i2d_X509_NAME(x, NULL);
+ if (i2d_X509_NAME(x, NULL) < 0)
+ goto end;
+
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))
return X509_PUBKEY_get(x->cert_info.key);
}
-int X509_check_private_key(const X509 *x, const EVP_PKEY *k)
+int X509_check_private_key(const X509 *cert, const EVP_PKEY *pkey)
{
- const EVP_PKEY *xk;
- int ret;
-
- xk = X509_get0_pubkey(x);
+ const EVP_PKEY *xk = X509_get0_pubkey(cert);
- if (xk)
- ret = EVP_PKEY_eq(xk, k);
- else
- ret = -2;
+ if (xk == NULL) {
+ ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ return 0;
+ }
+ return ossl_x509_check_private_key(xk, pkey);
+}
- switch (ret) {
+int ossl_x509_check_private_key(const EVP_PKEY *x, const EVP_PKEY *pkey)
+{
+ if (x == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ switch (EVP_PKEY_eq(x, pkey)) {
case 1:
- break;
+ return 1;
case 0:
ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH);
- break;
+ return 0;
case -1:
ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH);
- break;
+ return 0;
case -2:
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE);
+ /* fall thru */
+ default:
+ return 0;
}
- if (ret > 0)
- return 1;
- return 0;
}
/*
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
- const EC_GROUP *grp = NULL;
+ char curve_name[80];
+ size_t curve_name_len;
int curve_nid;
- if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_EC)
- grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey));
- if (!grp)
+
+ if (pkey == NULL || !EVP_PKEY_is_a(pkey, "EC"))
return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
- curve_nid = EC_GROUP_get_curve_name(grp);
+
+ if (!EVP_PKEY_get_group_name(pkey, curve_name, sizeof(curve_name),
+ &curve_name_len))
+ return X509_V_ERR_SUITE_B_INVALID_CURVE;
+
+ curve_nid = OBJ_txt2nid(curve_name);
/* Check curve is consistent with LOS */
if (curve_nid == NID_secp384r1) { /* P-384 */
/*
if (chain == NULL)
return check_suite_b(pk, -1, &tflags);
- if (X509_get_version(x) != 2) {
+ if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
/* Correct error depth */
i = 0;
for (; i < sk_X509_num(chain); i++) {
sign_nid = X509_get_signature_nid(x);
x = sk_X509_value(chain, i);
- if (X509_get_version(x) != 2) {
+ if (X509_get_version(x) != X509_VERSION_3) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
goto end;
}
}
#endif
+
/*
* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref of
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
{
- STACK_OF(X509) *ret;
+ STACK_OF(X509) *ret = sk_X509_dup(chain);
int i;
- ret = sk_X509_dup(chain);
+
if (ret == NULL)
return NULL;
for (i = 0; i < sk_X509_num(ret); i++) {
X509 *x = sk_X509_value(ret, i);
+
if (!X509_up_ref(x))
goto err;
}
return ret;
+
err:
while (i-- > 0)
X509_free(sk_X509_value(ret, i));