From e6526fbf4dc894d71ae3517a1ba484475b79b402 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Thu, 3 Apr 2003 22:27:24 +0000 Subject: [PATCH] Add functionality to help making self-signed certificate. --- CHANGES | 5 ++++ crypto/evp/evp.h | 2 ++ crypto/evp/p_lib.c | 46 +++++++++++++++++++++++++++++++ crypto/x509/x509.h | 3 ++ crypto/x509/x509_cmp.c | 62 ++++++++++++------------------------------ crypto/x509/x509_err.c | 3 +- crypto/x509/x509_req.c | 40 +++++++++++++++++++++++++++ 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. -- 2.25.1