aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--crypto/evp/evp.h2
-rw-r--r--crypto/evp/p_lib.c46
-rw-r--r--crypto/x509/x509.h3
-rw-r--r--crypto/x509/x509_cmp.c62
-rw-r--r--crypto/x509/x509_err.c3
-rw-r--r--crypto/x509/x509_req.c40
7 files changed, 116 insertions, 45 deletions
diff --git a/CHANGES b/CHANGES
index 505ef51880..0d767703cd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
Changes between 0.9.7a and 0.9.8 [xx XXX xxxx]
+ *) Add functionality to check the public key of a certificate request
+ against a given private. This is useful to check that a certificate
+ request can be signed by that key (self-signing).
+ [Richard Levitte]
+
*) Make it possible to have multiple active certificates with the same
subject in the CA index file. This is done only if the keyword
'unique_subject' is set to 'no' in the main CA section (default
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index b084a35809..4e4a667ab8 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -754,6 +754,8 @@ int EVP_PKEY_missing_parameters(EVP_PKEY *pkey);
int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode);
int EVP_PKEY_cmp_parameters(EVP_PKEY *a,EVP_PKEY *b);
+int EVP_PKEY_cmp(EVP_PKEY *a,EVP_PKEY *b);
+
int EVP_CIPHER_type(const EVP_CIPHER *ctx);
/* calls methods */
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index c7a3dee108..8d23c0bd72 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -237,6 +237,52 @@ int EVP_PKEY_cmp_parameters(EVP_PKEY *a, EVP_PKEY *b)
return(-1);
}
+int EVP_PKEY_cmp(EVP_PKEY *a, EVP_PKEY *b)
+ {
+ if (a->type != b->type)
+ return -1;
+
+ switch (a->type)
+ {
+#ifndef OPENSSL_NO_RSA
+ case EVP_PKEY_RSA:
+ if (BN_cmp(b->pkey.rsa->n,a->pkey.rsa->n) != 0
+ || BN_cmp(b->pkey.rsa->e,a->pkey.rsa->e) != 0)
+ return 0;
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case EVP_PKEY_DSA:
+ if (BN_cmp(b->pkey.dsa->pub_key,a->pkey.dsa->pub_key) != 0)
+ return 0;
+ break;
+#endif
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ {
+ int r = EC_POINT_cmp(b->pkey.eckey->group,
+ b->pkey.eckey->pub_key,a->pkey.eckey->pub_key,NULL);
+ if (r != 0)
+ {
+ if (r == 1)
+ return 0;
+ else
+ return -2;
+ }
+ }
+ break;
+#endif
+#ifndef OPENSSL_NO_DH
+ case EVP_PKEY_DH:
+ return -2;
+#endif
+ default:
+ return -2;
+ }
+
+ return 1;
+ }
+
EVP_PKEY *EVP_PKEY_new(void)
{
EVP_PKEY *ret;
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 53a8f6c758..049308ba80 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -1038,6 +1038,8 @@ int X509_CRL_sort(X509_CRL *crl);
int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
+
int X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
@@ -1271,6 +1273,7 @@ void ERR_load_X509_strings(void);
#define X509_F_X509_PRINT_FP 118
#define X509_F_X509_PUBKEY_GET 119
#define X509_F_X509_PUBKEY_SET 120
+#define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144
#define X509_F_X509_REQ_PRINT 121
#define X509_F_X509_REQ_PRINT_FP 122
#define X509_F_X509_REQ_TO_X509 123
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 9b28911409..5dfdcd41cb 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -374,62 +374,36 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k)
int ok=0;
xk=X509_get_pubkey(x);
- if (xk->type != k->type)
- {
- X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH);
- goto err;
- }
- switch (k->type)
+ switch (EVP_PKEY_cmp(xk, k))
{
-#ifndef OPENSSL_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)
- {
- X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);
- goto err;
- }
+ case 1:
+ ok=1;
break;
-#endif
-#ifndef OPENSSL_NO_DSA
- case EVP_PKEY_DSA:
- if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0)
- {
- X509err(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
+ case -1:
+ X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- {
- int r = EC_POINT_cmp(xk->pkey.eckey->group,
- xk->pkey.eckey->pub_key,k->pkey.eckey->pub_key,NULL);
- if (r != 0)
+ if (k->type == EVP_PKEY_EC)
{
- if (r == 1)
- X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH);
- else
- X509err(X509_F_X509_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
-
- goto err;
+ X509err(X509_F_X509_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
+ break;
}
- }
- break;
#endif
#ifndef OPENSSL_NO_DH
- case EVP_PKEY_DH:
- /* No idea */
- X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY);
- goto err;
+ if (k->type == EVP_PKEY_DH)
+ {
+ /* No idea */
+ X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY);
+ break;
+ }
#endif
- default:
X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE);
- goto err;
}
- ok=1;
-err:
EVP_PKEY_free(xk);
return(ok);
}
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index 5bbf4acf76..7a6d5a0072 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -1,6 +1,6 @@
/* crypto/x509/x509_err.c */
/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -95,6 +95,7 @@ static ERR_STRING_DATA X509_str_functs[]=
{ERR_PACK(0,X509_F_X509_PRINT_FP,0), "X509_print_fp"},
{ERR_PACK(0,X509_F_X509_PUBKEY_GET,0), "X509_PUBKEY_get"},
{ERR_PACK(0,X509_F_X509_PUBKEY_SET,0), "X509_PUBKEY_set"},
+{ERR_PACK(0,X509_F_X509_REQ_CHECK_PRIVATE_KEY,0), "X509_REQ_check_private_key"},
{ERR_PACK(0,X509_F_X509_REQ_PRINT,0), "X509_REQ_print"},
{ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0), "X509_REQ_print_fp"},
{ERR_PACK(0,X509_F_X509_REQ_TO_X509,0), "X509_REQ_to_X509"},
diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c
index 0affa3bf30..b4ad53431e 100644
--- a/crypto/x509/x509_req.c
+++ b/crypto/x509/x509_req.c
@@ -113,6 +113,46 @@ EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
return(X509_PUBKEY_get(req->req_info->pubkey));
}
+int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
+ {
+ EVP_PKEY *xk=NULL;
+ int ok=0;
+
+ xk=X509_REQ_get_pubkey(x);
+ switch (EVP_PKEY_cmp(xk, k))
+ {
+ case 1:
+ ok=1;
+ break;
+ case 0:
+ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+#ifndef OPENSSL_NO_EC
+ if (k->type == EVP_PKEY_EC)
+ {
+ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
+ break;
+ }
+#endif
+#ifndef OPENSSL_NO_DH
+ if (k->type == EVP_PKEY_DH)
+ {
+ /* No idea */
+ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY);
+ break;
+ }
+#endif
+ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE);
+ }
+
+ EVP_PKEY_free(xk);
+ return(ok);
+ }
+
/* It seems several organisations had the same idea of including a list of
* extensions in a certificate request. There are at least two OIDs that are
* used and there may be more: so the list is configurable.