1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * opensslUtils.h - Support for ssleay-derived crypto modules
21 */
22
23#include <openssl/rand.h>
24#include <openssl/crypto.h>
25#include <openssl/err.h>
26#include <openssl/sha.h>
27#include <openssl/rsa.h>
28#include <openssl/dsa.h>
29#include <openssl/dh.h>
30#include <openssl/err.h>
31#include <security_utilities/debugging.h>
32#include <Security/cssmerr.h>
33#include "opensslUtils.h"
34#include <YarrowConnection.h>
35#include <AppleCSPUtils.h>
36#include <security_utilities/logging.h>
37
38#define sslUtilsDebug(args...)	secdebug("sslUtils", ## args)
39
40openSslException::openSslException(
41	int irtn,
42	const char *op)
43		: mIrtn(irtn)
44{
45	if(op) {
46		char buf[300];
47		ERR_error_string(irtn, buf);
48		sslUtilsDebug("%s: %s\n", op, buf);
49	}
50}
51
52/* these are replacements for the ones in ssleay */
53#define DUMP_RAND_BYTES	0
54
55static int randDex = 1;
56
57int  RAND_bytes(unsigned char *buf,int num)
58{
59	try {
60		cspGetRandomBytes(buf, (unsigned)num);
61	}
62	catch(...) {
63		/* that can only mean Yarrow failure, which we really need to
64		 * cut some slack for */
65		Security::Syslog::error("Apple CSP: yarrow failure");
66		for(int i=0; i<num; i++) {
67			buf[i] = (i*3) + randDex++;
68		}
69	}
70	return 1;
71}
72
73int  RAND_pseudo_bytes(unsigned char *buf,int num)
74{
75	return RAND_bytes(buf, num);
76}
77
78void RAND_add(const void *buf,int num,double entropy)
79{
80	try {
81		cspAddEntropy(buf, (unsigned)num);
82	}
83	catch(...) {
84	}
85}
86
87/* replacement for mem_dbg.c */
88int CRYPTO_mem_ctrl(int mode)
89{
90	return 0;
91}
92
93/* Clear openssl error stack. */
94void clearOpensslErrors()
95{
96	while(ERR_get_error())
97		;
98}
99
100/*
101 * Log error info. Returns the error code we pop off the error queue.
102 */
103unsigned long logSslErrInfo(const char *op)
104{
105	unsigned long e = ERR_get_error();
106
107	/* flush out subsequent errors; we only want the first one */
108	clearOpensslErrors();
109
110	char outbuf[1024];
111	ERR_error_string(e, outbuf);
112	if(op) {
113		Security::Syslog::error("Apple CSP %s: %s", op, outbuf);
114	}
115	else {
116		Security::Syslog::error("Apple CSP %s", outbuf);
117	}
118	return e;
119}
120
121/*
122 * Replacement for same function in openssl's sha.c, which we don't link against.
123 * The only place this is used is in DSA_generate_parameters().
124 */
125unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md)
126{
127	if(md == NULL) {
128		sslUtilsDebug("SHA1 with NULL md");
129		CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
130	}
131	cspGenSha1Hash(d, n, md);
132	return md;
133}
134
135void throwRsaDsa(
136	const char *op)
137{
138	unsigned long e = logSslErrInfo(op);
139	CSSM_RETURN cerr = CSSM_OK;
140
141	/* try to parse into something meaningful */
142	int reason = ERR_GET_REASON(e);
143	int lib = ERR_GET_LIB(e);
144
145	/* first try the global ones */
146	switch(reason) {
147		case ERR_R_MALLOC_FAILURE:
148			cerr = CSSMERR_CSP_MEMORY_ERROR; break;
149		case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
150			/* internal */ break;
151		case ERR_R_PASSED_NULL_PARAMETER:
152			cerr = CSSMERR_CSP_INVALID_POINTER; break;
153		case ERR_R_NESTED_ASN1_ERROR:
154		case ERR_R_BAD_ASN1_OBJECT_HEADER:
155		case ERR_R_BAD_GET_ASN1_OBJECT_CALL:
156		case ERR_R_EXPECTING_AN_ASN1_SEQUENCE:
157		case ERR_R_ASN1_LENGTH_MISMATCH:
158		case ERR_R_MISSING_ASN1_EOS:
159			/* ASN - shouldn't happen, right? */
160			cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
161		default:
162			break;
163	}
164	if(cerr != CSSM_OK) {
165		CssmError::throwMe(cerr);
166	}
167
168	/* now the lib-specific ones */
169	switch(lib) {
170		case ERR_R_BN_LIB:
171			/* all indicate serious internal error...right? */
172			cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
173		case ERR_R_RSA_LIB:
174			switch(reason) {
175				case RSA_R_ALGORITHM_MISMATCH:
176					cerr = CSSMERR_CSP_ALGID_MISMATCH; break;
177				case RSA_R_BAD_SIGNATURE:
178					cerr = CSSMERR_CSP_VERIFY_FAILED; break;
179				case RSA_R_DATA_TOO_LARGE:
180				case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
181				case RSA_R_DATA_TOO_SMALL:
182				case RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:
183				case RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY:
184					cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
185				case RSA_R_KEY_SIZE_TOO_SMALL:
186					cerr = CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH; break;
187				case RSA_R_PADDING_CHECK_FAILED:
188				case RSA_R_BLOCK_TYPE_IS_NOT_01:
189				case RSA_R_BLOCK_TYPE_IS_NOT_02:
190				case RSA_R_DATA_GREATER_THAN_MOD_LEN:
191				case RSA_R_BAD_PAD_BYTE_COUNT:
192					cerr = CSSMERR_CSP_INVALID_DATA; break;
193				case RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:
194					cerr = CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED; break;
195				case RSA_R_UNKNOWN_ALGORITHM_TYPE:
196					cerr = CSSMERR_CSP_INVALID_ALGORITHM; break;
197				case RSA_R_WRONG_SIGNATURE_LENGTH:
198					cerr = CSSMERR_CSP_VERIFY_FAILED; break;
199				case RSA_R_SSLV3_ROLLBACK_ATTACK:
200					cerr = CSSMERR_CSP_APPLE_SSLv2_ROLLBACK; break;
201				default:
202					cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
203			}
204			break;
205		case ERR_R_DSA_LIB:
206			switch(reason) {
207				case DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
208					cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
209				default:
210					cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
211			}
212			break;
213		case ERR_R_DH_LIB:
214			/* actually none of the DH errors make sense at the CDSA level */
215			cerr = CSSMERR_CSP_INTERNAL_ERROR;
216			break;
217		default:
218			cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
219	}
220	CssmError::throwMe(cerr);
221}
222
223/*
224 * given an openssl-style error, throw appropriate CssmError.
225 */
226void throwOpensslErr(int irtn)
227{
228	/* FIXME */
229	CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
230}
231
232