generalop.c revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright(c) 1995-2000 Intel Corporation. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <thread.h>
#include <ber_der.h>
#include <kmfapiP.h>
#include <pem_encode.h>
#include <rdn_parser.h>
#include <libgen.h>
#include <cryptoutil.h>
static uchar_t pkcs11_initialized = 0;
extern int errno;
typedef struct {
char *message;
static kmf_error_map kmf_errcodes[] = {
{KMF_OK, "KMF_OK"},
{KMF_ERR_BAD_PARAMETER, "KMF_ERR_BAD_PARAMETER"},
{KMF_ERR_BAD_KEY_FORMAT, "KMF_ERR_BAD_KEY_FORMAT"},
{KMF_ERR_BAD_ALGORITHM, "KMF_ERR_BAD_ALGORITHM"},
{KMF_ERR_MEMORY, "KMF_ERR_MEMORY"},
{KMF_ERR_ENCODING, "KMF_ERR_ENCODING"},
{KMF_ERR_PLUGIN_INIT, "KMF_ERR_PLUGIN_INIT"},
{KMF_ERR_PLUGIN_NOTFOUND, "KMF_ERR_PLUGIN_NOTFOUND"},
{KMF_ERR_INTERNAL, "KMF_ERR_INTERNAL"},
{KMF_ERR_BAD_CERT_FORMAT, "KMF_ERR_BAD_CERT_FORMAT"},
{KMF_ERR_KEYGEN_FAILED, "KMF_ERR_KEYGEN_FAILED"},
{KMF_ERR_UNINITIALIZED, "KMF_ERR_UNINITIALIZED"},
{KMF_ERR_ISSUER, "KMF_ERR_ISSUER"},
{KMF_ERR_NOT_REVOKED, "KMF_ERR_NOT_REVOKED"},
{KMF_ERR_CERT_NOT_FOUND, "KMF_ERR_CERT_NOT_FOUND"},
{KMF_ERR_CRL_NOT_FOUND, "KMF_ERR_CRL_NOT_FOUND"},
{KMF_ERR_RDN_PARSER, "KMF_ERR_RDN_PARSER"},
{KMF_ERR_RDN_ATTR, "KMF_ERR_RDN_ATTR"},
{KMF_ERR_SLOTNAME, "KMF_ERR_SLOTNAME"},
{KMF_ERR_EMPTY_CRL, "KMF_ERR_EMPTY_CRL"},
{KMF_ERR_BUFFER_SIZE, "KMF_ERR_BUFFER_SIZE"},
{KMF_ERR_AUTH_FAILED, "KMF_ERR_AUTH_FAILED"},
{KMF_ERR_TOKEN_SELECTED, "KMF_ERR_TOKEN_SELECTED"},
{KMF_ERR_NO_TOKEN_SELECTED, "KMF_ERR_NO_TOKEN_SELECTED"},
{KMF_ERR_TOKEN_NOT_PRESENT, "KMF_ERR_TOKEN_NOT_PRESENT"},
{KMF_ERR_EXTENSION_NOT_FOUND, "KMF_ERR_EXTENSION_NOT_FOUND"},
{KMF_ERR_POLICY_ENGINE, "KMF_ERR_POLICY_ENGINE"},
{KMF_ERR_POLICY_DB_FORMAT, "KMF_ERR_POLICY_DB_FORMAT"},
{KMF_ERR_POLICY_NOT_FOUND, "KMF_ERR_POLICY_NOT_FOUND"},
{KMF_ERR_POLICY_DB_FILE, "KMF_ERR_POLICY_DB_FILE"},
{KMF_ERR_POLICY_NAME, "KMF_ERR_POLICY_NAME"},
{KMF_ERR_OCSP_POLICY, "KMF_ERR_OCSP_POLICY"},
{KMF_ERR_TA_POLICY, "KMF_ERR_TA_POLICY"},
{KMF_ERR_KEY_NOT_FOUND, "KMF_ERR_KEY_NOT_FOUND"},
{KMF_ERR_OPEN_FILE, "KMF_ERR_OPEN_FILE"},
{KMF_ERR_OCSP_BAD_ISSUER, "KMF_ERR_OCSP_BAD_ISSUER"},
{KMF_ERR_OCSP_BAD_CERT, "KMF_ERR_OCSP_BAD_CERT"},
{KMF_ERR_OCSP_CREATE_REQUEST, "KMF_ERR_OCSP_CREATE_REQUEST"},
{KMF_ERR_CONNECT_SERVER, "KMF_ERR_CONNECT_SERVER"},
{KMF_ERR_SEND_REQUEST, "KMF_ERR_SEND_REQUEST"},
{KMF_ERR_OCSP_CERTID, "KMF_ERR_OCSP_CERTID"},
{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
{KMF_ERR_OCSP_RESPONSE_STATUS, "KMF_ERR_OCSP_RESPONSE_STATUS"},
{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
{KMF_ERR_OCSP_BAD_SIGNER, "KMF_ERR_OCSP_BAD_SIGNER"},
{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
{KMF_ERR_OCSP_UNKNOWN_CERT, "KMF_ERR_OCSP_UNKNOWN_CERT"},
{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
{KMF_ERR_BAD_HTTP_RESPONSE, "KMF_ERR_BAD_HTTP_RESPONSE"},
{KMF_ERR_RECV_RESPONSE, "KMF_ERR_RECV_RESPONSE"},
{KMF_ERR_RECV_TIMEOUT, "KMF_ERR_RECV_TIMEOUT"},
{KMF_ERR_DUPLICATE_KEYFILE, "KMF_ERR_DUPLICATE_KEYFILE"},
{KMF_ERR_AMBIGUOUS_PATHNAME, "KMF_ERR_AMBIGUOUS_PATHNAME"},
{KMF_ERR_FUNCTION_NOT_FOUND, "KMF_ERR_FUNCTION_NOT_FOUND"},
{KMF_ERR_PKCS12_FORMAT, "KMF_ERR_PKCS12_FORMAT"},
{KMF_ERR_BAD_KEY_TYPE, "KMF_ERR_BAD_KEY_TYPE"},
{KMF_ERR_BAD_KEY_CLASS, "KMF_ERR_BAD_KEY_CLASS"},
{KMF_ERR_BAD_KEY_SIZE, "KMF_ERR_BAD_KEY_SIZE"},
{KMF_ERR_BAD_HEX_STRING, "KMF_ERR_BAD_HEX_STRING"},
{KMF_ERR_KEYUSAGE, "KMF_ERR_KEYUSAGE"},
{KMF_ERR_VALIDITY_PERIOD, "KMF_ERR_VALIDITY_PERIOD"},
{KMF_ERR_OCSP_REVOKED, "KMF_ERR_OCSP_REVOKED"},
{KMF_ERR_CERT_MULTIPLE_FOUND, "KMF_ERR_CERT_MULTIPLE_FOUND"},
{KMF_ERR_WRITE_FILE, "KMF_ERR_WRITE_FILE"},
{KMF_ERR_BAD_URI, "KMF_ERR_BAD_URI"},
{KMF_ERR_BAD_CRLFILE, "KMF_ERR_BAD_CRLFILE"},
{KMF_ERR_BAD_CERTFILE, "KMF_ERR_BAD_CERTFILE"},
{KMF_ERR_GETKEYVALUE_FAILED, "KMF_ERR_GETKEYVALUE_FAILED"},
{KMF_ERR_BAD_KEYHANDLE, "KMF_ERR_BAD_KEYHANDLE"},
{KMF_ERR_BAD_OBJECT_TYPE, "KMF_ERR_BAD_OBJECT_TYPE"},
{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE, "KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
{KMF_ERR_UNINITIALIZED_TOKEN, "KMF_ERR_UNINITIALIZED_TOKEN"},
{KMF_ERR_INCOMPLETE_TBS_CERT, "KMF_ERR_INCOMPLETE_TBS_CERT"},
{KMF_ERR_MISSING_ERRCODE, "KMF_ERR_MISSING_ERRCODE"},
{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"}
};
int
{
return (pkcs11_initialized);
}
/*
* Private method for searching the plugin list for the correct
* Plugin to use.
*/
{
return (NULL);
/* If it is NULL, that is indication enough of an error */
}
static KMF_RETURN
{
KMF_PLUGIN *p = NULL;
KMF_PLUGIN_FUNCLIST *(*sym)();
return (KMF_ERR_BAD_PARAMETER);
if (p == NULL)
return (KMF_ERR_MEMORY);
free(p);
return (KMF_ERR_MEMORY);
}
free(p);
return (KMF_ERR_PLUGIN_INIT);
}
free(p);
return (KMF_ERR_PLUGIN_INIT);
}
/* Get the function list */
free(p);
return (KMF_ERR_PLUGIN_INIT);
}
*plugin = p;
return (KMF_OK);
}
static KMF_RETURN
{
KMF_PLUGIN_LIST *n;
return (KMF_ERR_BAD_PARAMETER);
/* If the head is NULL, create it */
sizeof (KMF_PLUGIN_LIST));
return (KMF_ERR_MEMORY);
} else {
/* walk the list to find the tail */
n = n->next;
return (KMF_ERR_MEMORY);
}
return (0);
}
static void
{
if (plugin) {
}
}
static void
{
}
}
}
void
{
/* Close active session on a pkcs11 token */
}
}
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
(void) mutex_lock(&init_lock);
if (!pkcs11_initialized) {
(rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
(void) mutex_unlock(&init_lock);
goto errout;
} else {
pkcs11_initialized = 1;
}
}
(void) mutex_unlock(&init_lock);
/* Initialize the handle with the policy */
goto errout;
/* Create a record for the plugin */
goto errout;
/* Add it to the handle */
goto errout;
}
goto errout;
/* Add it to the handle */
goto errout;
goto errout;
/* Add it to the handle */
goto errout;
}
return (ret);
}
{
return (ret);
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_PLUGIN_NOTFOUND);
else
/* return KMF_OK, if the plugin does not have an entry */
return (KMF_OK);
}
{
return (ret);
if (pkcs11_initialized) {
}
return (ret);
}
{
int i, maxerr;
return (KMF_ERR_BAD_PARAMETER);
if (i == maxerr)
return (KMF_ERR_MISSING_ERRCODE);
else {
return (KMF_ERR_MEMORY);
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MISSING_ERRCODE);
}
return (KMF_ERR_MEMORY);
}
return (KMF_OK);
}
return (KMF_ERR_PLUGIN_NOTFOUND);
} else {
return (KMF_ERR_FUNCTION_NOT_FOUND);
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (err);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (rv);
}
{
struct stat s;
int fd;
return (ret);
return (KMF_ERR_BAD_PARAMETER);
}
return (KMF_ERR_OPEN_FILE);
}
return (KMF_ERR_OPEN_FILE);
}
return (KMF_ERR_MEMORY);
}
do {
if (nread < 0) {
return (KMF_ERR_INTERNAL);
}
return (KMF_OK);
}
/*
*
* Name: KMF_Der2Pem
*
* Description:
* Function for converting DER encoded format to PEM encoded format
*
* Parameters:
* type(input) - CERTIFICATE or CSR
* data(input) - pointer to the DER encoded data
* len(input) - length of input data
* out(output) - contains the output buffer address to be returned
* outlen(output) - pointer to the returned output length
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
{
return (KMF_ERR_BAD_PARAMETER);
return (err);
}
/*
*
* Name: KMF_Pem2Der
*
* Description:
* Function for converting PEM encoded format to DER encoded format
*
* Parameters:
* in(input) - pointer to the PEM encoded data
* inlen(input) - length of input data
* out(output) - contains the output buffer address to be returned
* outlen(output) - pointer to the returned output length
*
* Returns:
* A KMF_RETURN value indicating success or specifying a particular
* error condition.
* The value KMF_OK indicates success. All other values represent
* an error condition.
*
*/
{
return (KMF_ERR_BAD_PARAMETER);
return (err);
}
char *
{
char numstr[128];
int numshift;
char *bp;
/* First determine the size of the string */
string_length = 0;
number = 0;
numshift = 0;
numshift += 7;
} else {
return (NULL);
}
if ((cp[i] & 0x80) == 0) {
number = 0;
numshift = 0;
}
}
/*
* If we get here, we've calculated the length of "n n n ... n ". Add 4
* here for "{ " and "}\0".
*/
string_length += 4;
number = 0;
if ((cp[i] & 0x80) == 0) {
number = 0;
}
}
}
return (bp);
}
{
int f;
return (KMF_ERR_BAD_PARAMETER);
*fmt = 0;
return (KMF_ERR_OPEN_FILE);
}
goto end;
}
*fmt = KMF_FORMAT_PEM;
*fmt = KMF_FORMAT_PKCS12;
*fmt = KMF_FORMAT_PKCS12;
/* It is most likely a generic ASN.1 encoded file */
} else {
*fmt = KMF_FORMAT_ASN1;
}
} else {
/* Cannot determine this file format */
*fmt = 0;
}
end:
(void) close(f);
return (ret);
}
{
int i;
unsigned char ch;
return (KMF_ERR_BAD_PARAMETER);
}
if (hexstr[0] == '0' &&
hexstr += 2;
/*
* If all the characters are not legitimate hex chars,
* return an error.
*/
return (KMF_ERR_BAD_HEX_STRING);
stringlen = i;
return (KMF_ERR_MEMORY);
}
for (i = 0; i < stringlen; i++) {
hexstr++;
ch -= '0';
else {
goto out;
}
if (i & 1) {
} else {
}
}
out:
}
return (ret);
}
void
{
int i, j;
for (i = 0; i < name->numberOfRDNs; i++) {
for (j = 0; j < newrdn->numberOfPairs; j++) {
}
newrdn->numberOfPairs = 0;
}
name->numberOfRDNs = 0;
}
}
void
{
return;
return;
}
}
void
{
}
}
void
{
return;
}
void
{
return;
}
}
void
{
if (tbscsr) {
}
}
void
{
if (csr) {
}
}
static void
{
return;
}
static void
{
int i;
for (i = 0; i < extns->numberOfExtensions; i++) {
}
extns->numberOfExtensions = 0;
}
}
void
{
if (tbscert) {
}
}
void
{
if (!certptr)
return;
}
void
KMF_FreeString(char *pstr)
{
}
void
{
int i;
for (i = 0; i < len; i++) {
}
}
void
{
}
void
{
}
}
void
{
return;
return;
}
return;
}
}
void
{
}
}
static void
{
return;
}
static void
{
return;
}
static void
{
return;
}
void
{
return;
case KMF_RSA:
break;
case KMF_DSA:
break;
case KMF_AES:
case KMF_RC4:
case KMF_DES:
case KMF_DES3:
break;
}
}
void
{
return;
}
/*
* This function frees the space allocated for the name portion of a
* KMF_CRL_DIST_POINT.
*/
void
{
int i;
return;
/* For phase 1, we only need to free the fullname space. */
return;
}
}
/*
* This function frees the space allocated for a KMF_CRL_DIST_POINT.
*/
void
{
return;
/* Need not to free crl_issuer space at phase 1 */
}
/*
* This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
*/
void
{
int i;
return;
}
char *reqfile)
{
char *reqfile);
return (ret);
return (KMF_ERR_BAD_PARAMETER);
/*
* This framework function is actually implemented in the openssl
* plugin library, so we find the function address and call it.
*/
return (KMF_ERR_PLUGIN_NOTFOUND);
}
"OpenSSL_CreateOCSPRequest");
if (createReqFn == NULL) {
return (KMF_ERR_FUNCTION_NOT_FOUND);
}
}
{
KMF_RETURN (*getCertStatusFn)(void *,
return (ret);
params_out == NULL)
return (KMF_ERR_BAD_PARAMETER);
/*
* This framework function is actually implemented in the openssl
* plugin library, so we find the function address and call it.
*/
return (KMF_ERR_INTERNAL);
}
"OpenSSL_GetOCSPStatusForCert");
if (getCertStatusFn == NULL) {
return (KMF_ERR_INTERNAL);
}
}
{
int numbuf;
int onumbuf;
int len;
unsigned char *op;
return (KMF_ERR_BAD_PARAMETER);
/* Skip over leading space */
bp++;
nbytes = 0;
/*
* The first two numbers are chewed up by the first octet.
*/
return (KMF_ERR_BAD_PARAMETER);
bp++;
bp++;
return (KMF_ERR_BAD_PARAMETER);
bp++;
bp++;
nbytes++;
return (KMF_ERR_BAD_PARAMETER);
while (numbuf) {
nbytes++;
numbuf >>= 7;
}
bp++;
bp++;
}
return (KMF_ERR_MEMORY);
}
op++;
nbytes = 0;
/* Have to fill in the bytes msb-first */
while (numbuf) {
nbytes++;
numbuf >>= 7;
}
index = -1;
while (numbuf) {
if (index != -1)
index--;
numbuf >>= 7;
}
}
return (rv);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (rv);
}
static KMF_RETURN
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_ENCODING);
} else {
}
return (KMF_ERR_MEMORY);
return (rv);
}
static KMF_RETURN
verify_uri_format(char *uristring)
{
/* Parse the URI string; get the hostname and port */
goto out;
}
goto out;
}
goto out;
}
out:
return (ret);
}
static KMF_RETURN
encode_altname(char *namedata,
{
return (KMF_ERR_BAD_PARAMETER);
/*
* Encode the namedata according to rules in RFC 3280 for GeneralName.
* The input "namedata" is assumed to be an ASCII string representation
* of the AltName, we need to convert it to correct ASN.1 here before
* adding it to the cert.
*/
switch (nametype) {
case GENNAME_RFC822NAME: /* rfc 822 */
/* IA5String, no encoding needed */
return (KMF_ERR_MEMORY);
break;
case GENNAME_DNSNAME: /* rfc 1034 */
return (KMF_ERR_MEMORY);
break;
case GENNAME_URI: /* rfc 1738 */
return (ret);
/* IA5String, no encoding needed */
return (KMF_ERR_MEMORY);
break;
case GENNAME_IPADDRESS:
break;
case GENNAME_REGISTEREDID:
break;
case GENNAME_DIRECTORYNAME:
}
(void) KMF_FreeDN(&dnname);
break;
default:
/* unsupported */
return (KMF_ERR_BAD_PARAMETER);
}
return (ret);
}
return (KMF_ERR_MEMORY);
goto cleanup;
goto cleanup;
}
goto cleanup;
}
if (asn1)
return (ret);
}
{
int i;
return (NULL);
for (i = 0; i < exts->numberOfExtensions; i++) {
break;
}
}
return (foundextn);
}
{
int tag;
return (KMF_ERR_BAD_PARAMETER);
/*
* Decode the sequence of general names
*/
goto out;
}
/*
* Unwrap the sequence to find the size of the block
* of GeneralName items in the set.
*
* Peek at the tag and length ("tl"),
* then consume them ("{").
*/
oldsize == 0) {
goto out;
}
goto out;
}
/*
* Read the entire blob of GeneralNames, we don't
* need to interpret them now.
*/
goto out;
}
out:
*outlen = 0;
} else {
}
return (ret);
}
{
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
sizeof (KMF_X509_EXTENSION));
return (ret);
}
int critical,
char *namedata)
{
return (KMF_ERR_BAD_PARAMETER);
return (ret);
goto out;
/*
* Check to see if this cert already has a subjectAltName.
*/
goto out;
}
/*
* Assume (!!) that the namedata given is already properly encoded.
*/
return (KMF_ERR_MEMORY);
goto out;
}
/* Write the old extension data first */
goto out;
}
}
/* Now add the new name to the list */
goto out;
}
/* Now close the sequence */
goto out;
}
goto out;
}
/*
* If we are just adding to an existing list of altNames,
* just replace the BER data associated with the found extension.
*/
} else {
}
out:
return (ret);
}