#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <Security/debugging.h>
#include <Security/cssmerr.h>
#include "opensslUtils.h"
#include <AppleCSP/YarrowConnection.h>
#include <AppleCSP/AppleCSPUtils.h>
#include <Security/logging.h>
#define sslUtilsDebug(args...) debug("sslUtils", ## args)
openSslException::openSslException(
int irtn,
const char *op)
: mIrtn(irtn)
{
if(op) {
char buf[300];
ERR_error_string(irtn, buf);
sslUtilsDebug("%s: %s\n", op, buf);
}
}
#define DUMP_RAND_BYTES 0
static int randDex = 1;
int RAND_bytes(unsigned char *buf,int num)
{
try {
cspGetRandomBytes(buf, (unsigned)num);
}
catch(...) {
Security::Syslog::error("Apple CSP: yarrow failure");
for(int i=0; i<num; i++) {
buf[i] = (i*3) + randDex++;
}
}
return 1;
}
int RAND_pseudo_bytes(unsigned char *buf,int num)
{
return RAND_bytes(buf, num);
}
void RAND_add(const void *buf,int num,double entropy)
{
try {
cspAddEntropy(buf, (unsigned)num);
}
catch(...) {
}
}
int CRYPTO_mem_ctrl(int mode)
{
return 0;
}
unsigned long logSslErrInfo(const char *op)
{
unsigned long e = ERR_get_error();
char outbuf[1024];
ERR_error_string(e, outbuf);
if(op) {
Security::Syslog::error("Apple CSP %s: %s", op, outbuf);
}
else {
Security::Syslog::error("Apple CSP %s", outbuf);
}
return e;
}
unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md)
{
if(md == NULL) {
sslUtilsDebug("SHA1 with NULL md");
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}
cspGenSha1Hash(d, n, md);
return md;
}
void throwRsaDsa(
const char *op)
{
unsigned long e = logSslErrInfo(op);
CSSM_RETURN cerr = CSSM_OK;
int reason = ERR_GET_REASON(e);
int lib = ERR_GET_LIB(e);
switch(reason) {
case ERR_R_MALLOC_FAILURE:
cerr = CSSMERR_CSP_MEMORY_ERROR; break;
case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
break;
case ERR_R_PASSED_NULL_PARAMETER:
cerr = CSSMERR_CSP_INVALID_POINTER; break;
case ERR_R_NESTED_ASN1_ERROR:
case ERR_R_BAD_ASN1_OBJECT_HEADER:
case ERR_R_BAD_GET_ASN1_OBJECT_CALL:
case ERR_R_EXPECTING_AN_ASN1_SEQUENCE:
case ERR_R_ASN1_LENGTH_MISMATCH:
case ERR_R_MISSING_ASN1_EOS:
cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
default:
break;
}
if(cerr != CSSM_OK) {
CssmError::throwMe(cerr);
}
switch(lib) {
case ERR_R_BN_LIB:
cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
case ERR_R_RSA_LIB:
switch(reason) {
case RSA_R_ALGORITHM_MISMATCH:
cerr = CSSMERR_CSP_ALGID_MISMATCH; break;
case RSA_R_BAD_SIGNATURE:
cerr = CSSMERR_CSP_VERIFY_FAILED; break;
case RSA_R_DATA_TOO_LARGE:
case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
case RSA_R_DATA_TOO_SMALL:
case RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:
case RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY:
cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
case RSA_R_KEY_SIZE_TOO_SMALL:
cerr = CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH; break;
case RSA_R_PADDING_CHECK_FAILED:
cerr = CSSMERR_CSP_INVALID_DATA; break;
case RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:
cerr = CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED; break;
case RSA_R_UNKNOWN_ALGORITHM_TYPE:
cerr = CSSMERR_CSP_INVALID_ALGORITHM; break;
case RSA_R_WRONG_SIGNATURE_LENGTH:
cerr = CSSMERR_CSP_VERIFY_FAILED; break;
default:
cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
}
break;
case ERR_R_DSA_LIB:
switch(reason) {
case DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
default:
cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
}
break;
case ERR_R_DH_LIB:
cerr = CSSMERR_CSP_INTERNAL_ERROR;
break;
default:
cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
}
CssmError::throwMe(cerr);
}
void throwOpensslErr(int irtn)
{
CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
}