original files of m241
This commit is contained in:
@@ -0,0 +1,890 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
* SOURCE FILE
|
||||
*
|
||||
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_payload_certificate.c,v $ $Revision: 1.19.10.4 $
|
||||
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_payload_certificate.c,v $
|
||||
* $Author: edahlber $ $Date: 2012-02-15 08:41:53 $
|
||||
* $State: Exp $ $Locker: $
|
||||
*
|
||||
* INTERPEAK_COPYRIGHT_STRING
|
||||
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/* Certificate payload (RFC 2408, chapter 3.9) */
|
||||
/* IKE version 1 and 2 */
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
#include "ipike_config.h"
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include "ipike_h.h"
|
||||
#include "ipike_payload_certificate.h"
|
||||
#include "ipike_crypto.h"
|
||||
#include "ipike_util.h"
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_data
|
||||
*===========================================================================
|
||||
* Description: Returns a pointer to the certificate data in the payload.
|
||||
* Parameters: cert - A certificate payload.
|
||||
* Returns: A pointer to the certificate data.
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_u8*
|
||||
ipike_payload_certificate_data(Ipike_cert_payload* hash);
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_data_length
|
||||
*===========================================================================
|
||||
* Description: Returns the length of the certificate data.
|
||||
* Parameters: cert - A certificate payload.
|
||||
* Returns: The length of the certificate data (in bytes).
|
||||
*
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_u16
|
||||
ipike_payload_certificate_data_length(Ipike_cert_payload* cert);
|
||||
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_data
|
||||
*===========================================================================
|
||||
* Description: Returns a pointer to the certificate data in the payload.
|
||||
* Parameters: cert - A certificate payload.
|
||||
* Returns: A pointer to the certificate data.
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_u8*
|
||||
ipike_payload_certificate_req_data(Ipike_cert_req_payload* hash);
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_data_length
|
||||
*===========================================================================
|
||||
* Description: Returns the length of the certificate data.
|
||||
* Parameters: cert - A certificate payload.
|
||||
* Returns: The length of the certificate data (in bytes).
|
||||
*
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_u16
|
||||
ipike_payload_certificate_req_data_length(Ipike_cert_req_payload* certreq);
|
||||
|
||||
#endif /* IPIKE_USE_OCSP */
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 LOCAL FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_data
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_STATIC Ip_u8*
|
||||
ipike_payload_certificate_data(Ipike_cert_payload* cert)
|
||||
{
|
||||
return (Ip_u8*) cert + 5;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_data_length
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_STATIC Ip_u16
|
||||
ipike_payload_certificate_data_length(Ipike_cert_payload* cert)
|
||||
{
|
||||
return IPIKE_PAYLOAD_DATA_LENGTH(cert->header.length, 5);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_data
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_STATIC Ip_u8*
|
||||
ipike_payload_certificate_req_data(Ipike_cert_req_payload* hash)
|
||||
{
|
||||
return (Ip_u8*) hash + 5;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_data_length
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_STATIC Ip_u16
|
||||
ipike_payload_certificate_req_data_length(Ipike_cert_req_payload* certreq)
|
||||
{
|
||||
return IPIKE_PAYLOAD_DATA_LENGTH(certreq->header.length, 5);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_encode_type_to_string
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_STATIC const char*
|
||||
ipike_payload_certificate_encode_type_to_string(Ip_u8 type)
|
||||
{
|
||||
const char* s;
|
||||
if ((ipike_map_string(ipike.cert_encode_type_map, type, &s)))
|
||||
return "unknown certificate encoding type";
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 10 PUBLIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_free
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipike_payload_certificate_free(Ipike_cert* cert)
|
||||
{
|
||||
if (IP_NULL != cert->local)
|
||||
X509_free(cert->local);
|
||||
if (IP_NULL != cert->peer)
|
||||
X509_free(cert->peer);
|
||||
if (IP_NULL != cert->peer_url)
|
||||
ipcom_free((void*)cert->peer_url);
|
||||
ipike_array_free((void**)cert->crls, (void(*)(void*)) X509_CRL_free);
|
||||
ipike_array_free((void**)cert->ca, (void(*)(void*)) X509_free);
|
||||
ipike_array_free((void**)cert->trusted, (void(*)(void*)) X509_free);
|
||||
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
if (IP_NULL != cert->resp_local)
|
||||
OCSP_RESPONSE_free(cert->resp_local);
|
||||
if (IP_NULL != cert->resp_peer)
|
||||
OCSP_RESPONSE_free(cert->resp_peer);
|
||||
#endif
|
||||
|
||||
ipcom_memset(cert, 0, sizeof(Ipike_cert));
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_create
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_create(
|
||||
X509* cert,
|
||||
const char *url,
|
||||
Ipike_cert_payload** payload
|
||||
)
|
||||
{
|
||||
unsigned char* cert_data;
|
||||
int cert_len;
|
||||
int payload_len;
|
||||
int encoding = IPIKE_CERT_X509_SIGNATURE;
|
||||
|
||||
if (IP_NULL == cert)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_create: no certificate specified, check configuration");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
cert_len = i2d_X509(cert, IP_NULL);
|
||||
if (cert_len <= 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR,
|
||||
"ipike_payload_certificate_create: failed to determine the length of the certificate");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
payload_len = 5 + cert_len;
|
||||
if (IP_NULL == (*payload = ipcom_calloc(1, (Ip_size_t) payload_len)))
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
cert_data = (unsigned char*)ipike_payload_certificate_data(*payload);
|
||||
if (i2d_X509(cert, &cert_data) < 0)
|
||||
{
|
||||
IPIKE_FREEP(*payload);
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_create: failed to encode the certificate");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
#ifdef IPIKE_USE_VERSION2
|
||||
if ( IP_NULL != url )
|
||||
{
|
||||
Ip_u8 *message_digest;
|
||||
Ipike_value data;
|
||||
Ipike_error err;
|
||||
Ip_size_t url_len;
|
||||
|
||||
/* Length of URL including NULL termination */
|
||||
url_len = ipcom_strlen(url);
|
||||
IPCOM_LOG0(DEBUG2, "ipike_payload_certificate_create: Hash and URL enabled, sending hash of certificate");
|
||||
|
||||
/* Payload header + SHA1_HASH + url_base_len + NULL termination */
|
||||
payload_len = 5 + SHA_DIGEST_LENGTH + (int)url_len + SHA_DIGEST_LENGTH + SHA_DIGEST_LENGTH + 1;
|
||||
|
||||
message_digest = ipcom_malloc((Ip_size_t)payload_len);
|
||||
|
||||
if ( !message_digest )
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
data.value = ipike_payload_certificate_data(*payload);
|
||||
data.len = (Ip_size_t) cert_len;
|
||||
|
||||
if ( (err = ipike_crypto_sha_hash(&data, message_digest + 5)) != IPIKE_SUCCESS )
|
||||
{
|
||||
IPIKE_FREEP(*payload);
|
||||
ipcom_free(message_digest);
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_create: Failed to create SHA1 hash of the certificate");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Add URL base */
|
||||
memcpy(message_digest + 5 + SHA_DIGEST_LENGTH, url, url_len);
|
||||
|
||||
/* Add hex representation of certificate, this will add a NULL termination */
|
||||
ipike_bin2hex(message_digest + 5, SHA_DIGEST_LENGTH, (char *) message_digest + 5 + SHA_DIGEST_LENGTH + url_len);
|
||||
|
||||
ipcom_free(*payload);
|
||||
*payload = (Ipike_cert_payload *) message_digest;
|
||||
encoding = IPIKE_CERT_X509_HASH_AND_URL;
|
||||
}
|
||||
#else
|
||||
/* Send hash of certificate is only supported in IKEv2 */
|
||||
ip_assert(url == IP_NULL);
|
||||
#endif
|
||||
|
||||
(*payload)->header.length = (Ip_u16)ip_htons(payload_len);
|
||||
(*payload)->header.next_payload = IPIKE_PAYLOAD_CERTIFICATE;
|
||||
(*payload)->cert_encoding = (Ip_u8) encoding;
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_ocsp_create
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_ocsp_create(OCSP_RESPONSE* resp, Ipike_cert_payload** payload)
|
||||
{
|
||||
int resp_len;
|
||||
int payload_len;
|
||||
unsigned char* resp_data;
|
||||
|
||||
if (IP_NULL == resp)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_ocsp_create: no response specified, check configuration");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
resp_len = i2d_OCSP_RESPONSE(resp, IP_NULL);
|
||||
if (resp_len <= 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_ocsp_create: failed to determine the length of the response");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
payload_len = 5 + resp_len;
|
||||
if (IP_NULL == (*payload = ipcom_calloc(1, (Ip_size_t) payload_len)))
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
resp_data = (unsigned char*)ipike_payload_certificate_data(*payload);
|
||||
if (i2d_OCSP_RESPONSE(resp, &resp_data) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_ocsp_create: failed to encode the response");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
(*payload)->header.length = (Ip_u16) ip_htons(payload_len);
|
||||
(*payload)->header.next_payload = IPIKE_PAYLOAD_CERTIFICATE;
|
||||
(*payload)->cert_encoding = IPIKE_OCSP_CONTENT;
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* #ifdef IPIKE_USE_OCSP */
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_create
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_req_create_v1(
|
||||
Ipike_cert_req_payload** payload,
|
||||
X509* ca_cert)
|
||||
{
|
||||
Ip_size_t payload_len = 0;
|
||||
Ip_u8 *payload_data = IP_NULL;
|
||||
X509_NAME *x509_name = IP_NULL;
|
||||
int name_len = 0;
|
||||
|
||||
/* No trusted CA certificates => no certificate request payload */
|
||||
if ( !ca_cert )
|
||||
return IPIKE_SUCCESS;
|
||||
|
||||
/* Ignore non CA certificate */
|
||||
if ( !ipike_crypto_is_ca_certificate(ca_cert) )
|
||||
{
|
||||
IPCOM_LOG0(DEBUG2, "ipike_payload_certificate_req_create_v1() :: "\
|
||||
" skipping non-CA certificate");
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
x509_name = X509_get_subject_name(ca_cert);
|
||||
|
||||
/* Should not happen, skip this CA if it happens */
|
||||
if (!x509_name)
|
||||
return IPIKE_SUCCESS;
|
||||
|
||||
name_len = i2d_X509_NAME(x509_name, IP_NULL);
|
||||
|
||||
/* Should not happen, skip this CA if it happens */
|
||||
if ( name_len < 0 )
|
||||
return IPIKE_FAILED;
|
||||
|
||||
IPCOM_LOG0(DEBUG2, "ipike_payload_certificate_req_create_v1() :: "\
|
||||
" adding CA subject info into certificate request");
|
||||
|
||||
/* Calculate payload size */
|
||||
payload_len = (Ip_size_t)name_len + IPIKE_CERT_REQ_HEADER_LENGTH;
|
||||
|
||||
/* Allocate payload */
|
||||
if (IP_NULL == (*payload = ipcom_calloc(1, payload_len)))
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Get payload data pointer */
|
||||
payload_data = ipike_payload_certificate_req_data(*payload);
|
||||
|
||||
/* Encode to DER format into the payload data */
|
||||
name_len = i2d_X509_NAME(x509_name, &payload_data);
|
||||
|
||||
if ( name_len < 0 )
|
||||
{
|
||||
|
||||
IPCOM_LOG0(ERR, "ipike_payload_certificate_req_create_v1() :: "\
|
||||
" failed to decode CA subject name");
|
||||
ipcom_free(*payload);
|
||||
*payload = IP_NULL;
|
||||
|
||||
/* Skip this CA */
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set the rest of the payload fields */
|
||||
(*payload)->cert_encoding = IPIKE_CERT_X509_SIGNATURE;
|
||||
(*payload)->header.next_payload = IPIKE_PAYLOAD_CERTIFICATE_REQUEST;
|
||||
(*payload)->header.length = (Ip_u16) ip_htons(payload_len);
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef IPIKE_USE_VERSION2
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_create
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_req_create_v2(
|
||||
Ipike_cert_req_payload** payload,
|
||||
Ipike_cert *cert)
|
||||
{
|
||||
Ip_size_t payload_len = 0;
|
||||
Ipike_error err = IPIKE_SUCCESS;
|
||||
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
/* Request OCSP */
|
||||
if ( cert->resp_local != IP_NULL )
|
||||
{
|
||||
/* Only support CA signed OCSP responses*/
|
||||
payload_len = IPIKE_CERT_REQ_HEADER_LENGTH;
|
||||
|
||||
if (IP_NULL == (*payload = ipcom_calloc(1, payload_len)))
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
(*payload)->cert_encoding = IPIKE_OCSP_CONTENT;
|
||||
(*payload)->header.next_payload = IPIKE2_PAYLOAD_CERTIFICATE_REQUEST;
|
||||
(*payload)->header.length = (Ip_u16) ip_htons(payload_len);
|
||||
}
|
||||
else if ( cert->trusted )
|
||||
#endif
|
||||
{
|
||||
Ipike_value key_hashes;
|
||||
Ip_u32 num_cas;
|
||||
|
||||
memset(&key_hashes, 0, sizeof(key_hashes));
|
||||
IPCOM_LOG0(DEBUG2, "ipike_payload_certificate_req_create() :: adding public key hash to certificate request");
|
||||
|
||||
/* Get number of CAs we trust */
|
||||
num_cas = ipike_array_size((void **)cert->trusted);
|
||||
|
||||
/* Send a sha1 hash of the public key of the CAs we trust */
|
||||
payload_len = IPIKE_CERT_REQ_HEADER_LENGTH + (SHA_DIGEST_LENGTH * num_cas);
|
||||
|
||||
/* Allocate payload */
|
||||
if (IP_NULL == (*payload = ipcom_calloc(1, payload_len)))
|
||||
{
|
||||
IP_PANIC();
|
||||
return IPIKE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Get payload data pointer */
|
||||
key_hashes.value = ipike_payload_certificate_req_data(*payload);
|
||||
key_hashes.len = payload_len - IPIKE_CERT_REQ_HEADER_LENGTH;
|
||||
|
||||
/* Generate hashes */
|
||||
err = ipike_crypto_generate_public_key_hashes(cert->trusted, &key_hashes);
|
||||
|
||||
if ( IPIKE_SUCCESS != err )
|
||||
{
|
||||
IPCOM_LOG1(DEBUG2,
|
||||
"ipike_payload_certificate_req_create() :: failed to create hashes (%d)", err);
|
||||
|
||||
ipcom_free(*payload);
|
||||
return err;
|
||||
}
|
||||
|
||||
(*payload)->cert_encoding = IPIKE_CERT_X509_SIGNATURE;
|
||||
(*payload)->header.next_payload = IPIKE2_PAYLOAD_CERTIFICATE_REQUEST;
|
||||
(*payload)->header.length = (Ip_u16) ip_htons(payload_len);
|
||||
}
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* #ifdef IPIKE_USE_VERSION2 */
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_check
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_check(Ipike_cert_payload* cert)
|
||||
{
|
||||
switch (cert->cert_encoding)
|
||||
{
|
||||
case IPIKE_CERT_X509_SIGNATURE:
|
||||
return IPIKE_SUCCESS;
|
||||
#ifdef IPIKE_USE_VERSION2
|
||||
case IPIKE_CERT_X509_HASH_AND_URL:
|
||||
return IPIKE_SUCCESS;
|
||||
#endif
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
case IPIKE_OCSP_CONTENT:
|
||||
return IPIKE_SUCCESS;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
IPCOM_LOG2(ERR,
|
||||
"ipike_check_cert_payload: %s (%d) is a unsupported certificate encoding type",
|
||||
ipike_payload_certificate_encode_type_to_string(cert->cert_encoding), cert->cert_encoding);
|
||||
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_request_check
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_request_check(Ipike_cert_req_payload* req)
|
||||
{
|
||||
switch (req->cert_encoding)
|
||||
{
|
||||
case IPIKE_CERT_X509_SIGNATURE:
|
||||
return IPIKE_SUCCESS;
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
case IPIKE_OCSP_CONTENT:
|
||||
return IPIKE_SUCCESS;
|
||||
#endif
|
||||
case IPIKE_CERT_X509_HASH_AND_URL:
|
||||
return IPIKE_SUCCESS;
|
||||
/* Valid encodings but unsupported */
|
||||
case IPIKE_CERT_PKCS_7:
|
||||
case IPIKE_CERT_PGP:
|
||||
case IPIKE_CERT_SIGNED_KEY:
|
||||
case IPIKE_CERT_X509_KEY_EXCHANGE:
|
||||
case IPIKE_CERT_KERBEROS_TOKENS:
|
||||
case IPIKE_CERT_CRL:
|
||||
case IPIKE_CERT_ARL:
|
||||
case IPIKE_CERT_SPKI:
|
||||
case IPIKE_CERT_X509_ATTRIBUTE:
|
||||
IPCOM_LOG2(DEBUG2,
|
||||
"ipike_check_certreq_payload() :: unsupported certificate request encoding type %s (%d)",
|
||||
ipike_payload_certificate_encode_type_to_string(req->cert_encoding), req->cert_encoding);
|
||||
return IPIKE_ISAKMP_CERT_TYPE_UNSUPPORTED;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
IPCOM_LOG2(DEBUG2,
|
||||
"ipike_check_certreq_payload() :: invalid certificate request encoding type %s (%d)",
|
||||
ipike_payload_certificate_encode_type_to_string(req->cert_encoding), req->cert_encoding);
|
||||
|
||||
/* Ignored, until we support multiple certificates */
|
||||
return IPIKE_ISAKMP_INVALID_CERT_ENCODING;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_print
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipike_payload_certificate_print(Ipike_cert_payload* cert)
|
||||
{
|
||||
(void)ipike_payload_certificate_encode_type_to_string; /* lint */
|
||||
IPCOM_LOG1(DEBUG2, " encoding type: %s",
|
||||
ipike_payload_certificate_encode_type_to_string(cert->cert_encoding));
|
||||
(void)ipike_print_memory(IPCOM_LOG_DEBUG2, " value:\n",
|
||||
ipike_payload_certificate_data(cert),
|
||||
ipike_payload_certificate_data_length(cert));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_request_print
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipike_payload_certificate_request_print(Ipike_cert_req_payload* req)
|
||||
{
|
||||
/* Ignored until we support multiple certificates */
|
||||
IPCOM_LOG1(DEBUG2, " encoding type: %s",
|
||||
ipike_payload_certificate_encode_type_to_string(req->cert_encoding));
|
||||
|
||||
(void)ipike_print_memory(IPCOM_LOG_DEBUG2, " value:\n",
|
||||
ipike_payload_certificate_req_data(req),
|
||||
ipike_payload_certificate_req_data_length(req));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_extract
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_extract(
|
||||
Ipike_cert_payload* payload,
|
||||
Ipike_cert* cert)
|
||||
{
|
||||
Ipike_error err;
|
||||
Ip_u8* cert_data;
|
||||
X509* x509;
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
OCSP_RESPONSE* ocsp_resp;
|
||||
#endif
|
||||
|
||||
switch (payload->cert_encoding)
|
||||
{
|
||||
case IPIKE_CERT_X509_SIGNATURE:
|
||||
cert_data = ipike_payload_certificate_data(payload);
|
||||
x509 = d2i_X509(IP_NULL, (const unsigned char**)&cert_data, ipike_payload_certificate_data_length(payload));
|
||||
|
||||
if (IP_NULL == x509)
|
||||
{
|
||||
IPCOM_LOG1(CRIT,
|
||||
"ipike_payload_certificate_extract: failed to decode the certificate (type %s)",
|
||||
ipike_payload_certificate_encode_type_to_string(payload->cert_encoding));
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ipike_crypto_is_ca_certificate(x509))
|
||||
{
|
||||
if (IPIKE_SUCCESS != (err = ipike_array_add((void***)&cert->ca, x509)))
|
||||
{
|
||||
IPCOM_LOG0(CRIT, "ipike_payload_certificate_extract: Out of memory");
|
||||
X509_free(x509);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IP_NULL != cert->peer)
|
||||
X509_free(cert->peer);
|
||||
cert->peer = x509;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef IPIKE_USE_VERSION2
|
||||
case IPIKE_CERT_X509_HASH_AND_URL:
|
||||
{
|
||||
Ip_size_t cert_data_len;
|
||||
|
||||
if ( !ipike.use_hash_and_url )
|
||||
{
|
||||
IPCOM_LOG0(CRIT,
|
||||
"ipike_payload_certificate_extract: hash and url support not enabled");
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
cert_data = ipike_payload_certificate_data(payload);
|
||||
cert_data_len = ipike_payload_certificate_data_length(payload);
|
||||
|
||||
/* Expect a 20 byte SHA digest followed by an URL */
|
||||
if ( cert_data_len <= SHA_DIGEST_LENGTH )
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"ipike_cert_extract: Invalid length of \"Hash And URL\" data (type %d)",
|
||||
cert_data_len);
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
/* Verify that the URL is NULL terminated */
|
||||
if ( cert_data[cert_data_len - 1] != '\0' )
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipike_cert_extract: Invalid URL received in \"Hash And URL\" data") ;
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
cert->peer_url = ipcom_strdup( (char *) cert_data + SHA_DIGEST_LENGTH);
|
||||
cert->peer = IP_NULL;
|
||||
cert->ca = IP_NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
case IPIKE_OCSP_CONTENT:
|
||||
cert_data = (unsigned char*)ipike_payload_certificate_data(payload);
|
||||
ocsp_resp = d2i_OCSP_RESPONSE(IP_NULL, (const unsigned char**)&cert_data, ipike_payload_certificate_data_length(payload));
|
||||
|
||||
if (IP_NULL == ocsp_resp)
|
||||
{
|
||||
IPCOM_LOG1(CRIT,
|
||||
"ipike_payload_certificate_extract: failed to decode the ocsp_response (type %s)",
|
||||
ipike_payload_certificate_encode_type_to_string(payload->cert_encoding));
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IP_NULL != cert->resp_peer)
|
||||
OCSP_RESPONSE_free(cert->resp_peer);
|
||||
cert->resp_peer = ocsp_resp;
|
||||
}
|
||||
break;
|
||||
#endif /* IPIKE_USE_OCSP */
|
||||
|
||||
default:
|
||||
IPCOM_LOG1(CRIT,
|
||||
"ipike_payload_certificate_extract: %s not supported",
|
||||
ipike_payload_certificate_encode_type_to_string(payload->cert_encoding));
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_extract_v1
|
||||
*===========================================================================
|
||||
*/
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_req_extract_v1(
|
||||
Ipike_cert_req_payload *payload,
|
||||
Ipike_cert *cert)
|
||||
{
|
||||
Ip_u8 *payload_data = IP_NULL;
|
||||
Ip_size_t payload_len = 0;
|
||||
|
||||
payload_data = ipike_payload_certificate_req_data(payload);
|
||||
payload_len = ipike_payload_certificate_req_data_length(payload);
|
||||
|
||||
/* It's valid for a peer to send an empty certificate request payload.
|
||||
* See RFC4945 Section 3.2.7.2. */
|
||||
if ( payload_len == 0 )
|
||||
{
|
||||
IPCOM_LOG0(DEBUG2, "ipike_payload_certificate_req_extract_v1() ::"\
|
||||
" received empty certificate request payload");
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
switch (payload->cert_encoding)
|
||||
{
|
||||
case IPIKE_CERT_X509_SIGNATURE:
|
||||
{
|
||||
/* Get preferred CA certificate to use. This information could be used
|
||||
to separate tunnels by the CA certificate. This is not supported so
|
||||
just accept the presence of this payload for now. In IKEv1 this
|
||||
payload includes a DER encoded subject name of a CA which is
|
||||
trusted by the peer */
|
||||
X509_NAME *x509_name = IP_NULL;
|
||||
|
||||
x509_name = d2i_X509_NAME(IP_NULL,
|
||||
(const unsigned char **)&payload_data,
|
||||
(long)payload_len);
|
||||
|
||||
if ( !x509_name )
|
||||
{
|
||||
IPCOM_LOG0(ERR,
|
||||
"ipike_payload_certificate_req_extract_v1() ::"\
|
||||
" invalid CA format");
|
||||
return IPIKE_ISAKMP_INVALID_CERT_AUTHORITY;
|
||||
}
|
||||
|
||||
/* Find CA based on name, do nothing for now */
|
||||
IPCOM_UNUSED_ARG(cert);
|
||||
|
||||
X509_NAME_free(x509_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
IPCOM_LOG1(CRIT,
|
||||
"ipike_payload_certificate_req_extract: %s encoding not supported",
|
||||
ipike_payload_certificate_encode_type_to_string(payload->cert_encoding));
|
||||
return IPIKE_ISAKMP_INVALID_CERT_ENCODING;
|
||||
}
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipike_payload_certificate_req_extract_v2
|
||||
*===========================================================================
|
||||
*/
|
||||
#ifdef IPIKE_USE_OCSP
|
||||
IP_GLOBAL Ipike_error
|
||||
ipike_payload_certificate_req_extract_v2(
|
||||
Ipike_cert_req_payload* payload,
|
||||
Ip_bool* ocsp_resp_flag)
|
||||
{
|
||||
*ocsp_resp_flag = IP_FALSE;
|
||||
|
||||
switch (payload->cert_encoding)
|
||||
{
|
||||
case IPIKE_OCSP_CONTENT:
|
||||
IPCOM_LOG0(DEBUG2,
|
||||
"ipike_payload_certificate_req_extract: Received OCSP request");
|
||||
if (payload->header.length > 5)
|
||||
{
|
||||
/* Extract Responder public key SHA1 hashes */
|
||||
#if 0
|
||||
unsigned char *cert_data;
|
||||
|
||||
cert_data = (unsigned char*)ipike_payload_certificate_req_data(payload);
|
||||
#endif
|
||||
/*!!OCSP TODO: match hashes against OCSP response store
|
||||
to select one of the many. Currently only OCSP
|
||||
responses signed by CA can be configured */
|
||||
IPCOM_LOG0(DEBUG2,
|
||||
"ipike_payload_certificate_req_extract: Ignoring SHA1 hashes in OCSP content");
|
||||
|
||||
IPCOM_LOG0(DEBUG2,
|
||||
"ipike_payload_certificate_req_extract: Only support CA signed OCSP responses");
|
||||
}
|
||||
*ocsp_resp_flag = IP_TRUE;
|
||||
break;
|
||||
|
||||
case IPIKE_CERT_X509_SIGNATURE:
|
||||
/* Get preferred CA certificate to use. This information could be used
|
||||
to separate tunnels by the CA certificate. This is not supported so
|
||||
just accept the presence of this payload for now. */
|
||||
break;
|
||||
|
||||
default:
|
||||
IPCOM_LOG1(CRIT,
|
||||
"ipike_payload_certificate_req_extract: %s encoding not supported",
|
||||
ipike_payload_certificate_encode_type_to_string(payload->cert_encoding));
|
||||
return IPIKE_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return IPIKE_SUCCESS;
|
||||
}
|
||||
#endif /* #ifdef IPIKE_USE_OCSP */
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
Reference in New Issue
Block a user